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 (target->type() != Code::NORMAL) { | |
danno
2013/04/24 15:23:00
Can you please add a comment here why this compare
Toon Verwaest
2013/04/25 10:59:38
Done.
| |
186 Map* map = target->FindFirstMap(); | |
187 if (map != NULL && map->is_invalid_transition()) { | |
188 return true; | |
189 } | |
190 } | |
191 | |
185 InlineCacheHolderFlag cache_holder = | 192 InlineCacheHolderFlag cache_holder = |
186 Code::ExtractCacheHolderFromFlags(target->flags()); | 193 Code::ExtractCacheHolderFromFlags(target->flags()); |
187 | 194 |
188 Isolate* isolate = target->GetIsolate(); | 195 Isolate* isolate = target->GetIsolate(); |
189 if (cache_holder == OWN_MAP && !receiver->IsJSObject()) { | 196 if (cache_holder == OWN_MAP && !receiver->IsJSObject()) { |
190 // The stub was generated for JSObject but called for non-JSObject. | 197 // The stub was generated for JSObject but called for non-JSObject. |
191 // IC::GetCodeCacheHolder is not applicable. | 198 // IC::GetCodeCacheHolder is not applicable. |
192 return false; | 199 return false; |
193 } else if (cache_holder == PROTOTYPE_MAP && | 200 } else if (cache_holder == PROTOTYPE_MAP && |
194 receiver->GetPrototype(isolate)->IsNull()) { | 201 receiver->GetPrototype(isolate)->IsNull()) { |
(...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
498 int index = frame->ComputeExpressionsCount() - (argc + 1); | 505 int index = frame->ComputeExpressionsCount() - (argc + 1); |
499 frame->SetExpression(index, *isolate()->factory()->ToObject(object)); | 506 frame->SetExpression(index, *isolate()->factory()->ToObject(object)); |
500 } | 507 } |
501 } | 508 } |
502 | 509 |
503 | 510 |
504 MaybeObject* CallICBase::LoadFunction(State state, | 511 MaybeObject* CallICBase::LoadFunction(State state, |
505 Code::ExtraICState extra_ic_state, | 512 Code::ExtraICState extra_ic_state, |
506 Handle<Object> object, | 513 Handle<Object> object, |
507 Handle<String> name) { | 514 Handle<String> name) { |
515 if (object->IsJSObject()) { | |
516 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | |
517 if (receiver->map()->is_invalid_transition()) { | |
danno
2013/04/24 15:23:00
is_invalid_transition_target or is_invalid. is_dep
Toon Verwaest
2013/04/25 10:59:38
Done.
| |
518 JSObject::MigrateInstance(receiver); | |
519 } | |
520 } | |
521 | |
508 // If the object is undefined or null it's illegal to try to get any | 522 // If the object is undefined or null it's illegal to try to get any |
509 // of its properties; throw a TypeError in that case. | 523 // of its properties; throw a TypeError in that case. |
510 if (object->IsUndefined() || object->IsNull()) { | 524 if (object->IsUndefined() || object->IsNull()) { |
511 return TypeError("non_object_property_call", object, name); | 525 return TypeError("non_object_property_call", object, name); |
512 } | 526 } |
513 | 527 |
514 // Check if the name is trivially convertible to an index and get | 528 // Check if the name is trivially convertible to an index and get |
515 // the element if so. | 529 // the element if so. |
516 uint32_t index; | 530 uint32_t index; |
517 if (name->AsArrayIndex(&index)) { | 531 if (name->AsArrayIndex(&index)) { |
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
769 MaybeObject* KeyedCallIC::LoadFunction(State state, | 783 MaybeObject* KeyedCallIC::LoadFunction(State state, |
770 Handle<Object> object, | 784 Handle<Object> object, |
771 Handle<Object> key) { | 785 Handle<Object> key) { |
772 if (key->IsInternalizedString()) { | 786 if (key->IsInternalizedString()) { |
773 return CallICBase::LoadFunction(state, | 787 return CallICBase::LoadFunction(state, |
774 Code::kNoExtraICState, | 788 Code::kNoExtraICState, |
775 object, | 789 object, |
776 Handle<String>::cast(key)); | 790 Handle<String>::cast(key)); |
777 } | 791 } |
778 | 792 |
793 if (object->IsJSObject()) { | |
794 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | |
795 if (receiver->map()->is_invalid_transition()) { | |
796 JSObject::MigrateInstance(receiver); | |
797 } | |
798 } | |
799 | |
779 if (object->IsUndefined() || object->IsNull()) { | 800 if (object->IsUndefined() || object->IsNull()) { |
780 return TypeError("non_object_property_call", object, key); | 801 return TypeError("non_object_property_call", object, key); |
781 } | 802 } |
782 | 803 |
783 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded(); | 804 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded(); |
784 ASSERT(!(use_ic && object->IsJSGlobalProxy())); | 805 ASSERT(!(use_ic && object->IsJSGlobalProxy())); |
785 | 806 |
786 if (use_ic && state != MEGAMORPHIC) { | 807 if (use_ic && state != MEGAMORPHIC) { |
787 int argc = target()->arguments_count(); | 808 int argc = target()->arguments_count(); |
788 Handle<Code> stub = isolate()->stub_cache()->ComputeCallMegamorphic( | 809 Handle<Code> stub = isolate()->stub_cache()->ComputeCallMegamorphic( |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
883 | 904 |
884 // Check if the name is trivially convertible to an index and get | 905 // Check if the name is trivially convertible to an index and get |
885 // the element or char if so. | 906 // the element or char if so. |
886 uint32_t index; | 907 uint32_t index; |
887 if (kind() == Code::KEYED_LOAD_IC && name->AsArrayIndex(&index)) { | 908 if (kind() == Code::KEYED_LOAD_IC && name->AsArrayIndex(&index)) { |
888 // Rewrite to the generic keyed load stub. | 909 // Rewrite to the generic keyed load stub. |
889 if (FLAG_use_ic) set_target(*generic_stub()); | 910 if (FLAG_use_ic) set_target(*generic_stub()); |
890 return Runtime::GetElementOrCharAtOrFail(isolate(), object, index); | 911 return Runtime::GetElementOrCharAtOrFail(isolate(), object, index); |
891 } | 912 } |
892 | 913 |
914 if (object->IsJSObject()) { | |
915 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | |
916 if (receiver->map()->is_invalid_transition()) { | |
917 JSObject::MigrateInstance(receiver); | |
918 } | |
919 } | |
920 | |
893 // Named lookup in the object. | 921 // Named lookup in the object. |
894 LookupResult lookup(isolate()); | 922 LookupResult lookup(isolate()); |
895 LookupForRead(object, name, &lookup); | 923 LookupForRead(object, name, &lookup); |
896 | 924 |
897 // If we did not find a property, check if we need to throw an exception. | 925 // If we did not find a property, check if we need to throw an exception. |
898 if (!lookup.IsFound()) { | 926 if (!lookup.IsFound()) { |
899 if (IsUndeclaredGlobal(object)) { | 927 if (IsUndeclaredGlobal(object)) { |
900 return ReferenceError("not_defined", name); | 928 return ReferenceError("not_defined", name); |
901 } | 929 } |
902 LOG(isolate(), SuspectReadEvent(*name, *object)); | 930 LOG(isolate(), SuspectReadEvent(*name, *object)); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
947 Handle<Code> code) { | 975 Handle<Code> code) { |
948 if (code->type() == Code::NORMAL) return false; | 976 if (code->type() == Code::NORMAL) return false; |
949 if (target()->ic_state() == MONOMORPHIC && | 977 if (target()->ic_state() == MONOMORPHIC && |
950 target()->type() == Code::NORMAL) { | 978 target()->type() == Code::NORMAL) { |
951 return false; | 979 return false; |
952 } | 980 } |
953 | 981 |
954 MapHandleList receiver_maps; | 982 MapHandleList receiver_maps; |
955 CodeHandleList handlers; | 983 CodeHandleList handlers; |
956 | 984 |
985 int number_of_valid_maps; | |
957 { | 986 { |
958 AssertNoAllocation no_gc; | 987 AssertNoAllocation no_gc; |
959 target()->FindAllMaps(&receiver_maps); | 988 target()->FindAllMaps(&receiver_maps); |
960 int number_of_maps = receiver_maps.length(); | 989 int number_of_maps = receiver_maps.length(); |
961 if (number_of_maps >= 4) return false; | 990 number_of_valid_maps = number_of_maps; |
991 for (int i = 0; i < number_of_maps; i++) { | |
992 if (receiver_maps.at(i)->is_invalid_transition()) { | |
993 number_of_valid_maps--; | |
994 } | |
995 } | |
996 | |
997 if (number_of_valid_maps >= 4) return false; | |
962 | 998 |
963 // Only allow 0 maps in case target() was reset to UNINITIALIZED by the GC. | 999 // Only allow 0 maps in case target() was reset to UNINITIALIZED by the GC. |
964 // In that case, allow the IC to go back monomorphic. | 1000 // In that case, allow the IC to go back monomorphic. |
965 if (number_of_maps == 0 && target()->ic_state() != UNINITIALIZED) { | 1001 if (number_of_maps == 0 && target()->ic_state() != UNINITIALIZED) { |
966 return false; | 1002 return false; |
967 } | 1003 } |
968 target()->FindAllCode(&handlers, receiver_maps.length()); | 1004 target()->FindAllCode(&handlers, receiver_maps.length()); |
969 } | 1005 } |
970 | 1006 |
971 if (!AddOneReceiverMapIfMissing(&receiver_maps, | 1007 if (!AddOneReceiverMapIfMissing(&receiver_maps, |
972 Handle<Map>(receiver->map()))) { | 1008 Handle<Map>(receiver->map()))) { |
973 return false; | 1009 return false; |
974 } | 1010 } |
975 | 1011 |
976 handlers.Add(code); | 1012 handlers.Add(code); |
977 Handle<Code> ic = isolate()->stub_cache()->ComputePolymorphicIC( | 1013 Handle<Code> ic = isolate()->stub_cache()->ComputePolymorphicIC( |
978 &receiver_maps, &handlers, name); | 1014 &receiver_maps, &handlers, number_of_valid_maps + 1, name); |
979 set_target(*ic); | 1015 set_target(*ic); |
980 return true; | 1016 return true; |
981 } | 1017 } |
982 | 1018 |
983 | 1019 |
984 void LoadIC::UpdateMonomorphicIC(Handle<JSObject> receiver, | 1020 void LoadIC::UpdateMonomorphicIC(Handle<JSObject> receiver, |
985 Handle<Code> handler, | 1021 Handle<Code> handler, |
986 Handle<String> name) { | 1022 Handle<String> name) { |
987 if (handler->type() == Code::NORMAL) return set_target(*handler); | 1023 if (handler->type() == Code::NORMAL) return set_target(*handler); |
988 Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicIC( | 1024 Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicIC( |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1059 UpdateMonomorphicIC(receiver, code, name); | 1095 UpdateMonomorphicIC(receiver, code, name); |
1060 break; | 1096 break; |
1061 } | 1097 } |
1062 if (UpdatePolymorphicIC(state, strict_mode, receiver, name, code)) { | 1098 if (UpdatePolymorphicIC(state, strict_mode, receiver, name, code)) { |
1063 break; | 1099 break; |
1064 } | 1100 } |
1065 } | 1101 } |
1066 if (target()->type() != Code::NORMAL) { | 1102 if (target()->type() != Code::NORMAL) { |
1067 if (target()->is_load_stub()) { | 1103 if (target()->is_load_stub()) { |
1068 CopyICToMegamorphicCache(name); | 1104 CopyICToMegamorphicCache(name); |
1105 } else if (target()->is_store_stub()) { | |
1106 MapHandleList maps; | |
danno
2013/04/24 15:23:00
Comment that this is special handling that is only
Toon Verwaest
2013/04/25 10:59:38
Done.
| |
1107 Code* handler = target(); | |
1108 handler->FindAllMaps(&maps); | |
1109 for (int i = 0; i < Min(1, maps.length()); i++) { | |
1110 if (maps.at(i)->is_invalid_transition()) { | |
1111 UpdateMonomorphicIC(receiver, code, name); | |
1112 return; | |
1113 } | |
1114 } | |
1115 if (maps.length() > 0) { | |
1116 if (receiver->map() == *maps.at(0)) { | |
1117 UpdateMonomorphicIC(receiver, code, name); | |
1118 return; | |
1119 } | |
1120 UpdateMegamorphicCache(*maps.at(0), *name, handler); | |
1121 } | |
1069 } else { | 1122 } else { |
1070 Code* handler = target(); | 1123 Code* handler = target(); |
1071 Map* map = handler->FindFirstMap(); | 1124 Map* map = handler->FindFirstMap(); |
1072 if (map != NULL) { | 1125 if (map != NULL) { |
1073 UpdateMegamorphicCache(map, *name, handler); | 1126 UpdateMegamorphicCache(map, *name, handler); |
1074 } | 1127 } |
1075 } | 1128 } |
1076 } | 1129 } |
1077 | 1130 |
1078 UpdateMegamorphicCache(receiver->map(), *name, *code); | 1131 UpdateMegamorphicCache(receiver->map(), *name, *code); |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1151 Handle<Object> object, | 1204 Handle<Object> object, |
1152 Handle<String> name) { | 1205 Handle<String> name) { |
1153 // Bail out if the result is not cacheable. | 1206 // Bail out if the result is not cacheable. |
1154 if (!lookup->IsCacheable()) return; | 1207 if (!lookup->IsCacheable()) return; |
1155 | 1208 |
1156 // Loading properties from values is not common, so don't try to | 1209 // Loading properties from values is not common, so don't try to |
1157 // deal with non-JS objects here. | 1210 // deal with non-JS objects here. |
1158 if (!object->IsJSObject()) return; | 1211 if (!object->IsJSObject()) return; |
1159 | 1212 |
1160 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1213 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
1214 | |
danno
2013/04/24 15:23:00
extraneous whitespace change
Toon Verwaest
2013/04/25 10:59:38
Done.
| |
1161 Handle<Code> code; | 1215 Handle<Code> code; |
1162 if (state == UNINITIALIZED) { | 1216 if (state == UNINITIALIZED) { |
1163 // This is the first time we execute this inline cache. | 1217 // This is the first time we execute this inline cache. |
1164 // Set the target to the pre monomorphic stub to delay | 1218 // Set the target to the pre monomorphic stub to delay |
1165 // setting the monomorphic state. | 1219 // setting the monomorphic state. |
1166 code = pre_monomorphic_stub(); | 1220 code = pre_monomorphic_stub(); |
1167 } else { | 1221 } else { |
1168 code = ComputeLoadHandler(lookup, receiver, name); | 1222 code = ComputeLoadHandler(lookup, receiver, name); |
1169 if (code.is_null()) return; | 1223 if (code.is_null()) return; |
1170 } | 1224 } |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1358 | 1412 |
1359 if (use_ic) { | 1413 if (use_ic) { |
1360 Handle<Code> stub = generic_stub(); | 1414 Handle<Code> stub = generic_stub(); |
1361 if (miss_mode != MISS_FORCE_GENERIC) { | 1415 if (miss_mode != MISS_FORCE_GENERIC) { |
1362 if (object->IsString() && key->IsNumber()) { | 1416 if (object->IsString() && key->IsNumber()) { |
1363 if (state == UNINITIALIZED) { | 1417 if (state == UNINITIALIZED) { |
1364 stub = string_stub(); | 1418 stub = string_stub(); |
1365 } | 1419 } |
1366 } else if (object->IsJSObject()) { | 1420 } else if (object->IsJSObject()) { |
1367 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1421 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
1422 if (receiver->map()->is_invalid_transition()) { | |
1423 JSObject::MigrateInstance(receiver); | |
1424 } | |
1425 | |
1368 if (receiver->elements()->map() == | 1426 if (receiver->elements()->map() == |
1369 isolate()->heap()->non_strict_arguments_elements_map()) { | 1427 isolate()->heap()->non_strict_arguments_elements_map()) { |
1370 stub = non_strict_arguments_stub(); | 1428 stub = non_strict_arguments_stub(); |
1371 } else if (receiver->HasIndexedInterceptor()) { | 1429 } else if (receiver->HasIndexedInterceptor()) { |
1372 stub = indexed_interceptor_stub(); | 1430 stub = indexed_interceptor_stub(); |
1373 } else if (!key->ToSmi()->IsFailure() && | 1431 } else if (!key->ToSmi()->IsFailure() && |
1374 (target() != *non_strict_arguments_stub())) { | 1432 (target() != *non_strict_arguments_stub())) { |
1375 stub = LoadElementStub(receiver); | 1433 stub = LoadElementStub(receiver); |
1376 } | 1434 } |
1377 } | 1435 } |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1424 // Always rewrite to the generic case so that we do not | 1482 // Always rewrite to the generic case so that we do not |
1425 // repeatedly try to rewrite. | 1483 // repeatedly try to rewrite. |
1426 return generic_stub(); | 1484 return generic_stub(); |
1427 } | 1485 } |
1428 return Handle<Code>::null(); | 1486 return Handle<Code>::null(); |
1429 } | 1487 } |
1430 | 1488 |
1431 | 1489 |
1432 static bool LookupForWrite(Handle<JSObject> receiver, | 1490 static bool LookupForWrite(Handle<JSObject> receiver, |
1433 Handle<String> name, | 1491 Handle<String> name, |
1492 Handle<Object> value, | |
1434 LookupResult* lookup) { | 1493 LookupResult* lookup) { |
1435 Handle<JSObject> holder = receiver; | 1494 Handle<JSObject> holder = receiver; |
1436 receiver->Lookup(*name, lookup); | 1495 receiver->Lookup(*name, lookup); |
1437 if (lookup->IsFound()) { | 1496 if (lookup->IsFound()) { |
1438 if (lookup->IsReadOnly() || !lookup->IsCacheable()) return false; | 1497 if (lookup->IsReadOnly() || !lookup->IsCacheable()) return false; |
1439 | 1498 |
1440 if (lookup->holder() == *receiver) { | 1499 if (lookup->holder() == *receiver) { |
1441 if (lookup->IsInterceptor() && | 1500 if (lookup->IsInterceptor() && |
1442 receiver->GetNamedInterceptor()->setter()->IsUndefined()) { | 1501 receiver->GetNamedInterceptor()->setter()->IsUndefined()) { |
1443 receiver->LocalLookupRealNamedProperty(*name, lookup); | 1502 receiver->LocalLookupRealNamedProperty(*name, lookup); |
1444 return lookup->IsFound() && | 1503 return lookup->IsFound() && |
1445 !lookup->IsReadOnly() && | 1504 !lookup->IsReadOnly() && |
1505 lookup->CanStore(value) && | |
1446 lookup->IsCacheable(); | 1506 lookup->IsCacheable(); |
1447 } | 1507 } |
1448 return true; | 1508 return lookup->CanStore(value); |
danno
2013/04/24 15:23:00
CanHoldValue?
Toon Verwaest
2013/04/25 10:59:38
Done.
| |
1449 } | 1509 } |
1450 | 1510 |
1451 if (lookup->IsPropertyCallbacks()) return true; | 1511 if (lookup->IsPropertyCallbacks()) return true; |
1452 | 1512 |
1453 // Currently normal holders in the prototype chain are not supported. They | 1513 // Currently normal holders in the prototype chain are not supported. They |
1454 // would require a runtime positive lookup and verification that the details | 1514 // would require a runtime positive lookup and verification that the details |
1455 // have not changed. | 1515 // have not changed. |
1456 if (lookup->IsInterceptor() || lookup->IsNormal()) return false; | 1516 if (lookup->IsInterceptor() || lookup->IsNormal()) return false; |
1457 holder = Handle<JSObject>(lookup->holder(), lookup->isolate()); | 1517 holder = Handle<JSObject>(lookup->holder(), lookup->isolate()); |
1458 } | 1518 } |
1459 | 1519 |
1460 // While normally LookupTransition gets passed the receiver, in this case we | 1520 // While normally LookupTransition gets passed the receiver, in this case we |
1461 // pass the holder of the property that we overwrite. This keeps the holder in | 1521 // pass the holder of the property that we overwrite. This keeps the holder in |
1462 // the LookupResult intact so we can later use it to generate a prototype | 1522 // the LookupResult intact so we can later use it to generate a prototype |
1463 // chain check. This avoids a double lookup, but requires us to pass in the | 1523 // chain check. This avoids a double lookup, but requires us to pass in the |
1464 // receiver when trying to fetch extra information from the transition. | 1524 // receiver when trying to fetch extra information from the transition. |
1465 receiver->map()->LookupTransition(*holder, *name, lookup); | 1525 receiver->map()->LookupTransition(*holder, *name, lookup); |
1466 return lookup->IsTransition() && | 1526 if (!lookup->IsTransition()) return false; |
1467 !lookup->GetTransitionDetails(receiver->map()).IsReadOnly(); | 1527 PropertyDetails target_details = |
1528 lookup->GetTransitionDetails(receiver->map()); | |
1529 if (target_details.IsReadOnly()) return false; | |
1530 return value->FitsRepresentation(target_details.representation()); | |
1468 } | 1531 } |
1469 | 1532 |
1470 | 1533 |
1471 MaybeObject* StoreIC::Store(State state, | 1534 MaybeObject* StoreIC::Store(State state, |
1472 StrictModeFlag strict_mode, | 1535 StrictModeFlag strict_mode, |
1473 Handle<Object> object, | 1536 Handle<Object> object, |
1474 Handle<String> name, | 1537 Handle<String> name, |
1475 Handle<Object> value, | 1538 Handle<Object> value, |
1476 JSReceiver::StoreFromKeyed store_mode) { | 1539 JSReceiver::StoreFromKeyed store_mode) { |
1477 // Handle proxies. | 1540 // Handle proxies. |
(...skipping 13 matching lines...) Expand all Loading... | |
1491 name->Equals(isolate()->heap()->length_string())) { | 1554 name->Equals(isolate()->heap()->length_string())) { |
1492 return TypeError("strict_read_only_property", object, name); | 1555 return TypeError("strict_read_only_property", object, name); |
1493 } | 1556 } |
1494 | 1557 |
1495 // Ignore other stores where the receiver is not a JSObject. | 1558 // Ignore other stores where the receiver is not a JSObject. |
1496 // TODO(1475): Must check prototype chains of object wrappers. | 1559 // TODO(1475): Must check prototype chains of object wrappers. |
1497 if (!object->IsJSObject()) return *value; | 1560 if (!object->IsJSObject()) return *value; |
1498 | 1561 |
1499 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1562 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
1500 | 1563 |
1564 if (receiver->map()->is_invalid_transition()) { | |
1565 JSObject::MigrateInstance(receiver); | |
1566 } | |
1567 | |
1501 // Check if the given name is an array index. | 1568 // Check if the given name is an array index. |
1502 uint32_t index; | 1569 uint32_t index; |
1503 if (name->AsArrayIndex(&index)) { | 1570 if (name->AsArrayIndex(&index)) { |
1504 Handle<Object> result = | 1571 Handle<Object> result = |
1505 JSObject::SetElement(receiver, index, value, NONE, strict_mode); | 1572 JSObject::SetElement(receiver, index, value, NONE, strict_mode); |
1506 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 1573 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
1507 return *value; | 1574 return *value; |
1508 } | 1575 } |
1509 | 1576 |
1510 // Observed objects are always modified through the runtime. | 1577 // Observed objects are always modified through the runtime. |
(...skipping 26 matching lines...) Expand all Loading... | |
1537 ? global_proxy_stub_strict() | 1604 ? global_proxy_stub_strict() |
1538 : global_proxy_stub(); | 1605 : global_proxy_stub(); |
1539 set_target(*stub); | 1606 set_target(*stub); |
1540 TRACE_IC("StoreIC", name, state, *stub); | 1607 TRACE_IC("StoreIC", name, state, *stub); |
1541 } | 1608 } |
1542 return JSReceiver::SetPropertyOrFail( | 1609 return JSReceiver::SetPropertyOrFail( |
1543 receiver, name, value, NONE, strict_mode, store_mode); | 1610 receiver, name, value, NONE, strict_mode, store_mode); |
1544 } | 1611 } |
1545 | 1612 |
1546 LookupResult lookup(isolate()); | 1613 LookupResult lookup(isolate()); |
1547 if (LookupForWrite(receiver, name, &lookup)) { | 1614 if (LookupForWrite(receiver, name, value, &lookup)) { |
1548 if (FLAG_use_ic) { | 1615 if (FLAG_use_ic) { |
1549 UpdateCaches(&lookup, state, strict_mode, receiver, name, value); | 1616 UpdateCaches(&lookup, state, strict_mode, receiver, name, value); |
1550 } | 1617 } |
1551 } else if (strict_mode == kStrictMode && | 1618 } else if (strict_mode == kStrictMode && |
1552 !(lookup.IsProperty() && lookup.IsReadOnly()) && | 1619 !(lookup.IsProperty() && lookup.IsReadOnly()) && |
1553 IsUndeclaredGlobal(object)) { | 1620 IsUndeclaredGlobal(object)) { |
1554 // Strict mode doesn't allow setting non-existent global property. | 1621 // Strict mode doesn't allow setting non-existent global property. |
1555 return ReferenceError("not_defined", name); | 1622 return ReferenceError("not_defined", name); |
1556 } | 1623 } |
1557 | 1624 |
(...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1946 JSObject::cast(*object)->map()->is_observed()); | 2013 JSObject::cast(*object)->map()->is_observed()); |
1947 ASSERT(!(use_ic && object->IsJSGlobalProxy())); | 2014 ASSERT(!(use_ic && object->IsJSGlobalProxy())); |
1948 | 2015 |
1949 if (use_ic) { | 2016 if (use_ic) { |
1950 Handle<Code> stub = (strict_mode == kStrictMode) | 2017 Handle<Code> stub = (strict_mode == kStrictMode) |
1951 ? generic_stub_strict() | 2018 ? generic_stub_strict() |
1952 : generic_stub(); | 2019 : generic_stub(); |
1953 if (miss_mode != MISS_FORCE_GENERIC) { | 2020 if (miss_mode != MISS_FORCE_GENERIC) { |
1954 if (object->IsJSObject()) { | 2021 if (object->IsJSObject()) { |
1955 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 2022 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
2023 if (receiver->map()->is_invalid_transition()) { | |
2024 JSObject::MigrateInstance(receiver); | |
2025 } | |
1956 bool key_is_smi_like = key->IsSmi() || | 2026 bool key_is_smi_like = key->IsSmi() || |
1957 (FLAG_compiled_keyed_stores && !key->ToSmi()->IsFailure()); | 2027 (FLAG_compiled_keyed_stores && !key->ToSmi()->IsFailure()); |
1958 if (receiver->elements()->map() == | 2028 if (receiver->elements()->map() == |
1959 isolate()->heap()->non_strict_arguments_elements_map()) { | 2029 isolate()->heap()->non_strict_arguments_elements_map()) { |
1960 stub = non_strict_arguments_stub(); | 2030 stub = non_strict_arguments_stub(); |
1961 } else if (key_is_smi_like && | 2031 } else if (key_is_smi_like && |
1962 (target() != *non_strict_arguments_stub())) { | 2032 (target() != *non_strict_arguments_stub())) { |
1963 KeyedAccessStoreMode store_mode = GetStoreMode(receiver, key, value); | 2033 KeyedAccessStoreMode store_mode = GetStoreMode(receiver, key, value); |
1964 stub = StoreElementStub(receiver, store_mode, strict_mode); | 2034 stub = StoreElementStub(receiver, store_mode, strict_mode); |
1965 } else { | 2035 } else { |
(...skipping 843 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2809 #undef ADDR | 2879 #undef ADDR |
2810 }; | 2880 }; |
2811 | 2881 |
2812 | 2882 |
2813 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2883 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
2814 return IC_utilities[id]; | 2884 return IC_utilities[id]; |
2815 } | 2885 } |
2816 | 2886 |
2817 | 2887 |
2818 } } // namespace v8::internal | 2888 } } // namespace v8::internal |
OLD | NEW |