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

Side by Side Diff: src/ic.cc

Issue 6894003: Better support for 'polymorphic' JS and external arrays (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: review feedback and merge Created 9 years, 7 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
OLDNEW
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. 1 // Copyright 2011 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
11 // with the distribution. 11 // with the distribution.
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
60 60
61 void IC::TraceIC(const char* type, 61 void IC::TraceIC(const char* type,
62 Handle<Object> name, 62 Handle<Object> name,
63 State old_state, 63 State old_state,
64 Code* new_target, 64 Code* new_target,
65 const char* extra_info) { 65 const char* extra_info) {
66 if (FLAG_trace_ic) { 66 if (FLAG_trace_ic) {
67 State new_state = StateFrom(new_target, 67 State new_state = StateFrom(new_target,
68 HEAP->undefined_value(), 68 HEAP->undefined_value(),
69 HEAP->undefined_value()); 69 HEAP->undefined_value());
70 PrintF("[%s (%c->%c)%s", type, 70 PrintF("[%s in ", type);
71 StackFrameIterator it;
72 while (it.frame()->fp() != this->fp()) it.Advance();
73 StackFrame* raw_frame = it.frame();
74 if (raw_frame->is_internal()) {
75 Isolate* isolate = new_target->GetIsolate();
76 Code* apply_builtin = isolate->builtins()->builtin(
77 Builtins::kFunctionApply);
78 if (raw_frame->unchecked_code() == apply_builtin) {
79 PrintF("apply from ");
80 it.Advance();
81 raw_frame = it.frame();
82 }
83 }
84 if (raw_frame->is_java_script()) {
85 JavaScriptFrame* frame = JavaScriptFrame::cast(raw_frame);
86 Code* js_code = frame->unchecked_code();
87 // Find the function on the stack and both the active code for the
88 // function and the original code.
89 JSFunction* function = JSFunction::cast(frame->function());
90 function->PrintName();
91 int code_offset = address() - js_code->instruction_start();
92 PrintF("+%d", code_offset);
93 } else {
94 PrintF("<unknown>");
95 }
96 PrintF(" (%c->%c)%s",
71 TransitionMarkFromState(old_state), 97 TransitionMarkFromState(old_state),
72 TransitionMarkFromState(new_state), 98 TransitionMarkFromState(new_state),
73 extra_info); 99 extra_info);
74 name->Print(); 100 name->Print();
75 PrintF("]\n"); 101 PrintF("]\n");
76 } 102 }
77 } 103 }
78 #endif 104 #endif
79 105
80 106
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
267 293
268 void IC::Clear(Address address) { 294 void IC::Clear(Address address) {
269 Code* target = GetTargetAtAddress(address); 295 Code* target = GetTargetAtAddress(address);
270 296
271 // Don't clear debug break inline cache as it will remove the break point. 297 // Don't clear debug break inline cache as it will remove the break point.
272 if (target->ic_state() == DEBUG_BREAK) return; 298 if (target->ic_state() == DEBUG_BREAK) return;
273 299
274 switch (target->kind()) { 300 switch (target->kind()) {
275 case Code::LOAD_IC: return LoadIC::Clear(address, target); 301 case Code::LOAD_IC: return LoadIC::Clear(address, target);
276 case Code::KEYED_LOAD_IC: 302 case Code::KEYED_LOAD_IC:
277 case Code::KEYED_EXTERNAL_ARRAY_LOAD_IC:
278 return KeyedLoadIC::Clear(address, target); 303 return KeyedLoadIC::Clear(address, target);
279 case Code::STORE_IC: return StoreIC::Clear(address, target); 304 case Code::STORE_IC: return StoreIC::Clear(address, target);
280 case Code::KEYED_STORE_IC: 305 case Code::KEYED_STORE_IC:
281 case Code::KEYED_EXTERNAL_ARRAY_STORE_IC:
282 return KeyedStoreIC::Clear(address, target); 306 return KeyedStoreIC::Clear(address, target);
283 case Code::CALL_IC: return CallIC::Clear(address, target); 307 case Code::CALL_IC: return CallIC::Clear(address, target);
284 case Code::KEYED_CALL_IC: return KeyedCallIC::Clear(address, target); 308 case Code::KEYED_CALL_IC: return KeyedCallIC::Clear(address, target);
285 case Code::TYPE_RECORDING_UNARY_OP_IC: 309 case Code::TYPE_RECORDING_UNARY_OP_IC:
286 case Code::TYPE_RECORDING_BINARY_OP_IC: 310 case Code::TYPE_RECORDING_BINARY_OP_IC:
287 case Code::COMPARE_IC: 311 case Code::COMPARE_IC:
288 // Clearing these is tricky and does not 312 // Clearing these is tricky and does not
289 // make any performance difference. 313 // make any performance difference.
290 return; 314 return;
291 default: UNREACHABLE(); 315 default: UNREACHABLE();
(...skipping 732 matching lines...) Expand 10 before | Expand all | Expand 10 after
1024 1048
1025 isolate()->stub_cache()->Set(*name, map, Code::cast(code)); 1049 isolate()->stub_cache()->Set(*name, map, Code::cast(code));
1026 } 1050 }
1027 1051
1028 #ifdef DEBUG 1052 #ifdef DEBUG
1029 TraceIC("LoadIC", name, state, target()); 1053 TraceIC("LoadIC", name, state, target());
1030 #endif 1054 #endif
1031 } 1055 }
1032 1056
1033 1057
1058 String* KeyedLoadIC::GetStubNameForCache(IC::State ic_state) {
1059 if (ic_state == MONOMORPHIC) {
1060 return isolate()->heap()->KeyedLoadSpecializedMonomorphic_symbol();
1061 } else {
1062 ASSERT(ic_state == MEGAMORPHIC);
1063 return isolate()->heap()->KeyedLoadSpecializedPolymorphic_symbol();
1064 }
1065 }
1066
1067
1068 MaybeObject* KeyedLoadIC::GetFastElementStubWithoutMapCheck(
1069 bool is_js_array) {
1070 return KeyedLoadFastElementStub().TryGetCode();
1071 }
1072
1073
1074 MaybeObject* KeyedLoadIC::GetExternalArrayStubWithoutMapCheck(
1075 ExternalArrayType array_type) {
1076 return KeyedLoadExternalArrayStub(array_type).TryGetCode();
1077 }
1078
1079
1080 MaybeObject* KeyedLoadIC::ConstructMegamorphicStub(
1081 MapList* receiver_maps,
1082 CodeList* targets,
1083 StrictModeFlag strict_mode) {
1084 Object* object;
1085 KeyedLoadStubCompiler compiler;
1086 MaybeObject* maybe_code = compiler.CompileLoadMegamorphic(receiver_maps,
1087 targets);
1088 if (!maybe_code->ToObject(&object)) return maybe_code;
1089 isolate()->counters()->keyed_load_polymorphic_stubs()->Increment();
1090 PROFILE(isolate(), CodeCreateEvent(
1091 Logger::KEYED_LOAD_MEGAMORPHIC_IC_TAG,
1092 Code::cast(object), 0));
1093 return object;
1094 }
1095
1096
1034 MaybeObject* KeyedLoadIC::Load(State state, 1097 MaybeObject* KeyedLoadIC::Load(State state,
1035 Handle<Object> object, 1098 Handle<Object> object,
1036 Handle<Object> key) { 1099 Handle<Object> key,
1100 bool force_generic_stub) {
1037 // Check for values that can be converted into a symbol. 1101 // Check for values that can be converted into a symbol.
1038 // TODO(1295): Remove this code. 1102 // TODO(1295): Remove this code.
1039 HandleScope scope(isolate()); 1103 HandleScope scope(isolate());
1040 if (key->IsHeapNumber() && 1104 if (key->IsHeapNumber() &&
1041 isnan(HeapNumber::cast(*key)->value())) { 1105 isnan(HeapNumber::cast(*key)->value())) {
1042 key = isolate()->factory()->nan_symbol(); 1106 key = isolate()->factory()->nan_symbol();
1043 } else if (key->IsUndefined()) { 1107 } else if (key->IsUndefined()) {
1044 key = isolate()->factory()->undefined_symbol(); 1108 key = isolate()->factory()->undefined_symbol();
1045 } 1109 }
1046 1110
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
1152 1216
1153 return object->GetProperty(*object, &lookup, *name, &attr); 1217 return object->GetProperty(*object, &lookup, *name, &attr);
1154 } 1218 }
1155 1219
1156 // Do not use ICs for objects that require access checks (including 1220 // Do not use ICs for objects that require access checks (including
1157 // the global object). 1221 // the global object).
1158 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded(); 1222 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded();
1159 1223
1160 if (use_ic) { 1224 if (use_ic) {
1161 Code* stub = generic_stub(); 1225 Code* stub = generic_stub();
1162 if (state == UNINITIALIZED) { 1226 if (!force_generic_stub) {
1163 if (object->IsString() && key->IsNumber()) { 1227 if (object->IsString() && key->IsNumber()) {
1164 stub = string_stub(); 1228 if (state == UNINITIALIZED) {
1229 stub = string_stub();
1230 }
1165 } else if (object->IsJSObject()) { 1231 } else if (object->IsJSObject()) {
1166 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 1232 JSObject* receiver = JSObject::cast(*object);
1167 if (receiver->HasExternalArrayElements()) { 1233 if (receiver->HasIndexedInterceptor()) {
1168 MaybeObject* probe =
1169 isolate()->stub_cache()->ComputeKeyedLoadOrStoreExternalArray(
1170 *receiver, false, kNonStrictMode);
1171 stub = probe->IsFailure() ?
1172 NULL : Code::cast(probe->ToObjectUnchecked());
1173 } else if (receiver->HasIndexedInterceptor()) {
1174 stub = indexed_interceptor_stub(); 1234 stub = indexed_interceptor_stub();
1175 } else if (key->IsSmi() && 1235 } else if (key->IsSmi()) {
1176 receiver->map()->has_fast_elements()) { 1236 MaybeObject* maybe_stub = ComputeStub(receiver,
1177 MaybeObject* probe = 1237 false,
1178 isolate()->stub_cache()->ComputeKeyedLoadSpecialized(*receiver); 1238 kNonStrictMode,
1179 stub = probe->IsFailure() ? 1239 stub);
1180 NULL : Code::cast(probe->ToObjectUnchecked()); 1240 stub = maybe_stub->IsFailure() ?
1241 NULL : Code::cast(maybe_stub->ToObjectUnchecked());
1181 } 1242 }
1182 } 1243 }
1183 } 1244 }
1184 if (stub != NULL) set_target(stub); 1245 if (stub != NULL) set_target(stub);
1246 }
1185 1247
1186 #ifdef DEBUG 1248 #ifdef DEBUG
1187 TraceIC("KeyedLoadIC", key, state, target()); 1249 TraceIC("KeyedLoadIC", key, state, target());
1188 #endif // DEBUG 1250 #endif // DEBUG
1189 }
1190 1251
1191 // Get the property. 1252 // Get the property.
1192 return Runtime::GetObjectProperty(isolate(), object, key); 1253 return Runtime::GetObjectProperty(isolate(), object, key);
1193 } 1254 }
1194 1255
1195 1256
1196 void KeyedLoadIC::UpdateCaches(LookupResult* lookup, State state, 1257 void KeyedLoadIC::UpdateCaches(LookupResult* lookup, State state,
1197 Handle<Object> object, Handle<String> name) { 1258 Handle<Object> object, Handle<String> name) {
1198 // Bail out if we didn't find a result. 1259 // Bail out if we didn't find a result.
1199 if (!lookup->IsProperty() || !lookup->IsCacheable()) return; 1260 if (!lookup->IsProperty() || !lookup->IsCacheable()) return;
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after
1476 receiver->map(), 1537 receiver->map(),
1477 Code::cast(code)); 1538 Code::cast(code));
1478 } 1539 }
1479 1540
1480 #ifdef DEBUG 1541 #ifdef DEBUG
1481 TraceIC("StoreIC", name, state, target()); 1542 TraceIC("StoreIC", name, state, target());
1482 #endif 1543 #endif
1483 } 1544 }
1484 1545
1485 1546
1547 static bool AddOneReceiverMapIfMissing(MapList* receiver_maps,
1548 Map* new_receiver_map) {
1549 for (int current = 0; current < receiver_maps->length(); ++current) {
1550 if (receiver_maps->at(current) == new_receiver_map) {
1551 return false;
1552 }
1553 }
1554 receiver_maps->Add(new_receiver_map);
1555 return true;
1556 }
1557
1558
1559 void KeyedIC::GetReceiverMapsForStub(Code* stub, MapList* result) {
1560 ASSERT(stub->is_inline_cache_stub());
1561 if (stub == string_stub()) {
1562 return result->Add(isolate()->heap()->string_map());
1563 } else if (stub->is_keyed_load_stub() || stub->is_keyed_store_stub()) {
1564 if (stub->ic_state() == MONOMORPHIC) {
1565 result->Add(Map::cast(stub->FindFirstMap()));
1566 } else {
1567 ASSERT(stub->ic_state() == MEGAMORPHIC);
1568 AssertNoAllocation no_allocation;
1569 int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
1570 for (RelocIterator it(stub, mask); !it.done(); it.next()) {
1571 RelocInfo* info = it.rinfo();
1572 Object* object = info->target_object();
1573 ASSERT(object->IsMap());
1574 result->Add(Map::cast(object));
1575 }
1576 }
1577 }
1578 }
1579
1580
1581 MaybeObject* KeyedIC::ComputeStub(JSObject* receiver,
1582 bool is_store,
1583 StrictModeFlag strict_mode,
1584 Code* generic_stub) {
1585 State ic_state = target()->ic_state();
1586 Code* monomorphic_stub;
1587 // Always compute the MONOMORPHIC stub, even if the MEGAMORPHIC stub ends up
1588 // being used. This is necessary because the megamorphic stub needs to have
1589 // access to more information than what is stored in the receiver map in some
1590 // cases (external arrays need the array type from the MONOMORPHIC stub).
Mads Ager (chromium) 2011/05/12 09:42:47 I don't know how much that will happen, but we sho
danno 2011/06/01 13:16:08 It's not the easy here, unfortunately. We need to
1591 MaybeObject* maybe_stub = ComputeMonomorphicStub(receiver,
1592 is_store,
1593 strict_mode,
1594 generic_stub);
1595 if (!maybe_stub->To(&monomorphic_stub)) return maybe_stub;
1596
1597 if (ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) {
1598 return monomorphic_stub;
1599 }
1600 ASSERT(target() != generic_stub);
1601
1602 // Don't handle megamorphic property accesses for INTERCEPTORS or CALLBACKS
1603 // via megamorphic stubs, since they don't have a map in their relocation info
1604 // and so the stubs can't be harvested for the object needed for a map check.
1605 if (target()->type() != NORMAL) {
1606 return generic_stub;
1607 }
1608
1609 // Determine the list of receiver maps that this call site has seen,
1610 // adding the map that was just encountered.
1611 MapList target_receiver_maps;
1612 GetReceiverMapsForStub(target(), &target_receiver_maps);
1613 if (!AddOneReceiverMapIfMissing(&target_receiver_maps, receiver->map())) {
1614 // If the miss wasn't due to an unseen map, a MEGAMORPHIC stub
1615 // won't help, use the generic stub.
1616 return generic_stub;
1617 }
1618
1619 // TODO(1385): Currently MEGAMORPHIC stubs are cached in the receiver map stub
1620 // cache, but that can put receiver types together from unrelated call sites
1621 // into the same stub--they always handle the union of all receiver maps seen
1622 // at all call sites involving the receiver map. This is only an
1623 // approximation: ideally, there would be a global cache that mapped sets of
1624 // receiver maps to MEGAMORPHIC stubs. The complexity of the MEGAMORPHIC stub
1625 // computation also leads to direct manipulation of the stub cache from the IC
1626 // code, which the global cache solution would avoid.
1627 Code::Kind kind = this->kind();
1628 Code::Flags flags = Code::ComputeFlags(kind,
1629 NOT_IN_LOOP,
1630 MEGAMORPHIC,
1631 strict_mode);
1632 String* megamorphic_name = GetStubNameForCache(MEGAMORPHIC);
1633 Object* maybe_cached_stub = receiver->map()->FindInCodeCache(megamorphic_name,
1634 flags);
1635
1636 // Create a set of all receiver maps that have been seen at the IC call site
1637 // and those seen by the MEGAMORPHIC cached stub, if that's the stub that's
1638 // been selected.
1639 MapList receiver_maps;
1640 if (!maybe_cached_stub->IsUndefined()) {
1641 GetReceiverMapsForStub(Code::cast(maybe_cached_stub), &receiver_maps);
1642 }
1643 bool added_map = false;
1644 for (int i = 0; i < target_receiver_maps.length(); ++i) {
1645 if (AddOneReceiverMapIfMissing(&receiver_maps,
1646 target_receiver_maps.at(i))) {
1647 added_map = true;
1648 }
1649 }
1650 ASSERT(receiver_maps.length() > 0);
1651
1652 // If the maximum number of receiver maps has been exceeded, use the Generic
1653 // version of the IC.
1654 if (receiver_maps.length() > KeyedIC::kMaxKeyedPolymorphism) {
1655 return generic_stub;
1656 }
1657
1658 // If no maps have been seen at the call site that aren't in the cached
1659 // stub, then use it.
1660 if (!added_map) {
1661 ASSERT(!maybe_cached_stub->IsUndefined());
1662 ASSERT(maybe_cached_stub->IsCode());
1663 return Code::cast(maybe_cached_stub);
1664 }
1665
1666 // Lookup all of the receiver maps in the cache, they should all already
1667 // have MONOMORPHIC stubs.
1668 CodeList handler_ics(KeyedIC::kMaxKeyedPolymorphism);
1669 for (int current = 0; current < receiver_maps.length(); ++current) {
1670 Map* receiver_map(receiver_maps.at(current));
1671 MaybeObject* maybe_cached_stub = ComputeMonomorphicStubWithoutMapCheck(
1672 receiver_map,
1673 strict_mode,
1674 generic_stub);
1675 Code* cached_stub;
1676 if (!maybe_cached_stub->To(&cached_stub)) {
1677 return maybe_cached_stub;
1678 }
1679 handler_ics.Add(cached_stub);
1680 }
1681
1682 Code* stub;
1683 // Build the MEGAMORPHIC stub.
1684 maybe_stub = ConstructMegamorphicStub(&receiver_maps,
1685 &handler_ics,
1686 strict_mode);
1687 if (!maybe_stub->To(&stub)) return maybe_stub;
1688
1689 MaybeObject* maybe_update = receiver->UpdateMapCodeCache(
1690 megamorphic_name,
1691 stub);
1692 if (maybe_update->IsFailure()) return maybe_update;
1693 return stub;
1694 }
1695
1696
1697 MaybeObject* KeyedIC::ComputeMonomorphicStubWithoutMapCheck(
1698 Map* receiver_map,
1699 StrictModeFlag strict_mode,
1700 Code* generic_stub) {
1701 if ((receiver_map->instance_type() & kNotStringTag) == 0) {
1702 ASSERT(string_stub() != NULL);
1703 return string_stub();
1704 } else if (receiver_map->has_external_array_elements()) {
1705 // Determine the array type from the default MONOMORPHIC already generated
1706 // stub. There is no other way to determine the type of the external array
1707 // directly from the receiver type.
1708 Code::Kind kind = this->kind();
1709 Code::Flags flags = Code::ComputeMonomorphicFlags(kind,
1710 NORMAL,
1711 strict_mode);
1712 String* monomorphic_name = GetStubNameForCache(MONOMORPHIC);
1713 Object* maybe_default_stub = receiver_map->FindInCodeCache(monomorphic_name,
1714 flags);
1715 if (maybe_default_stub->IsUndefined()) {
1716 return generic_stub;
1717 }
1718 Code* default_stub = Code::cast(maybe_default_stub);
1719 return GetExternalArrayStubWithoutMapCheck(
1720 default_stub->external_array_type());
1721 } else if (receiver_map->has_fast_elements()) {
1722 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
1723 return GetFastElementStubWithoutMapCheck(is_js_array);
1724 } else {
1725 return generic_stub;
1726 }
1727 }
1728
1729
1730 MaybeObject* KeyedIC::ComputeMonomorphicStub(JSObject* receiver,
1731 bool is_store,
1732 StrictModeFlag strict_mode,
1733 Code* generic_stub) {
1734 Code* result = NULL;
1735 if (receiver->HasExternalArrayElements()) {
1736 MaybeObject* maybe_stub =
1737 isolate()->stub_cache()->ComputeKeyedLoadOrStoreExternalArray(
1738 receiver, is_store, strict_mode);
1739 if (!maybe_stub->To(&result)) return maybe_stub;
1740 } else if (receiver->map()->has_fast_elements()) {
1741 MaybeObject* maybe_stub =
1742 isolate()->stub_cache()->ComputeKeyedLoadOrStoreFastElement(
1743 receiver, is_store, strict_mode);
1744 if (!maybe_stub->To(&result)) return maybe_stub;
1745 } else {
1746 result = generic_stub;
1747 }
1748 return result;
1749 }
1750
1751
1752 String* KeyedStoreIC::GetStubNameForCache(IC::State ic_state) {
1753 if (ic_state == MONOMORPHIC) {
1754 return isolate()->heap()->KeyedStoreSpecializedMonomorphic_symbol();
1755 } else {
1756 ASSERT(ic_state == MEGAMORPHIC);
1757 return isolate()->heap()->KeyedStoreSpecializedPolymorphic_symbol();
1758 }
1759 }
1760
1761
1762 MaybeObject* KeyedStoreIC::GetFastElementStubWithoutMapCheck(
1763 bool is_js_array) {
1764 return KeyedStoreFastElementStub(is_js_array).TryGetCode();
1765 }
1766
1767
1768 MaybeObject* KeyedStoreIC::GetExternalArrayStubWithoutMapCheck(
1769 ExternalArrayType array_type) {
1770 return KeyedStoreExternalArrayStub(array_type).TryGetCode();
1771 }
1772
1773
1774 MaybeObject* KeyedStoreIC::ConstructMegamorphicStub(
1775 MapList* receiver_maps,
1776 CodeList* targets,
1777 StrictModeFlag strict_mode) {
1778 Object* object;
1779 KeyedStoreStubCompiler compiler(strict_mode);
1780 MaybeObject* maybe_code = compiler.CompileStoreMegamorphic(receiver_maps,
1781 targets);
1782 if (!maybe_code->ToObject(&object)) return maybe_code;
1783 isolate()->counters()->keyed_store_polymorphic_stubs()->Increment();
1784 PROFILE(isolate(), CodeCreateEvent(
1785 Logger::KEYED_STORE_MEGAMORPHIC_IC_TAG,
1786 Code::cast(object), 0));
1787 return object;
1788 }
1789
1790
1486 MaybeObject* KeyedStoreIC::Store(State state, 1791 MaybeObject* KeyedStoreIC::Store(State state,
1487 StrictModeFlag strict_mode, 1792 StrictModeFlag strict_mode,
1488 Handle<Object> object, 1793 Handle<Object> object,
1489 Handle<Object> key, 1794 Handle<Object> key,
1490 Handle<Object> value) { 1795 Handle<Object> value,
1796 bool force_generic) {
1491 if (key->IsSymbol()) { 1797 if (key->IsSymbol()) {
1492 Handle<String> name = Handle<String>::cast(key); 1798 Handle<String> name = Handle<String>::cast(key);
1493 1799
1494 // If the object is undefined or null it's illegal to try to set any 1800 // If the object is undefined or null it's illegal to try to set any
1495 // properties on it; throw a TypeError in that case. 1801 // properties on it; throw a TypeError in that case.
1496 if (object->IsUndefined() || object->IsNull()) { 1802 if (object->IsUndefined() || object->IsNull()) {
1497 return TypeError("non_object_property_store", object, name); 1803 return TypeError("non_object_property_store", object, name);
1498 } 1804 }
1499 1805
1500 // Ignore stores where the receiver is not a JSObject. 1806 // Ignore stores where the receiver is not a JSObject.
(...skipping 21 matching lines...) Expand all
1522 // Set the property. 1828 // Set the property.
1523 return receiver->SetProperty(*name, *value, NONE, strict_mode); 1829 return receiver->SetProperty(*name, *value, NONE, strict_mode);
1524 } 1830 }
1525 1831
1526 // Do not use ICs for objects that require access checks (including 1832 // Do not use ICs for objects that require access checks (including
1527 // the global object). 1833 // the global object).
1528 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded(); 1834 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded();
1529 ASSERT(!(use_ic && object->IsJSGlobalProxy())); 1835 ASSERT(!(use_ic && object->IsJSGlobalProxy()));
1530 1836
1531 if (use_ic) { 1837 if (use_ic) {
1532 Code* stub = 1838 Code* stub = (strict_mode == kStrictMode)
1533 (strict_mode == kStrictMode) ? generic_stub_strict() : generic_stub(); 1839 ? generic_stub_strict()
1534 if (state == UNINITIALIZED) { 1840 : generic_stub();
1535 if (object->IsJSObject()) { 1841 if (!force_generic) {
1536 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 1842 if (object->IsJSObject() && key->IsSmi()) {
1537 if (receiver->HasExternalArrayElements()) { 1843 JSObject* receiver = JSObject::cast(*object);
1538 MaybeObject* probe = 1844 MaybeObject* maybe_stub = ComputeStub(receiver,
1539 isolate()->stub_cache()->ComputeKeyedLoadOrStoreExternalArray( 1845 true,
1540 *receiver, true, strict_mode); 1846 strict_mode,
1541 stub = probe->IsFailure() ? 1847 stub);
1542 NULL : Code::cast(probe->ToObjectUnchecked()); 1848 stub = maybe_stub->IsFailure() ?
1543 } else if (key->IsSmi() && receiver->map()->has_fast_elements()) { 1849 NULL : Code::cast(maybe_stub->ToObjectUnchecked());
1544 MaybeObject* probe =
1545 isolate()->stub_cache()->ComputeKeyedStoreSpecialized(
1546 *receiver, strict_mode);
1547 stub = probe->IsFailure() ?
1548 NULL : Code::cast(probe->ToObjectUnchecked());
1549 }
1550 } 1850 }
1551 } 1851 }
1552 if (stub != NULL) set_target(stub); 1852 if (stub != NULL) set_target(stub);
1553 } 1853 }
1554 1854
1855 #ifdef DEBUG
1856 TraceIC("KeyedStoreIC", key, state, target());
1857 #endif
1858
1555 // Set the property. 1859 // Set the property.
1556 return Runtime::SetObjectProperty( 1860 return Runtime::SetObjectProperty(
1557 isolate(), object , key, value, NONE, strict_mode); 1861 isolate(), object , key, value, NONE, strict_mode);
1558 } 1862 }
1559 1863
1560 1864
1561 void KeyedStoreIC::UpdateCaches(LookupResult* lookup, 1865 void KeyedStoreIC::UpdateCaches(LookupResult* lookup,
1562 State state, 1866 State state,
1563 StrictModeFlag strict_mode, 1867 StrictModeFlag strict_mode,
1564 Handle<JSObject> receiver, 1868 Handle<JSObject> receiver,
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
1713 return ic.Load(state, args.at<Object>(0), args.at<String>(1)); 2017 return ic.Load(state, args.at<Object>(0), args.at<String>(1));
1714 } 2018 }
1715 2019
1716 2020
1717 // Used from ic-<arch>.cc 2021 // Used from ic-<arch>.cc
1718 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_Miss) { 2022 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_Miss) {
1719 NoHandleAllocation na; 2023 NoHandleAllocation na;
1720 ASSERT(args.length() == 2); 2024 ASSERT(args.length() == 2);
1721 KeyedLoadIC ic(isolate); 2025 KeyedLoadIC ic(isolate);
1722 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); 2026 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
1723 return ic.Load(state, args.at<Object>(0), args.at<Object>(1)); 2027 return ic.Load(state, args.at<Object>(0), args.at<Object>(1), false);
1724 } 2028 }
1725 2029
1726 2030
2031 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissForceGeneric) {
2032 NoHandleAllocation na;
2033 ASSERT(args.length() == 2);
2034 KeyedLoadIC ic(isolate);
2035 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
2036 return ic.Load(state, args.at<Object>(0), args.at<Object>(1), true);
2037 }
2038
2039
1727 // Used from ic-<arch>.cc. 2040 // Used from ic-<arch>.cc.
1728 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Miss) { 2041 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Miss) {
1729 NoHandleAllocation na; 2042 NoHandleAllocation na;
1730 ASSERT(args.length() == 3); 2043 ASSERT(args.length() == 3);
1731 StoreIC ic(isolate); 2044 StoreIC ic(isolate);
1732 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); 2045 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
1733 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); 2046 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
1734 return ic.Store(state, 2047 return ic.Store(state,
1735 static_cast<StrictModeFlag>(extra_ic_state & kStrictMode), 2048 static_cast<StrictModeFlag>(extra_ic_state & kStrictMode),
1736 args.at<Object>(0), 2049 args.at<Object>(0),
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
1797 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Miss) { 2110 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Miss) {
1798 NoHandleAllocation na; 2111 NoHandleAllocation na;
1799 ASSERT(args.length() == 3); 2112 ASSERT(args.length() == 3);
1800 KeyedStoreIC ic(isolate); 2113 KeyedStoreIC ic(isolate);
1801 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); 2114 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
1802 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); 2115 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
1803 return ic.Store(state, 2116 return ic.Store(state,
1804 static_cast<StrictModeFlag>(extra_ic_state & kStrictMode), 2117 static_cast<StrictModeFlag>(extra_ic_state & kStrictMode),
1805 args.at<Object>(0), 2118 args.at<Object>(0),
1806 args.at<Object>(1), 2119 args.at<Object>(1),
1807 args.at<Object>(2)); 2120 args.at<Object>(2),
2121 false);
1808 } 2122 }
1809 2123
1810 2124
2125 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Slow) {
2126 NoHandleAllocation na;
2127 ASSERT(args.length() == 3);
2128 KeyedStoreIC ic(isolate);
2129 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
2130 Handle<Object> object = args.at<Object>(0);
2131 Handle<Object> key = args.at<Object>(1);
2132 Handle<Object> value = args.at<Object>(2);
2133 StrictModeFlag strict_mode =
2134 static_cast<StrictModeFlag>(extra_ic_state & kStrictMode);
2135 return Runtime::SetObjectProperty(isolate,
2136 object,
2137 key,
2138 value,
2139 NONE,
2140 strict_mode);
2141 }
2142
2143
2144 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissForceGeneric) {
2145 NoHandleAllocation na;
2146 ASSERT(args.length() == 3);
2147 KeyedStoreIC ic(isolate);
2148 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
2149 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
2150 return ic.Store(state,
2151 static_cast<StrictModeFlag>(extra_ic_state & kStrictMode),
2152 args.at<Object>(0),
2153 args.at<Object>(1),
2154 args.at<Object>(2),
2155 true);
2156 }
2157
2158
1811 void TRUnaryOpIC::patch(Code* code) { 2159 void TRUnaryOpIC::patch(Code* code) {
1812 set_target(code); 2160 set_target(code);
1813 } 2161 }
1814 2162
1815 2163
1816 const char* TRUnaryOpIC::GetName(TypeInfo type_info) { 2164 const char* TRUnaryOpIC::GetName(TypeInfo type_info) {
1817 switch (type_info) { 2165 switch (type_info) {
1818 case UNINITIALIZED: return "Uninitialized"; 2166 case UNINITIALIZED: return "Uninitialized";
1819 case SMI: return "Smi"; 2167 case SMI: return "Smi";
1820 case HEAP_NUMBER: return "HeapNumbers"; 2168 case HEAP_NUMBER: return "HeapNumbers";
(...skipping 368 matching lines...) Expand 10 before | Expand all | Expand 10 after
2189 #undef ADDR 2537 #undef ADDR
2190 }; 2538 };
2191 2539
2192 2540
2193 Address IC::AddressFromUtilityId(IC::UtilityId id) { 2541 Address IC::AddressFromUtilityId(IC::UtilityId id) {
2194 return IC_utilities[id]; 2542 return IC_utilities[id];
2195 } 2543 }
2196 2544
2197 2545
2198 } } // namespace v8::internal 2546 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698