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

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

Powered by Google App Engine
This is Rietveld 408576698