Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(178)

Side by Side Diff: src/ic.cc

Issue 25090002: Make strict_mode a flag on StoreIC. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Move setting strictmode to the constructor Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« src/ic.h ('K') | « src/ic.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« src/ic.h ('K') | « src/ic.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698