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 411 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
422 | 422 |
423 void LoadIC::Clear(Isolate* isolate, Address address, Code* target) { | 423 void LoadIC::Clear(Isolate* isolate, Address address, Code* target) { |
424 if (IsCleared(target)) return; | 424 if (IsCleared(target)) return; |
425 SetTargetAtAddress(address, *pre_monomorphic_stub(isolate)); | 425 SetTargetAtAddress(address, *pre_monomorphic_stub(isolate)); |
426 } | 426 } |
427 | 427 |
428 | 428 |
429 void StoreIC::Clear(Isolate* isolate, Address address, Code* target) { | 429 void StoreIC::Clear(Isolate* isolate, Address address, Code* target) { |
430 if (IsCleared(target)) return; | 430 if (IsCleared(target)) return; |
431 SetTargetAtAddress(address, | 431 SetTargetAtAddress(address, |
432 (Code::GetStrictMode(target->extra_ic_state()) == kStrictMode) | 432 *pre_monomorphic_stub( |
433 ? *pre_monomorphic_stub_strict(isolate) | 433 isolate, Code::GetStrictMode(target->extra_ic_state()))); |
434 : *pre_monomorphic_stub(isolate)); | |
435 } | 434 } |
436 | 435 |
437 | 436 |
438 void KeyedStoreIC::Clear(Isolate* isolate, Address address, Code* target) { | 437 void KeyedStoreIC::Clear(Isolate* isolate, Address address, Code* target) { |
439 if (IsCleared(target)) return; | 438 if (IsCleared(target)) return; |
440 SetTargetAtAddress(address, | 439 SetTargetAtAddress(address, |
441 (Code::GetStrictMode(target->extra_ic_state()) == kStrictMode) | 440 *pre_monomorphic_stub( |
442 ? *pre_monomorphic_stub_strict(isolate) | 441 isolate, Code::GetStrictMode(target->extra_ic_state()))); |
443 : *pre_monomorphic_stub(isolate)); | |
444 } | 442 } |
445 | 443 |
446 | 444 |
447 void CompareIC::Clear(Isolate* isolate, Address address, Code* target) { | 445 void CompareIC::Clear(Isolate* isolate, Address address, Code* target) { |
448 ASSERT(target->major_key() == CodeStub::CompareIC); | 446 ASSERT(target->major_key() == CodeStub::CompareIC); |
449 CompareIC::State handler_state; | 447 CompareIC::State handler_state; |
450 Token::Value op; | 448 Token::Value op; |
451 ICCompareStub::DecodeMinorKey(target->stub_info(), NULL, NULL, | 449 ICCompareStub::DecodeMinorKey(target->stub_info(), NULL, NULL, |
452 &handler_state, &op); | 450 &handler_state, &op); |
453 // Only clear CompareICs that can retain objects. | 451 // Only clear CompareICs that can retain objects. |
(...skipping 533 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
987 } | 985 } |
988 } | 986 } |
989 receiver_maps->Add(new_receiver_map); | 987 receiver_maps->Add(new_receiver_map); |
990 return true; | 988 return true; |
991 } | 989 } |
992 | 990 |
993 | 991 |
994 bool IC::UpdatePolymorphicIC(State state, | 992 bool IC::UpdatePolymorphicIC(State state, |
995 Handle<HeapObject> receiver, | 993 Handle<HeapObject> receiver, |
996 Handle<String> name, | 994 Handle<String> name, |
997 Handle<Code> code, | 995 Handle<Code> code) { |
998 StrictModeFlag strict_mode) { | |
999 if (!code->is_handler()) return false; | 996 if (!code->is_handler()) return false; |
1000 | 997 |
1001 MapHandleList receiver_maps; | 998 MapHandleList receiver_maps; |
1002 CodeHandleList handlers; | 999 CodeHandleList handlers; |
1003 | 1000 |
1004 int number_of_valid_maps; | 1001 int number_of_valid_maps; |
1005 int handler_to_overwrite = -1; | 1002 int handler_to_overwrite = -1; |
1006 Handle<Map> new_receiver_map(receiver->map()); | 1003 Handle<Map> new_receiver_map(receiver->map()); |
1007 { | 1004 { |
1008 DisallowHeapAllocation no_gc; | 1005 DisallowHeapAllocation no_gc; |
(...skipping 30 matching lines...) Expand all Loading... |
1039 | 1036 |
1040 number_of_valid_maps++; | 1037 number_of_valid_maps++; |
1041 if (handler_to_overwrite >= 0) { | 1038 if (handler_to_overwrite >= 0) { |
1042 handlers.Set(handler_to_overwrite, code); | 1039 handlers.Set(handler_to_overwrite, code); |
1043 } else { | 1040 } else { |
1044 receiver_maps.Add(new_receiver_map); | 1041 receiver_maps.Add(new_receiver_map); |
1045 handlers.Add(code); | 1042 handlers.Add(code); |
1046 } | 1043 } |
1047 | 1044 |
1048 Handle<Code> ic = isolate()->stub_cache()->ComputePolymorphicIC( | 1045 Handle<Code> ic = isolate()->stub_cache()->ComputePolymorphicIC( |
1049 &receiver_maps, &handlers, number_of_valid_maps, name, strict_mode); | 1046 &receiver_maps, &handlers, number_of_valid_maps, name, strict_mode()); |
1050 set_target(*ic); | 1047 set_target(*ic); |
1051 return true; | 1048 return true; |
1052 } | 1049 } |
1053 | 1050 |
1054 | 1051 |
1055 void IC::UpdateMonomorphicIC(Handle<HeapObject> receiver, | 1052 void IC::UpdateMonomorphicIC(Handle<HeapObject> receiver, |
1056 Handle<Code> handler, | 1053 Handle<Code> handler, |
1057 Handle<String> name, | 1054 Handle<String> name) { |
1058 StrictModeFlag strict_mode) { | |
1059 if (!handler->is_handler()) return set_target(*handler); | 1055 if (!handler->is_handler()) return set_target(*handler); |
1060 Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicIC( | 1056 Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicIC( |
1061 receiver, handler, name, strict_mode); | 1057 receiver, handler, name, strict_mode()); |
1062 set_target(*ic); | 1058 set_target(*ic); |
1063 } | 1059 } |
1064 | 1060 |
1065 | 1061 |
1066 void IC::CopyICToMegamorphicCache(Handle<String> name) { | 1062 void IC::CopyICToMegamorphicCache(Handle<String> name) { |
1067 MapHandleList receiver_maps; | 1063 MapHandleList receiver_maps; |
1068 CodeHandleList handlers; | 1064 CodeHandleList handlers; |
1069 { | 1065 { |
1070 DisallowHeapAllocation no_gc; | 1066 DisallowHeapAllocation no_gc; |
1071 target()->FindAllMaps(&receiver_maps); | 1067 target()->FindAllMaps(&receiver_maps); |
(...skipping 17 matching lines...) Expand all Loading... |
1089 ? current_map->LookupElementsTransitionMap(receiver_elements_kind) | 1085 ? current_map->LookupElementsTransitionMap(receiver_elements_kind) |
1090 : NULL; | 1086 : NULL; |
1091 | 1087 |
1092 return transitioned_map == receiver_map; | 1088 return transitioned_map == receiver_map; |
1093 } | 1089 } |
1094 | 1090 |
1095 | 1091 |
1096 // Since GC may have been invoked, by the time PatchCache is called, |state| is | 1092 // Since GC may have been invoked, by the time PatchCache is called, |state| is |
1097 // not necessarily equal to target()->state(). | 1093 // not necessarily equal to target()->state(). |
1098 void IC::PatchCache(State state, | 1094 void IC::PatchCache(State state, |
1099 StrictModeFlag strict_mode, | |
1100 Handle<HeapObject> receiver, | 1095 Handle<HeapObject> receiver, |
1101 Handle<String> name, | 1096 Handle<String> name, |
1102 Handle<Code> code) { | 1097 Handle<Code> code) { |
1103 switch (state) { | 1098 switch (state) { |
1104 case UNINITIALIZED: | 1099 case UNINITIALIZED: |
1105 case PREMONOMORPHIC: | 1100 case PREMONOMORPHIC: |
1106 case MONOMORPHIC_PROTOTYPE_FAILURE: | 1101 case MONOMORPHIC_PROTOTYPE_FAILURE: |
1107 UpdateMonomorphicIC(receiver, code, name, strict_mode); | 1102 UpdateMonomorphicIC(receiver, code, name); |
1108 break; | 1103 break; |
1109 case MONOMORPHIC: | 1104 case MONOMORPHIC: |
1110 // Only move to megamorphic if the target changes. | 1105 // Only move to megamorphic if the target changes. |
1111 if (target() != *code) { | 1106 if (target() != *code) { |
1112 if (target()->is_load_stub() || target()->is_store_stub()) { | 1107 if (target()->is_load_stub() || target()->is_store_stub()) { |
1113 bool is_same_handler = false; | 1108 bool is_same_handler = false; |
1114 { | 1109 { |
1115 DisallowHeapAllocation no_allocation; | 1110 DisallowHeapAllocation no_allocation; |
1116 Code* old_handler = target()->FindFirstHandler(); | 1111 Code* old_handler = target()->FindFirstHandler(); |
1117 is_same_handler = old_handler == *code; | 1112 is_same_handler = old_handler == *code; |
1118 } | 1113 } |
1119 if (is_same_handler | 1114 if (is_same_handler |
1120 && IsTransitionedMapOfMonomorphicTarget(receiver->map())) { | 1115 && IsTransitionedMapOfMonomorphicTarget(receiver->map())) { |
1121 UpdateMonomorphicIC(receiver, code, name, strict_mode); | 1116 UpdateMonomorphicIC(receiver, code, name); |
1122 break; | 1117 break; |
1123 } | 1118 } |
1124 if (UpdatePolymorphicIC(state, receiver, name, code, strict_mode)) { | 1119 if (UpdatePolymorphicIC(state, receiver, name, code)) { |
1125 break; | 1120 break; |
1126 } | 1121 } |
1127 | 1122 |
1128 CopyICToMegamorphicCache(name); | 1123 CopyICToMegamorphicCache(name); |
1129 } | 1124 } |
1130 | 1125 |
1131 UpdateMegamorphicCache(receiver->map(), *name, *code); | 1126 UpdateMegamorphicCache(receiver->map(), *name, *code); |
1132 set_target((strict_mode == kStrictMode) | 1127 set_target(*megamorphic_stub()); |
1133 ? *megamorphic_stub_strict() | |
1134 : *megamorphic_stub()); | |
1135 } | 1128 } |
1136 break; | 1129 break; |
1137 case MEGAMORPHIC: | 1130 case MEGAMORPHIC: |
1138 UpdateMegamorphicCache(receiver->map(), *name, *code); | 1131 UpdateMegamorphicCache(receiver->map(), *name, *code); |
1139 break; | 1132 break; |
1140 case POLYMORPHIC: | 1133 case POLYMORPHIC: |
1141 if (target()->is_load_stub() || target()->is_store_stub()) { | 1134 if (target()->is_load_stub() || target()->is_store_stub()) { |
1142 if (UpdatePolymorphicIC(state, receiver, name, code, strict_mode)) { | 1135 if (UpdatePolymorphicIC(state, receiver, name, code)) { |
1143 break; | 1136 break; |
1144 } | 1137 } |
1145 CopyICToMegamorphicCache(name); | 1138 CopyICToMegamorphicCache(name); |
1146 UpdateMegamorphicCache(receiver->map(), *name, *code); | 1139 UpdateMegamorphicCache(receiver->map(), *name, *code); |
1147 set_target((strict_mode == kStrictMode) | 1140 set_target(*megamorphic_stub()); |
1148 ? *megamorphic_stub_strict() | |
1149 : *megamorphic_stub()); | |
1150 } else { | 1141 } else { |
1151 // When trying to patch a polymorphic keyed load/store element stub | 1142 // When trying to patch a polymorphic keyed load/store element stub |
1152 // with anything other than another polymorphic stub, go generic. | 1143 // with anything other than another polymorphic stub, go generic. |
1153 set_target((strict_mode == kStrictMode) | 1144 set_target(*generic_stub()); |
1154 ? *generic_stub_strict() | |
1155 : *generic_stub()); | |
1156 } | 1145 } |
1157 break; | 1146 break; |
1158 case DEBUG_STUB: | 1147 case DEBUG_STUB: |
1159 break; | 1148 break; |
1160 case GENERIC: | 1149 case GENERIC: |
1161 UNREACHABLE(); | 1150 UNREACHABLE(); |
1162 break; | 1151 break; |
1163 } | 1152 } |
1164 } | 1153 } |
1165 | 1154 |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1231 } | 1220 } |
1232 } else if (!object->IsJSObject()) { | 1221 } else if (!object->IsJSObject()) { |
1233 // TODO(jkummerow): It would be nice to support non-JSObjects in | 1222 // TODO(jkummerow): It would be nice to support non-JSObjects in |
1234 // ComputeLoadHandler, then we wouldn't need to go generic here. | 1223 // ComputeLoadHandler, then we wouldn't need to go generic here. |
1235 code = slow_stub(); | 1224 code = slow_stub(); |
1236 } else { | 1225 } else { |
1237 code = ComputeLoadHandler(lookup, Handle<JSObject>::cast(receiver), name); | 1226 code = ComputeLoadHandler(lookup, Handle<JSObject>::cast(receiver), name); |
1238 if (code.is_null()) code = slow_stub(); | 1227 if (code.is_null()) code = slow_stub(); |
1239 } | 1228 } |
1240 | 1229 |
1241 PatchCache(state, kNonStrictMode, receiver, name, code); | 1230 PatchCache(state, receiver, name, code); |
1242 TRACE_IC("LoadIC", name, state, target()); | 1231 TRACE_IC("LoadIC", name, state, target()); |
1243 } | 1232 } |
1244 | 1233 |
1245 | 1234 |
1246 void IC::UpdateMegamorphicCache(Map* map, Name* name, Code* code) { | 1235 void IC::UpdateMegamorphicCache(Map* map, Name* name, Code* code) { |
1247 // Cache code holding map should be consistent with | 1236 // Cache code holding map should be consistent with |
1248 // GenerateMonomorphicCacheProbe. | 1237 // GenerateMonomorphicCacheProbe. |
1249 isolate()->stub_cache()->Set(name, map, code); | 1238 isolate()->stub_cache()->Set(name, map, code); |
1250 } | 1239 } |
1251 | 1240 |
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1600 // entirely by the migration above. | 1589 // entirely by the migration above. |
1601 receiver->map()->LookupTransition(*holder, *name, lookup); | 1590 receiver->map()->LookupTransition(*holder, *name, lookup); |
1602 if (!lookup->IsTransition()) return false; | 1591 if (!lookup->IsTransition()) return false; |
1603 *state = MONOMORPHIC_PROTOTYPE_FAILURE; | 1592 *state = MONOMORPHIC_PROTOTYPE_FAILURE; |
1604 } | 1593 } |
1605 return true; | 1594 return true; |
1606 } | 1595 } |
1607 | 1596 |
1608 | 1597 |
1609 MaybeObject* StoreIC::Store(State state, | 1598 MaybeObject* StoreIC::Store(State state, |
1610 StrictModeFlag strict_mode, | |
1611 Handle<Object> object, | 1599 Handle<Object> object, |
1612 Handle<String> name, | 1600 Handle<String> name, |
1613 Handle<Object> value, | 1601 Handle<Object> value, |
1614 JSReceiver::StoreFromKeyed store_mode) { | 1602 JSReceiver::StoreFromKeyed store_mode) { |
1615 // Handle proxies. | 1603 // Handle proxies. |
1616 if (object->IsJSProxy()) { | 1604 if (object->IsJSProxy()) { |
1617 Handle<Object> result = JSReceiver::SetProperty( | 1605 Handle<Object> result = JSReceiver::SetProperty( |
1618 Handle<JSReceiver>::cast(object), name, value, NONE, strict_mode); | 1606 Handle<JSReceiver>::cast(object), name, value, NONE, strict_mode()); |
1619 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 1607 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
1620 return *result; | 1608 return *result; |
1621 } | 1609 } |
1622 | 1610 |
1623 // If the object is undefined or null it's illegal to try to set any | 1611 // If the object is undefined or null it's illegal to try to set any |
1624 // properties on it; throw a TypeError in that case. | 1612 // properties on it; throw a TypeError in that case. |
1625 if (object->IsUndefined() || object->IsNull()) { | 1613 if (object->IsUndefined() || object->IsNull()) { |
1626 return TypeError("non_object_property_store", object, name); | 1614 return TypeError("non_object_property_store", object, name); |
1627 } | 1615 } |
1628 | 1616 |
1629 // The length property of string values is read-only. Throw in strict mode. | 1617 // The length property of string values is read-only. Throw in strict mode. |
1630 if (strict_mode == kStrictMode && object->IsString() && | 1618 if (strict_mode() == kStrictMode && object->IsString() && |
1631 name->Equals(isolate()->heap()->length_string())) { | 1619 name->Equals(isolate()->heap()->length_string())) { |
1632 return TypeError("strict_read_only_property", object, name); | 1620 return TypeError("strict_read_only_property", object, name); |
1633 } | 1621 } |
1634 | 1622 |
1635 // Ignore other stores where the receiver is not a JSObject. | 1623 // Ignore other stores where the receiver is not a JSObject. |
1636 // TODO(1475): Must check prototype chains of object wrappers. | 1624 // TODO(1475): Must check prototype chains of object wrappers. |
1637 if (!object->IsJSObject()) return *value; | 1625 if (!object->IsJSObject()) return *value; |
1638 | 1626 |
1639 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1627 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
1640 | 1628 |
1641 bool use_ic = FLAG_use_ic; | 1629 bool use_ic = FLAG_use_ic; |
1642 if (receiver->map()->is_deprecated()) { | 1630 if (receiver->map()->is_deprecated()) { |
1643 use_ic = false; | 1631 use_ic = false; |
1644 JSObject::MigrateInstance(receiver); | 1632 JSObject::MigrateInstance(receiver); |
1645 } | 1633 } |
1646 | 1634 |
1647 // Check if the given name is an array index. | 1635 // Check if the given name is an array index. |
1648 uint32_t index; | 1636 uint32_t index; |
1649 if (name->AsArrayIndex(&index)) { | 1637 if (name->AsArrayIndex(&index)) { |
1650 Handle<Object> result = | 1638 Handle<Object> result = |
1651 JSObject::SetElement(receiver, index, value, NONE, strict_mode); | 1639 JSObject::SetElement(receiver, index, value, NONE, strict_mode()); |
1652 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 1640 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
1653 return *value; | 1641 return *value; |
1654 } | 1642 } |
1655 | 1643 |
1656 // Observed objects are always modified through the runtime. | 1644 // Observed objects are always modified through the runtime. |
1657 if (FLAG_harmony_observation && receiver->map()->is_observed()) { | 1645 if (FLAG_harmony_observation && receiver->map()->is_observed()) { |
1658 Handle<Object> result = JSReceiver::SetProperty( | 1646 Handle<Object> result = JSReceiver::SetProperty( |
1659 receiver, name, value, NONE, strict_mode, store_mode); | 1647 receiver, name, value, NONE, strict_mode(), store_mode); |
1660 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 1648 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
1661 return *result; | 1649 return *result; |
1662 } | 1650 } |
1663 | 1651 |
1664 // Use specialized code for setting the length of arrays with fast | 1652 // Use specialized code for setting the length of arrays with fast |
1665 // properties. Slow properties might indicate redefinition of the length | 1653 // properties. Slow properties might indicate redefinition of the length |
1666 // property. Note that when redefined using Object.freeze, it's possible | 1654 // property. Note that when redefined using Object.freeze, it's possible |
1667 // to have fast properties but a read-only length. | 1655 // to have fast properties but a read-only length. |
1668 if (use_ic && | 1656 if (use_ic && |
1669 receiver->IsJSArray() && | 1657 receiver->IsJSArray() && |
1670 name->Equals(isolate()->heap()->length_string()) && | 1658 name->Equals(isolate()->heap()->length_string()) && |
1671 Handle<JSArray>::cast(receiver)->AllowsSetElementsLength() && | 1659 Handle<JSArray>::cast(receiver)->AllowsSetElementsLength() && |
1672 receiver->HasFastProperties() && | 1660 receiver->HasFastProperties() && |
1673 !receiver->map()->is_frozen()) { | 1661 !receiver->map()->is_frozen()) { |
1674 Handle<Code> stub = | 1662 Handle<Code> stub = |
1675 StoreArrayLengthStub(kind(), strict_mode).GetCode(isolate()); | 1663 StoreArrayLengthStub(kind(), strict_mode()).GetCode(isolate()); |
1676 set_target(*stub); | 1664 set_target(*stub); |
1677 TRACE_IC("StoreIC", name, state, *stub); | 1665 TRACE_IC("StoreIC", name, state, *stub); |
1678 Handle<Object> result = JSReceiver::SetProperty( | 1666 Handle<Object> result = JSReceiver::SetProperty( |
1679 receiver, name, value, NONE, strict_mode, store_mode); | 1667 receiver, name, value, NONE, strict_mode(), store_mode); |
1680 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 1668 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
1681 return *result; | 1669 return *result; |
1682 } | 1670 } |
1683 | 1671 |
1684 if (receiver->IsJSGlobalProxy()) { | 1672 if (receiver->IsJSGlobalProxy()) { |
1685 if (use_ic && kind() != Code::KEYED_STORE_IC) { | 1673 if (use_ic && kind() != Code::KEYED_STORE_IC) { |
1686 // Generate a generic stub that goes to the runtime when we see a global | 1674 // Generate a generic stub that goes to the runtime when we see a global |
1687 // proxy as receiver. | 1675 // proxy as receiver. |
1688 Handle<Code> stub = (strict_mode == kStrictMode) | 1676 Handle<Code> stub = global_proxy_stub(); |
1689 ? global_proxy_stub_strict() | |
1690 : global_proxy_stub(); | |
1691 set_target(*stub); | 1677 set_target(*stub); |
1692 TRACE_IC("StoreIC", name, state, *stub); | 1678 TRACE_IC("StoreIC", name, state, *stub); |
1693 } | 1679 } |
1694 Handle<Object> result = JSReceiver::SetProperty( | 1680 Handle<Object> result = JSReceiver::SetProperty( |
1695 receiver, name, value, NONE, strict_mode, store_mode); | 1681 receiver, name, value, NONE, strict_mode(), store_mode); |
1696 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 1682 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
1697 return *result; | 1683 return *result; |
1698 } | 1684 } |
1699 | 1685 |
1700 LookupResult lookup(isolate()); | 1686 LookupResult lookup(isolate()); |
1701 bool can_store = LookupForWrite(receiver, name, value, &lookup, &state); | 1687 bool can_store = LookupForWrite(receiver, name, value, &lookup, &state); |
1702 if (!can_store && | 1688 if (!can_store && |
1703 strict_mode == kStrictMode && | 1689 strict_mode() == kStrictMode && |
1704 !(lookup.IsProperty() && lookup.IsReadOnly()) && | 1690 !(lookup.IsProperty() && lookup.IsReadOnly()) && |
1705 IsUndeclaredGlobal(object)) { | 1691 IsUndeclaredGlobal(object)) { |
1706 // Strict mode doesn't allow setting non-existent global property. | 1692 // Strict mode doesn't allow setting non-existent global property. |
1707 return ReferenceError("not_defined", name); | 1693 return ReferenceError("not_defined", name); |
1708 } | 1694 } |
1709 if (use_ic) { | 1695 if (use_ic) { |
1710 if (state == UNINITIALIZED) { | 1696 if (state == UNINITIALIZED) { |
1711 Handle<Code> stub = (strict_mode == kStrictMode) | 1697 Handle<Code> stub = pre_monomorphic_stub(); |
1712 ? pre_monomorphic_stub_strict() | |
1713 : pre_monomorphic_stub(); | |
1714 set_target(*stub); | 1698 set_target(*stub); |
1715 TRACE_IC("StoreIC", name, state, *stub); | 1699 TRACE_IC("StoreIC", name, state, *stub); |
1716 } else if (can_store) { | 1700 } else if (can_store) { |
1717 UpdateCaches(&lookup, state, strict_mode, receiver, name, value); | 1701 UpdateCaches(&lookup, state, receiver, name, value); |
1718 } else if (!name->IsCacheable(isolate()) || | 1702 } else if (!name->IsCacheable(isolate()) || |
1719 lookup.IsNormal() || | 1703 lookup.IsNormal() || |
1720 (lookup.IsField() && lookup.CanHoldValue(value))) { | 1704 (lookup.IsField() && lookup.CanHoldValue(value))) { |
1721 Handle<Code> stub = (strict_mode == kStrictMode) ? generic_stub_strict() | 1705 Handle<Code> stub = generic_stub(); |
1722 : generic_stub(); | |
1723 set_target(*stub); | 1706 set_target(*stub); |
1724 } | 1707 } |
1725 } | 1708 } |
1726 | 1709 |
1727 // Set the property. | 1710 // Set the property. |
1728 Handle<Object> result = JSReceiver::SetProperty( | 1711 Handle<Object> result = JSReceiver::SetProperty( |
1729 receiver, name, value, NONE, strict_mode, store_mode); | 1712 receiver, name, value, NONE, strict_mode(), store_mode); |
1730 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 1713 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
1731 return *result; | 1714 return *result; |
1732 } | 1715 } |
1733 | 1716 |
1734 | 1717 |
1735 void StoreIC::UpdateCaches(LookupResult* lookup, | 1718 void StoreIC::UpdateCaches(LookupResult* lookup, |
1736 State state, | 1719 State state, |
1737 StrictModeFlag strict_mode, | |
1738 Handle<JSObject> receiver, | 1720 Handle<JSObject> receiver, |
1739 Handle<String> name, | 1721 Handle<String> name, |
1740 Handle<Object> value) { | 1722 Handle<Object> value) { |
1741 ASSERT(!receiver->IsJSGlobalProxy()); | 1723 ASSERT(!receiver->IsJSGlobalProxy()); |
1742 ASSERT(lookup->IsFound()); | 1724 ASSERT(lookup->IsFound()); |
1743 | 1725 |
1744 // These are not cacheable, so we never see such LookupResults here. | 1726 // These are not cacheable, so we never see such LookupResults here. |
1745 ASSERT(!lookup->IsHandler()); | 1727 ASSERT(!lookup->IsHandler()); |
1746 | 1728 |
1747 Handle<Code> code = ComputeStoreMonomorphic( | 1729 Handle<Code> code = ComputeStoreMonomorphic(lookup, receiver, name, value); |
1748 lookup, strict_mode, receiver, name, value); | |
1749 if (code.is_null()) { | 1730 if (code.is_null()) { |
1750 Handle<Code> stub = strict_mode == kStrictMode | 1731 set_target(*generic_stub()); |
1751 ? generic_stub_strict() : generic_stub(); | |
1752 set_target(*stub); | |
1753 return; | 1732 return; |
1754 } | 1733 } |
1755 | 1734 |
1756 PatchCache(state, strict_mode, receiver, name, code); | 1735 PatchCache(state, receiver, name, code); |
1757 TRACE_IC("StoreIC", name, state, target()); | 1736 TRACE_IC("StoreIC", name, state, target()); |
1758 } | 1737 } |
1759 | 1738 |
1760 | 1739 |
1761 Handle<Code> StoreIC::ComputeStoreMonomorphic(LookupResult* lookup, | 1740 Handle<Code> StoreIC::ComputeStoreMonomorphic(LookupResult* lookup, |
1762 StrictModeFlag strict_mode, | |
1763 Handle<JSObject> receiver, | 1741 Handle<JSObject> receiver, |
1764 Handle<String> name, | 1742 Handle<String> name, |
1765 Handle<Object> value) { | 1743 Handle<Object> value) { |
1766 Handle<JSObject> holder(lookup->holder()); | 1744 Handle<JSObject> holder(lookup->holder()); |
1767 switch (lookup->type()) { | 1745 switch (lookup->type()) { |
1768 case FIELD: | 1746 case FIELD: |
1769 return isolate()->stub_cache()->ComputeStoreField( | 1747 return isolate()->stub_cache()->ComputeStoreField( |
1770 name, receiver, lookup, strict_mode); | 1748 name, receiver, lookup, strict_mode()); |
1771 case NORMAL: | 1749 case NORMAL: |
1772 if (receiver->IsGlobalObject()) { | 1750 if (receiver->IsGlobalObject()) { |
1773 // The stub generated for the global object picks the value directly | 1751 // The stub generated for the global object picks the value directly |
1774 // from the property cell. So the property must be directly on the | 1752 // from the property cell. So the property must be directly on the |
1775 // global object. | 1753 // global object. |
1776 Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver); | 1754 Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver); |
1777 Handle<PropertyCell> cell( | 1755 Handle<PropertyCell> cell( |
1778 global->GetPropertyCell(lookup), isolate()); | 1756 global->GetPropertyCell(lookup), isolate()); |
1779 return isolate()->stub_cache()->ComputeStoreGlobal( | 1757 return isolate()->stub_cache()->ComputeStoreGlobal( |
1780 name, global, cell, value, strict_mode); | 1758 name, global, cell, value, strict_mode()); |
1781 } | 1759 } |
1782 ASSERT(holder.is_identical_to(receiver)); | 1760 ASSERT(holder.is_identical_to(receiver)); |
1783 return isolate()->stub_cache()->ComputeStoreNormal(strict_mode); | 1761 return isolate()->stub_cache()->ComputeStoreNormal(strict_mode()); |
1784 case CALLBACKS: { | 1762 case CALLBACKS: { |
1785 Handle<Object> callback(lookup->GetCallbackObject(), isolate()); | 1763 Handle<Object> callback(lookup->GetCallbackObject(), isolate()); |
1786 if (callback->IsExecutableAccessorInfo()) { | 1764 if (callback->IsExecutableAccessorInfo()) { |
1787 Handle<ExecutableAccessorInfo> info = | 1765 Handle<ExecutableAccessorInfo> info = |
1788 Handle<ExecutableAccessorInfo>::cast(callback); | 1766 Handle<ExecutableAccessorInfo>::cast(callback); |
1789 if (v8::ToCData<Address>(info->setter()) == 0) break; | 1767 if (v8::ToCData<Address>(info->setter()) == 0) break; |
1790 if (!holder->HasFastProperties()) break; | 1768 if (!holder->HasFastProperties()) break; |
1791 if (!info->IsCompatibleReceiver(*receiver)) break; | 1769 if (!info->IsCompatibleReceiver(*receiver)) break; |
1792 return isolate()->stub_cache()->ComputeStoreCallback( | 1770 return isolate()->stub_cache()->ComputeStoreCallback( |
1793 name, receiver, holder, info, strict_mode); | 1771 name, receiver, holder, info, strict_mode()); |
1794 } else if (callback->IsAccessorPair()) { | 1772 } else if (callback->IsAccessorPair()) { |
1795 Handle<Object> setter( | 1773 Handle<Object> setter( |
1796 Handle<AccessorPair>::cast(callback)->setter(), isolate()); | 1774 Handle<AccessorPair>::cast(callback)->setter(), isolate()); |
1797 if (!setter->IsJSFunction()) break; | 1775 if (!setter->IsJSFunction()) break; |
1798 if (holder->IsGlobalObject()) break; | 1776 if (holder->IsGlobalObject()) break; |
1799 if (!holder->HasFastProperties()) break; | 1777 if (!holder->HasFastProperties()) break; |
1800 Handle<JSFunction> function = Handle<JSFunction>::cast(setter); | 1778 Handle<JSFunction> function = Handle<JSFunction>::cast(setter); |
1801 CallOptimization call_optimization(function); | 1779 CallOptimization call_optimization(function); |
1802 if (call_optimization.is_simple_api_call() && | 1780 if (call_optimization.is_simple_api_call() && |
1803 call_optimization.IsCompatibleReceiver(*receiver)) { | 1781 call_optimization.IsCompatibleReceiver(*receiver)) { |
1804 return isolate()->stub_cache()->ComputeStoreCallback( | 1782 return isolate()->stub_cache()->ComputeStoreCallback( |
1805 name, receiver, holder, call_optimization, strict_mode); | 1783 name, receiver, holder, call_optimization, strict_mode()); |
1806 } | 1784 } |
1807 return isolate()->stub_cache()->ComputeStoreViaSetter( | 1785 return isolate()->stub_cache()->ComputeStoreViaSetter( |
1808 name, receiver, holder, Handle<JSFunction>::cast(setter), | 1786 name, receiver, holder, Handle<JSFunction>::cast(setter), |
1809 strict_mode); | 1787 strict_mode()); |
1810 } | 1788 } |
1811 // TODO(dcarney): Handle correctly. | 1789 // TODO(dcarney): Handle correctly. |
1812 if (callback->IsDeclaredAccessorInfo()) break; | 1790 if (callback->IsDeclaredAccessorInfo()) break; |
1813 ASSERT(callback->IsForeign()); | 1791 ASSERT(callback->IsForeign()); |
1814 // No IC support for old-style native accessors. | 1792 // No IC support for old-style native accessors. |
1815 break; | 1793 break; |
1816 } | 1794 } |
1817 case INTERCEPTOR: | 1795 case INTERCEPTOR: |
1818 ASSERT(!receiver->GetNamedInterceptor()->setter()->IsUndefined()); | 1796 ASSERT(!receiver->GetNamedInterceptor()->setter()->IsUndefined()); |
1819 return isolate()->stub_cache()->ComputeStoreInterceptor( | 1797 return isolate()->stub_cache()->ComputeStoreInterceptor( |
1820 name, receiver, strict_mode); | 1798 name, receiver, strict_mode()); |
1821 case CONSTANT: | 1799 case CONSTANT: |
1822 break; | 1800 break; |
1823 case TRANSITION: { | 1801 case TRANSITION: { |
1824 // Explicitly pass in the receiver map since LookupForWrite may have | 1802 // Explicitly pass in the receiver map since LookupForWrite may have |
1825 // stored something else than the receiver in the holder. | 1803 // stored something else than the receiver in the holder. |
1826 Handle<Map> transition( | 1804 Handle<Map> transition( |
1827 lookup->GetTransitionTarget(receiver->map()), isolate()); | 1805 lookup->GetTransitionTarget(receiver->map()), isolate()); |
1828 int descriptor = transition->LastAdded(); | 1806 int descriptor = transition->LastAdded(); |
1829 | 1807 |
1830 DescriptorArray* target_descriptors = transition->instance_descriptors(); | 1808 DescriptorArray* target_descriptors = transition->instance_descriptors(); |
1831 PropertyDetails details = target_descriptors->GetDetails(descriptor); | 1809 PropertyDetails details = target_descriptors->GetDetails(descriptor); |
1832 | 1810 |
1833 if (details.type() == CALLBACKS || details.attributes() != NONE) break; | 1811 if (details.type() == CALLBACKS || details.attributes() != NONE) break; |
1834 | 1812 |
1835 return isolate()->stub_cache()->ComputeStoreTransition( | 1813 return isolate()->stub_cache()->ComputeStoreTransition( |
1836 name, receiver, lookup, transition, strict_mode); | 1814 name, receiver, lookup, transition, strict_mode()); |
1837 } | 1815 } |
1838 case NONEXISTENT: | 1816 case NONEXISTENT: |
1839 case HANDLER: | 1817 case HANDLER: |
1840 UNREACHABLE(); | 1818 UNREACHABLE(); |
1841 break; | 1819 break; |
1842 } | 1820 } |
1843 return Handle<Code>::null(); | 1821 return Handle<Code>::null(); |
1844 } | 1822 } |
1845 | 1823 |
1846 | 1824 |
1847 Handle<Code> KeyedStoreIC::StoreElementStub(Handle<JSObject> receiver, | 1825 Handle<Code> KeyedStoreIC::StoreElementStub(Handle<JSObject> receiver, |
1848 KeyedAccessStoreMode store_mode, | 1826 KeyedAccessStoreMode store_mode) { |
1849 StrictModeFlag strict_mode) { | |
1850 // Don't handle megamorphic property accesses for INTERCEPTORS or CALLBACKS | 1827 // Don't handle megamorphic property accesses for INTERCEPTORS or CALLBACKS |
1851 // via megamorphic stubs, since they don't have a map in their relocation info | 1828 // via megamorphic stubs, since they don't have a map in their relocation info |
1852 // and so the stubs can't be harvested for the object needed for a map check. | 1829 // and so the stubs can't be harvested for the object needed for a map check. |
1853 if (target()->type() != Code::NORMAL) { | 1830 if (target()->type() != Code::NORMAL) { |
1854 TRACE_GENERIC_IC(isolate(), "KeyedIC", "non-NORMAL target type"); | 1831 TRACE_GENERIC_IC(isolate(), "KeyedIC", "non-NORMAL target type"); |
1855 return strict_mode == kStrictMode ? generic_stub_strict() : generic_stub(); | 1832 return generic_stub(); |
1856 } | 1833 } |
1857 | 1834 |
1858 State ic_state = target()->ic_state(); | 1835 State ic_state = target()->ic_state(); |
1859 Handle<Map> receiver_map(receiver->map(), isolate()); | 1836 Handle<Map> receiver_map(receiver->map(), isolate()); |
1860 if (ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) { | 1837 if (ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) { |
1861 // Optimistically assume that ICs that haven't reached the MONOMORPHIC state | 1838 // Optimistically assume that ICs that haven't reached the MONOMORPHIC state |
1862 // yet will do so and stay there. | 1839 // yet will do so and stay there. |
1863 Handle<Map> monomorphic_map = ComputeTransitionedMap(receiver, store_mode); | 1840 Handle<Map> monomorphic_map = ComputeTransitionedMap(receiver, store_mode); |
1864 store_mode = GetNonTransitioningStoreMode(store_mode); | 1841 store_mode = GetNonTransitioningStoreMode(store_mode); |
1865 return isolate()->stub_cache()->ComputeKeyedStoreElement( | 1842 return isolate()->stub_cache()->ComputeKeyedStoreElement( |
1866 monomorphic_map, strict_mode, store_mode); | 1843 monomorphic_map, strict_mode(), store_mode); |
1867 } | 1844 } |
1868 | 1845 |
1869 MapHandleList target_receiver_maps; | 1846 MapHandleList target_receiver_maps; |
1870 target()->FindAllMaps(&target_receiver_maps); | 1847 target()->FindAllMaps(&target_receiver_maps); |
1871 if (target_receiver_maps.length() == 0) { | 1848 if (target_receiver_maps.length() == 0) { |
1872 // In the case that there is a non-map-specific IC is installed (e.g. keyed | 1849 // In the case that there is a non-map-specific IC is installed (e.g. keyed |
1873 // stores into properties in dictionary mode), then there will be not | 1850 // stores into properties in dictionary mode), then there will be not |
1874 // receiver maps in the target. | 1851 // receiver maps in the target. |
1875 return strict_mode == kStrictMode | 1852 return generic_stub(); |
1876 ? generic_stub_strict() | |
1877 : generic_stub(); | |
1878 } | 1853 } |
1879 | 1854 |
1880 // There are several special cases where an IC that is MONOMORPHIC can still | 1855 // There are several special cases where an IC that is MONOMORPHIC can still |
1881 // transition to a different GetNonTransitioningStoreMode IC that handles a | 1856 // transition to a different GetNonTransitioningStoreMode IC that handles a |
1882 // superset of the original IC. Handle those here if the receiver map hasn't | 1857 // superset of the original IC. Handle those here if the receiver map hasn't |
1883 // changed or it has transitioned to a more general kind. | 1858 // changed or it has transitioned to a more general kind. |
1884 KeyedAccessStoreMode old_store_mode = | 1859 KeyedAccessStoreMode old_store_mode = |
1885 Code::GetKeyedAccessStoreMode(target()->extra_ic_state()); | 1860 Code::GetKeyedAccessStoreMode(target()->extra_ic_state()); |
1886 Handle<Map> previous_receiver_map = target_receiver_maps.at(0); | 1861 Handle<Map> previous_receiver_map = target_receiver_maps.at(0); |
1887 if (ic_state == MONOMORPHIC) { | 1862 if (ic_state == MONOMORPHIC) { |
1888 // If the "old" and "new" maps are in the same elements map family, stay | 1863 // If the "old" and "new" maps are in the same elements map family, stay |
1889 // MONOMORPHIC and use the map for the most generic ElementsKind. | 1864 // MONOMORPHIC and use the map for the most generic ElementsKind. |
1890 Handle<Map> transitioned_receiver_map = receiver_map; | 1865 Handle<Map> transitioned_receiver_map = receiver_map; |
1891 if (IsTransitionStoreMode(store_mode)) { | 1866 if (IsTransitionStoreMode(store_mode)) { |
1892 transitioned_receiver_map = | 1867 transitioned_receiver_map = |
1893 ComputeTransitionedMap(receiver, store_mode); | 1868 ComputeTransitionedMap(receiver, store_mode); |
1894 } | 1869 } |
1895 if (IsTransitionedMapOfMonomorphicTarget(*transitioned_receiver_map)) { | 1870 if (IsTransitionedMapOfMonomorphicTarget(*transitioned_receiver_map)) { |
1896 // Element family is the same, use the "worst" case map. | 1871 // Element family is the same, use the "worst" case map. |
1897 store_mode = GetNonTransitioningStoreMode(store_mode); | 1872 store_mode = GetNonTransitioningStoreMode(store_mode); |
1898 return isolate()->stub_cache()->ComputeKeyedStoreElement( | 1873 return isolate()->stub_cache()->ComputeKeyedStoreElement( |
1899 transitioned_receiver_map, strict_mode, store_mode); | 1874 transitioned_receiver_map, strict_mode(), store_mode); |
1900 } else if (*previous_receiver_map == receiver->map() && | 1875 } else if (*previous_receiver_map == receiver->map() && |
1901 old_store_mode == STANDARD_STORE && | 1876 old_store_mode == STANDARD_STORE && |
1902 (IsGrowStoreMode(store_mode) || | 1877 (IsGrowStoreMode(store_mode) || |
1903 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || | 1878 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || |
1904 store_mode == STORE_NO_TRANSITION_HANDLE_COW)) { | 1879 store_mode == STORE_NO_TRANSITION_HANDLE_COW)) { |
1905 // A "normal" IC that handles stores can switch to a version that can | 1880 // A "normal" IC that handles stores can switch to a version that can |
1906 // grow at the end of the array, handle OOB accesses or copy COW arrays | 1881 // grow at the end of the array, handle OOB accesses or copy COW arrays |
1907 // and still stay MONOMORPHIC. | 1882 // and still stay MONOMORPHIC. |
1908 return isolate()->stub_cache()->ComputeKeyedStoreElement( | 1883 return isolate()->stub_cache()->ComputeKeyedStoreElement( |
1909 receiver_map, strict_mode, store_mode); | 1884 receiver_map, strict_mode(), store_mode); |
1910 } | 1885 } |
1911 } | 1886 } |
1912 | 1887 |
1913 ASSERT(ic_state != GENERIC); | 1888 ASSERT(ic_state != GENERIC); |
1914 | 1889 |
1915 bool map_added = | 1890 bool map_added = |
1916 AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map); | 1891 AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map); |
1917 | 1892 |
1918 if (IsTransitionStoreMode(store_mode)) { | 1893 if (IsTransitionStoreMode(store_mode)) { |
1919 Handle<Map> transitioned_receiver_map = | 1894 Handle<Map> transitioned_receiver_map = |
1920 ComputeTransitionedMap(receiver, store_mode); | 1895 ComputeTransitionedMap(receiver, store_mode); |
1921 map_added |= AddOneReceiverMapIfMissing(&target_receiver_maps, | 1896 map_added |= AddOneReceiverMapIfMissing(&target_receiver_maps, |
1922 transitioned_receiver_map); | 1897 transitioned_receiver_map); |
1923 } | 1898 } |
1924 | 1899 |
1925 if (!map_added) { | 1900 if (!map_added) { |
1926 // If the miss wasn't due to an unseen map, a polymorphic stub | 1901 // If the miss wasn't due to an unseen map, a polymorphic stub |
1927 // won't help, use the generic stub. | 1902 // won't help, use the generic stub. |
1928 TRACE_GENERIC_IC(isolate(), "KeyedIC", "same map added twice"); | 1903 TRACE_GENERIC_IC(isolate(), "KeyedIC", "same map added twice"); |
1929 return strict_mode == kStrictMode ? generic_stub_strict() : generic_stub(); | 1904 return generic_stub(); |
1930 } | 1905 } |
1931 | 1906 |
1932 // If the maximum number of receiver maps has been exceeded, use the generic | 1907 // If the maximum number of receiver maps has been exceeded, use the generic |
1933 // version of the IC. | 1908 // version of the IC. |
1934 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) { | 1909 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) { |
1935 TRACE_GENERIC_IC(isolate(), "KeyedIC", "max polymorph exceeded"); | 1910 TRACE_GENERIC_IC(isolate(), "KeyedIC", "max polymorph exceeded"); |
1936 return strict_mode == kStrictMode ? generic_stub_strict() : generic_stub(); | 1911 return generic_stub(); |
1937 } | 1912 } |
1938 | 1913 |
1939 // Make sure all polymorphic handlers have the same store mode, otherwise the | 1914 // Make sure all polymorphic handlers have the same store mode, otherwise the |
1940 // generic stub must be used. | 1915 // generic stub must be used. |
1941 store_mode = GetNonTransitioningStoreMode(store_mode); | 1916 store_mode = GetNonTransitioningStoreMode(store_mode); |
1942 if (old_store_mode != STANDARD_STORE) { | 1917 if (old_store_mode != STANDARD_STORE) { |
1943 if (store_mode == STANDARD_STORE) { | 1918 if (store_mode == STANDARD_STORE) { |
1944 store_mode = old_store_mode; | 1919 store_mode = old_store_mode; |
1945 } else if (store_mode != old_store_mode) { | 1920 } else if (store_mode != old_store_mode) { |
1946 TRACE_GENERIC_IC(isolate(), "KeyedIC", "store mode mismatch"); | 1921 TRACE_GENERIC_IC(isolate(), "KeyedIC", "store mode mismatch"); |
1947 return strict_mode == kStrictMode | 1922 return generic_stub(); |
1948 ? generic_stub_strict() | |
1949 : generic_stub(); | |
1950 } | 1923 } |
1951 } | 1924 } |
1952 | 1925 |
1953 // If the store mode isn't the standard mode, make sure that all polymorphic | 1926 // If the store mode isn't the standard mode, make sure that all polymorphic |
1954 // receivers are either external arrays, or all "normal" arrays. Otherwise, | 1927 // receivers are either external arrays, or all "normal" arrays. Otherwise, |
1955 // use the generic stub. | 1928 // use the generic stub. |
1956 if (store_mode != STANDARD_STORE) { | 1929 if (store_mode != STANDARD_STORE) { |
1957 int external_arrays = 0; | 1930 int external_arrays = 0; |
1958 for (int i = 0; i < target_receiver_maps.length(); ++i) { | 1931 for (int i = 0; i < target_receiver_maps.length(); ++i) { |
1959 if (target_receiver_maps[i]->has_external_array_elements()) { | 1932 if (target_receiver_maps[i]->has_external_array_elements()) { |
1960 external_arrays++; | 1933 external_arrays++; |
1961 } | 1934 } |
1962 } | 1935 } |
1963 if (external_arrays != 0 && | 1936 if (external_arrays != 0 && |
1964 external_arrays != target_receiver_maps.length()) { | 1937 external_arrays != target_receiver_maps.length()) { |
1965 TRACE_GENERIC_IC(isolate(), "KeyedIC", | 1938 TRACE_GENERIC_IC(isolate(), "KeyedIC", |
1966 "unsupported combination of external and normal arrays"); | 1939 "unsupported combination of external and normal arrays"); |
1967 return strict_mode == kStrictMode | 1940 return generic_stub(); |
1968 ? generic_stub_strict() | |
1969 : generic_stub(); | |
1970 } | 1941 } |
1971 } | 1942 } |
1972 | 1943 |
1973 return isolate()->stub_cache()->ComputeStoreElementPolymorphic( | 1944 return isolate()->stub_cache()->ComputeStoreElementPolymorphic( |
1974 &target_receiver_maps, store_mode, strict_mode); | 1945 &target_receiver_maps, store_mode, strict_mode()); |
1975 } | 1946 } |
1976 | 1947 |
1977 | 1948 |
1978 Handle<Map> KeyedStoreIC::ComputeTransitionedMap( | 1949 Handle<Map> KeyedStoreIC::ComputeTransitionedMap( |
1979 Handle<JSObject> receiver, | 1950 Handle<JSObject> receiver, |
1980 KeyedAccessStoreMode store_mode) { | 1951 KeyedAccessStoreMode store_mode) { |
1981 switch (store_mode) { | 1952 switch (store_mode) { |
1982 case STORE_TRANSITION_SMI_TO_OBJECT: | 1953 case STORE_TRANSITION_SMI_TO_OBJECT: |
1983 case STORE_TRANSITION_DOUBLE_TO_OBJECT: | 1954 case STORE_TRANSITION_DOUBLE_TO_OBJECT: |
1984 case STORE_AND_GROW_TRANSITION_SMI_TO_OBJECT: | 1955 case STORE_AND_GROW_TRANSITION_SMI_TO_OBJECT: |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2088 if (receiver->elements()->map() == heap->fixed_cow_array_map()) { | 2059 if (receiver->elements()->map() == heap->fixed_cow_array_map()) { |
2089 return STORE_NO_TRANSITION_HANDLE_COW; | 2060 return STORE_NO_TRANSITION_HANDLE_COW; |
2090 } else { | 2061 } else { |
2091 return STANDARD_STORE; | 2062 return STANDARD_STORE; |
2092 } | 2063 } |
2093 } | 2064 } |
2094 } | 2065 } |
2095 | 2066 |
2096 | 2067 |
2097 MaybeObject* KeyedStoreIC::Store(State state, | 2068 MaybeObject* KeyedStoreIC::Store(State state, |
2098 StrictModeFlag strict_mode, | |
2099 Handle<Object> object, | 2069 Handle<Object> object, |
2100 Handle<Object> key, | 2070 Handle<Object> key, |
2101 Handle<Object> value, | 2071 Handle<Object> value, |
2102 ICMissMode miss_mode) { | 2072 ICMissMode miss_mode) { |
2103 // Check for values that can be converted into an internalized string directly | 2073 // Check for values that can be converted into an internalized string directly |
2104 // or is representable as a smi. | 2074 // or is representable as a smi. |
2105 key = TryConvertKey(key, isolate()); | 2075 key = TryConvertKey(key, isolate()); |
2106 | 2076 |
2107 if (key->IsInternalizedString()) { | 2077 if (key->IsInternalizedString()) { |
2108 return StoreIC::Store(state, | 2078 return StoreIC::Store(state, |
2109 strict_mode, | |
2110 object, | 2079 object, |
2111 Handle<String>::cast(key), | 2080 Handle<String>::cast(key), |
2112 value, | 2081 value, |
2113 JSReceiver::MAY_BE_STORE_FROM_KEYED); | 2082 JSReceiver::MAY_BE_STORE_FROM_KEYED); |
2114 } | 2083 } |
2115 | 2084 |
2116 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded() && | 2085 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded() && |
2117 !(FLAG_harmony_observation && object->IsJSObject() && | 2086 !(FLAG_harmony_observation && object->IsJSObject() && |
2118 JSObject::cast(*object)->map()->is_observed()); | 2087 JSObject::cast(*object)->map()->is_observed()); |
2119 if (use_ic && !object->IsSmi()) { | 2088 if (use_ic && !object->IsSmi()) { |
2120 // Don't use ICs for maps of the objects in Array's prototype chain. We | 2089 // Don't use ICs for maps of the objects in Array's prototype chain. We |
2121 // expect to be able to trap element sets to objects with those maps in the | 2090 // expect to be able to trap element sets to objects with those maps in the |
2122 // runtime to enable optimization of element hole access. | 2091 // runtime to enable optimization of element hole access. |
2123 Handle<HeapObject> heap_object = Handle<HeapObject>::cast(object); | 2092 Handle<HeapObject> heap_object = Handle<HeapObject>::cast(object); |
2124 if (heap_object->map()->IsMapInArrayPrototypeChain()) use_ic = false; | 2093 if (heap_object->map()->IsMapInArrayPrototypeChain()) use_ic = false; |
2125 } | 2094 } |
2126 ASSERT(!(use_ic && object->IsJSGlobalProxy())); | 2095 ASSERT(!(use_ic && object->IsJSGlobalProxy())); |
2127 | 2096 |
2128 if (use_ic) { | 2097 if (use_ic) { |
2129 Handle<Code> stub = (strict_mode == kStrictMode) | 2098 Handle<Code> stub = generic_stub(); |
2130 ? generic_stub_strict() | |
2131 : generic_stub(); | |
2132 if (miss_mode != MISS_FORCE_GENERIC) { | 2099 if (miss_mode != MISS_FORCE_GENERIC) { |
2133 if (object->IsJSObject()) { | 2100 if (object->IsJSObject()) { |
2134 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 2101 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
2135 if (receiver->map()->is_deprecated()) { | 2102 if (receiver->map()->is_deprecated()) { |
2136 JSObject::MigrateInstance(receiver); | 2103 JSObject::MigrateInstance(receiver); |
2137 } | 2104 } |
2138 bool key_is_smi_like = key->IsSmi() || !key->ToSmi()->IsFailure(); | 2105 bool key_is_smi_like = key->IsSmi() || !key->ToSmi()->IsFailure(); |
2139 if (receiver->elements()->map() == | 2106 if (receiver->elements()->map() == |
2140 isolate()->heap()->non_strict_arguments_elements_map()) { | 2107 isolate()->heap()->non_strict_arguments_elements_map()) { |
2141 stub = non_strict_arguments_stub(); | 2108 stub = non_strict_arguments_stub(); |
2142 } else if (key_is_smi_like && | 2109 } else if (key_is_smi_like && |
2143 (target() != *non_strict_arguments_stub())) { | 2110 (target() != *non_strict_arguments_stub())) { |
2144 KeyedAccessStoreMode store_mode = GetStoreMode(receiver, key, value); | 2111 KeyedAccessStoreMode store_mode = GetStoreMode(receiver, key, value); |
2145 stub = StoreElementStub(receiver, store_mode, strict_mode); | 2112 stub = StoreElementStub(receiver, store_mode); |
2146 } else { | 2113 } else { |
2147 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "key not a number"); | 2114 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "key not a number"); |
2148 } | 2115 } |
2149 } else { | 2116 } else { |
2150 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "not an object"); | 2117 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "not an object"); |
2151 } | 2118 } |
2152 } else { | 2119 } else { |
2153 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "force generic"); | 2120 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "force generic"); |
2154 } | 2121 } |
2155 ASSERT(!stub.is_null()); | 2122 ASSERT(!stub.is_null()); |
2156 set_target(*stub); | 2123 set_target(*stub); |
2157 TRACE_IC("KeyedStoreIC", key, state, target()); | 2124 TRACE_IC("KeyedStoreIC", key, state, target()); |
2158 } | 2125 } |
2159 | 2126 |
2160 return Runtime::SetObjectPropertyOrFail( | 2127 return Runtime::SetObjectPropertyOrFail( |
2161 isolate(), object , key, value, NONE, strict_mode); | 2128 isolate(), object , key, value, NONE, strict_mode()); |
2162 } | 2129 } |
2163 | 2130 |
2164 | 2131 |
2165 Handle<Code> KeyedStoreIC::ComputeStoreMonomorphic(LookupResult* lookup, | 2132 Handle<Code> KeyedStoreIC::ComputeStoreMonomorphic(LookupResult* lookup, |
2166 StrictModeFlag strict_mode, | |
2167 Handle<JSObject> receiver, | 2133 Handle<JSObject> receiver, |
2168 Handle<String> name, | 2134 Handle<String> name, |
2169 Handle<Object> value) { | 2135 Handle<Object> value) { |
2170 // If the property has a non-field type allowing map transitions | 2136 // If the property has a non-field type allowing map transitions |
2171 // where there is extra room in the object, we leave the IC in its | 2137 // where there is extra room in the object, we leave the IC in its |
2172 // current state. | 2138 // current state. |
2173 switch (lookup->type()) { | 2139 switch (lookup->type()) { |
2174 case FIELD: | 2140 case FIELD: |
2175 return isolate()->stub_cache()->ComputeKeyedStoreField( | 2141 return isolate()->stub_cache()->ComputeKeyedStoreField( |
2176 name, receiver, lookup, strict_mode); | 2142 name, receiver, lookup, strict_mode()); |
2177 case TRANSITION: { | 2143 case TRANSITION: { |
2178 // Explicitly pass in the receiver map since LookupForWrite may have | 2144 // Explicitly pass in the receiver map since LookupForWrite may have |
2179 // stored something else than the receiver in the holder. | 2145 // stored something else than the receiver in the holder. |
2180 Handle<Map> transition( | 2146 Handle<Map> transition( |
2181 lookup->GetTransitionTarget(receiver->map()), isolate()); | 2147 lookup->GetTransitionTarget(receiver->map()), isolate()); |
2182 int descriptor = transition->LastAdded(); | 2148 int descriptor = transition->LastAdded(); |
2183 | 2149 |
2184 DescriptorArray* target_descriptors = transition->instance_descriptors(); | 2150 DescriptorArray* target_descriptors = transition->instance_descriptors(); |
2185 PropertyDetails details = target_descriptors->GetDetails(descriptor); | 2151 PropertyDetails details = target_descriptors->GetDetails(descriptor); |
2186 | 2152 |
2187 if (details.type() != CALLBACKS && details.attributes() == NONE) { | 2153 if (details.type() != CALLBACKS && details.attributes() == NONE) { |
2188 return isolate()->stub_cache()->ComputeKeyedStoreTransition( | 2154 return isolate()->stub_cache()->ComputeKeyedStoreTransition( |
2189 name, receiver, lookup, transition, strict_mode); | 2155 name, receiver, lookup, transition, strict_mode()); |
2190 } | 2156 } |
2191 // fall through. | 2157 // fall through. |
2192 } | 2158 } |
2193 case NORMAL: | 2159 case NORMAL: |
2194 case CONSTANT: | 2160 case CONSTANT: |
2195 case CALLBACKS: | 2161 case CALLBACKS: |
2196 case INTERCEPTOR: | 2162 case INTERCEPTOR: |
2197 // Always rewrite to the generic case so that we do not | 2163 // Always rewrite to the generic case so that we do not |
2198 // repeatedly try to rewrite. | 2164 // repeatedly try to rewrite. |
2199 return (strict_mode == kStrictMode) | 2165 return generic_stub(); |
2200 ? generic_stub_strict() | |
2201 : generic_stub(); | |
2202 case HANDLER: | 2166 case HANDLER: |
2203 case NONEXISTENT: | 2167 case NONEXISTENT: |
2204 UNREACHABLE(); | 2168 UNREACHABLE(); |
2205 break; | 2169 break; |
2206 } | 2170 } |
2207 return Handle<Code>::null(); | 2171 return Handle<Code>::null(); |
2208 } | 2172 } |
2209 | 2173 |
2210 | 2174 |
2211 #undef TRACE_IC | 2175 #undef TRACE_IC |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2302 MISS_FORCE_GENERIC); | 2266 MISS_FORCE_GENERIC); |
2303 } | 2267 } |
2304 | 2268 |
2305 | 2269 |
2306 // Used from ic-<arch>.cc. | 2270 // Used from ic-<arch>.cc. |
2307 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Miss) { | 2271 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Miss) { |
2308 HandleScope scope(isolate); | 2272 HandleScope scope(isolate); |
2309 ASSERT(args.length() == 3); | 2273 ASSERT(args.length() == 3); |
2310 StoreIC ic(IC::NO_EXTRA_FRAME, isolate); | 2274 StoreIC ic(IC::NO_EXTRA_FRAME, isolate); |
2311 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 2275 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); |
2312 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); | |
2313 return ic.Store(state, | 2276 return ic.Store(state, |
2314 Code::GetStrictMode(extra_ic_state), | |
2315 args.at<Object>(0), | 2277 args.at<Object>(0), |
2316 args.at<String>(1), | 2278 args.at<String>(1), |
2317 args.at<Object>(2)); | 2279 args.at<Object>(2)); |
2318 } | 2280 } |
2319 | 2281 |
2320 | 2282 |
2321 RUNTIME_FUNCTION(MaybeObject*, StoreIC_MissFromStubFailure) { | 2283 RUNTIME_FUNCTION(MaybeObject*, StoreIC_MissFromStubFailure) { |
2322 HandleScope scope(isolate); | 2284 HandleScope scope(isolate); |
2323 ASSERT(args.length() == 3); | 2285 ASSERT(args.length() == 3); |
2324 StoreIC ic(IC::EXTRA_CALL_FRAME, isolate); | 2286 StoreIC ic(IC::EXTRA_CALL_FRAME, isolate); |
2325 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 2287 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); |
2326 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); | |
2327 return ic.Store(state, | 2288 return ic.Store(state, |
2328 Code::GetStrictMode(extra_ic_state), | |
2329 args.at<Object>(0), | 2289 args.at<Object>(0), |
2330 args.at<String>(1), | 2290 args.at<String>(1), |
2331 args.at<Object>(2)); | 2291 args.at<Object>(2)); |
2332 } | 2292 } |
2333 | 2293 |
2334 | 2294 |
2335 RUNTIME_FUNCTION(MaybeObject*, StoreIC_ArrayLength) { | 2295 RUNTIME_FUNCTION(MaybeObject*, StoreIC_ArrayLength) { |
2336 SealHandleScope shs(isolate); | 2296 SealHandleScope shs(isolate); |
2337 | 2297 |
2338 ASSERT(args.length() == 2); | 2298 ASSERT(args.length() == 2); |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2405 return value; | 2365 return value; |
2406 } | 2366 } |
2407 | 2367 |
2408 | 2368 |
2409 // Used from ic-<arch>.cc. | 2369 // Used from ic-<arch>.cc. |
2410 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Miss) { | 2370 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Miss) { |
2411 HandleScope scope(isolate); | 2371 HandleScope scope(isolate); |
2412 ASSERT(args.length() == 3); | 2372 ASSERT(args.length() == 3); |
2413 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate); | 2373 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate); |
2414 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 2374 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); |
2415 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); | |
2416 return ic.Store(state, | 2375 return ic.Store(state, |
2417 Code::GetStrictMode(extra_ic_state), | |
2418 args.at<Object>(0), | 2376 args.at<Object>(0), |
2419 args.at<Object>(1), | 2377 args.at<Object>(1), |
2420 args.at<Object>(2), | 2378 args.at<Object>(2), |
2421 MISS); | 2379 MISS); |
2422 } | 2380 } |
2423 | 2381 |
2424 | 2382 |
2425 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissFromStubFailure) { | 2383 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissFromStubFailure) { |
2426 HandleScope scope(isolate); | 2384 HandleScope scope(isolate); |
2427 ASSERT(args.length() == 3); | 2385 ASSERT(args.length() == 3); |
2428 KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate); | 2386 KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate); |
2429 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 2387 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); |
2430 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); | |
2431 return ic.Store(state, | 2388 return ic.Store(state, |
2432 Code::GetStrictMode(extra_ic_state), | |
2433 args.at<Object>(0), | 2389 args.at<Object>(0), |
2434 args.at<Object>(1), | 2390 args.at<Object>(1), |
2435 args.at<Object>(2), | 2391 args.at<Object>(2), |
2436 MISS); | 2392 MISS); |
2437 } | 2393 } |
2438 | 2394 |
2439 | 2395 |
2440 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Slow) { | 2396 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Slow) { |
2441 SealHandleScope shs(isolate); | 2397 SealHandleScope shs(isolate); |
2442 ASSERT(args.length() == 3); | 2398 ASSERT(args.length() == 3); |
(...skipping 28 matching lines...) Expand all Loading... |
2471 NONE, | 2427 NONE, |
2472 strict_mode); | 2428 strict_mode); |
2473 } | 2429 } |
2474 | 2430 |
2475 | 2431 |
2476 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissForceGeneric) { | 2432 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissForceGeneric) { |
2477 HandleScope scope(isolate); | 2433 HandleScope scope(isolate); |
2478 ASSERT(args.length() == 3); | 2434 ASSERT(args.length() == 3); |
2479 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate); | 2435 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate); |
2480 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 2436 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); |
2481 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); | |
2482 return ic.Store(state, | 2437 return ic.Store(state, |
2483 Code::GetStrictMode(extra_ic_state), | |
2484 args.at<Object>(0), | 2438 args.at<Object>(0), |
2485 args.at<Object>(1), | 2439 args.at<Object>(1), |
2486 args.at<Object>(2), | 2440 args.at<Object>(2), |
2487 MISS_FORCE_GENERIC); | 2441 MISS_FORCE_GENERIC); |
2488 } | 2442 } |
2489 | 2443 |
2490 | 2444 |
2491 RUNTIME_FUNCTION(MaybeObject*, ElementsTransitionAndStoreIC_Miss) { | 2445 RUNTIME_FUNCTION(MaybeObject*, ElementsTransitionAndStoreIC_Miss) { |
2492 SealHandleScope scope(isolate); | 2446 SealHandleScope scope(isolate); |
2493 ASSERT(args.length() == 4); | 2447 ASSERT(args.length() == 4); |
(...skipping 608 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3102 #undef ADDR | 3056 #undef ADDR |
3103 }; | 3057 }; |
3104 | 3058 |
3105 | 3059 |
3106 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 3060 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
3107 return IC_utilities[id]; | 3061 return IC_utilities[id]; |
3108 } | 3062 } |
3109 | 3063 |
3110 | 3064 |
3111 } } // namespace v8::internal | 3065 } } // namespace v8::internal |
OLD | NEW |