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

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: new strategy Created 9 years, 8 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_BINARY_OP_IC: 309 case Code::TYPE_RECORDING_BINARY_OP_IC:
286 case Code::COMPARE_IC: 310 case Code::COMPARE_IC:
287 // Clearing these is tricky and does not 311 // Clearing these is tricky and does not
288 // make any performance difference. 312 // make any performance difference.
289 return; 313 return;
290 default: UNREACHABLE(); 314 default: UNREACHABLE();
291 } 315 }
(...skipping 731 matching lines...) Expand 10 before | Expand all | Expand 10 after
1023 1047
1024 isolate()->stub_cache()->Set(*name, map, Code::cast(code)); 1048 isolate()->stub_cache()->Set(*name, map, Code::cast(code));
1025 } 1049 }
1026 1050
1027 #ifdef DEBUG 1051 #ifdef DEBUG
1028 TraceIC("LoadIC", name, state, target()); 1052 TraceIC("LoadIC", name, state, target());
1029 #endif 1053 #endif
1030 } 1054 }
1031 1055
1032 1056
1057 String* KeyedLoadIC::GetStubNameForCache(IC::State ic_state) {
1058 if (ic_state == MONOMORPHIC) {
1059 return isolate()->heap()->KeyedLoadSpecializedMonomorphic_symbol();
1060 } else {
1061 ASSERT(ic_state == MEGAMORPHIC);
1062 return isolate()->heap()->KeyedLoadSpecializedPolymorphic_symbol();
1063 }
1064 }
1065
1066
1067 MaybeObject* KeyedLoadIC::ConstructSpecializedKeyedIC(
1068 Handle<Map> receiver_map,
1069 StrictModeFlag strict_mode) {
1070 Object* object;
1071 KeyedLoadStubCompiler compiler;
1072 MaybeObject* maybe_code = compiler.CompileLoadSpecialized(receiver_map);
1073 if (!maybe_code->ToObject(&object)) return maybe_code;
1074 PROFILE(isolate(), CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG,
1075 Code::cast(object), 0));
1076 return object;
1077 }
1078
1079
1080 MaybeObject* KeyedLoadIC::ConstructMegamorphicKeyedIC(
1081 ZoneMapList* receiver_maps,
Mads Ager (chromium) 2011/04/28 13:02:01 Do you have a zone at this point? Maybe just use n
1082 ZoneCodeList* 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
1033 MaybeObject* KeyedLoadIC::Load(State state, 1097 MaybeObject* KeyedLoadIC::Load(State state,
1034 Handle<Object> object, 1098 Handle<Object> object,
1035 Handle<Object> key) { 1099 Handle<Object> key,
1100 bool force_generic_stub) {
1036 // Check for values that can be converted into a symbol. 1101 // Check for values that can be converted into a symbol.
1037 // TODO(1295): Remove this code. 1102 // TODO(1295): Remove this code.
1038 HandleScope scope(isolate()); 1103 HandleScope scope(isolate());
1039 if (key->IsHeapNumber() && 1104 if (key->IsHeapNumber() &&
1040 isnan(HeapNumber::cast(*key)->value())) { 1105 isnan(HeapNumber::cast(*key)->value())) {
1041 key = isolate()->factory()->nan_symbol(); 1106 key = isolate()->factory()->nan_symbol();
1042 } else if (key->IsUndefined()) { 1107 } else if (key->IsUndefined()) {
1043 key = isolate()->factory()->undefined_symbol(); 1108 key = isolate()->factory()->undefined_symbol();
1044 } 1109 }
1045 1110
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
1149 return result; 1214 return result;
1150 } 1215 }
1151 1216
1152 return object->GetProperty(*object, &lookup, *name, &attr); 1217 return object->GetProperty(*object, &lookup, *name, &attr);
1153 } 1218 }
1154 1219
1155 // Do not use ICs for objects that require access checks (including 1220 // Do not use ICs for objects that require access checks (including
1156 // the global object). 1221 // the global object).
1157 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded(); 1222 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded();
1158 1223
1224 #ifdef DEBUG
1225 TraceIC("KeyedLoadIC", key, state, target());
1226 #endif // DEBUG
1227
1228 Code* stub = generic_stub();
1159 if (use_ic) { 1229 if (use_ic) {
1160 Code* stub = generic_stub(); 1230 if (!force_generic_stub) {
1161 if (state == UNINITIALIZED) {
1162 if (object->IsString() && key->IsNumber()) { 1231 if (object->IsString() && key->IsNumber()) {
1163 stub = string_stub(); 1232 if (state == UNINITIALIZED) {
1233 stub = string_stub();
1234 }
1164 } else if (object->IsJSObject()) { 1235 } else if (object->IsJSObject()) {
1165 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 1236 JSObject* receiver = JSObject::cast(*object);
1166 if (receiver->HasExternalArrayElements()) { 1237 if (receiver->HasIndexedInterceptor()) {
1167 MaybeObject* probe =
1168 isolate()->stub_cache()->ComputeKeyedLoadOrStoreExternalArray(
1169 *receiver, false, kNonStrictMode);
1170 stub = probe->IsFailure() ?
1171 NULL : Code::cast(probe->ToObjectUnchecked());
1172 } else if (receiver->HasIndexedInterceptor()) {
1173 stub = indexed_interceptor_stub(); 1238 stub = indexed_interceptor_stub();
1174 } else if (key->IsSmi() && 1239 } else if (key->IsSmi()) {
1175 receiver->map()->has_fast_elements()) { 1240 MaybeObject* maybe_stub = ComputeKeyedIC(receiver,
1176 MaybeObject* probe = 1241 false,
1177 isolate()->stub_cache()->ComputeKeyedLoadSpecialized(*receiver); 1242 kNonStrictMode,
1178 stub = probe->IsFailure() ? 1243 stub);
1179 NULL : Code::cast(probe->ToObjectUnchecked()); 1244 if (!maybe_stub->To(&stub)) return maybe_stub;
1180 } 1245 }
1181 } 1246 }
1182 } 1247 }
1183 if (stub != NULL) set_target(stub); 1248 }
1184 1249
1185 #ifdef DEBUG 1250 #ifdef DEBUG
1186 TraceIC("KeyedLoadIC", key, state, target()); 1251 TraceIC("KeyedLoadIC", key, state, stub);
1187 #endif // DEBUG 1252 #endif // DEBUG
1253
1254 HandleScope handle_scope(isolate());
Mads Ager (chromium) 2011/04/28 13:02:01 This is a nasty mix of handlified and non-handlifi
1255 Handle<Code> stub_handle(stub); // Survives possible GC below.
1256
1257 // Get the property.
1258 MaybeObject* result = Runtime::GetObjectProperty(isolate(), object, key);
1259
1260 ASSERT(!result->IsFailure());
1261 if (use_ic) {
1262 ASSERT(*stub_handle != NULL);
1263 set_target(*stub_handle);
1188 } 1264 }
1189 1265
1190 // Get the property. 1266 return result;
1191 return Runtime::GetObjectProperty(isolate(), object, key);
1192 } 1267 }
1193 1268
1194 1269
1195 void KeyedLoadIC::UpdateCaches(LookupResult* lookup, State state, 1270 void KeyedLoadIC::UpdateCaches(LookupResult* lookup, State state,
1196 Handle<Object> object, Handle<String> name) { 1271 Handle<Object> object, Handle<String> name) {
1197 // Bail out if we didn't find a result. 1272 // Bail out if we didn't find a result.
1198 if (!lookup->IsProperty() || !lookup->IsCacheable()) return; 1273 if (!lookup->IsProperty() || !lookup->IsCacheable()) return;
1199 1274
1200 if (!object->IsJSObject()) return; 1275 if (!object->IsJSObject()) return;
1201 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 1276 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
(...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after
1475 receiver->map(), 1550 receiver->map(),
1476 Code::cast(code)); 1551 Code::cast(code));
1477 } 1552 }
1478 1553
1479 #ifdef DEBUG 1554 #ifdef DEBUG
1480 TraceIC("StoreIC", name, state, target()); 1555 TraceIC("StoreIC", name, state, target());
1481 #endif 1556 #endif
1482 } 1557 }
1483 1558
1484 1559
1560 static bool AddOneReceiverMapIfMissing(ZoneMapList* receiver_maps,
1561 Map* new_receiver_map) {
1562 for (int current = 0; current < receiver_maps->length(); ++current) {
1563 if (*(receiver_maps->at(current)) == new_receiver_map) {
1564 return false;
1565 }
1566 }
1567 receiver_maps->Add(Handle<Map>(new_receiver_map));
1568 return true;
1569 }
1570
1571
1572 static ZoneMapList* GetReceiverMapsForStub(Code* stub) {
1573 ASSERT(stub->is_inline_cache_stub());
1574 if (!stub->is_keyed_load_stub() && !stub->is_keyed_store_stub()) {
1575 return new ZoneMapList(KeyedIC::kMaxKeyedPolymorphism);
1576 }
1577 ZoneMapList* result = new ZoneMapList(KeyedIC::kMaxKeyedPolymorphism);
1578 AssertNoAllocation no_allocation;
1579 if (stub->ic_state() == MONOMORPHIC) {
1580 result->Add(Handle<Map>(Map::cast(stub->FindFirstMap())));
1581 } else {
1582 ASSERT(stub->ic_state() == MEGAMORPHIC);
1583 ZoneMapList* result = new ZoneMapList(KeyedIC::kMaxKeyedPolymorphism);
Mads Ager (chromium) 2011/04/28 13:02:01 This looks wrong. You have a local |result| here t
1584 AssertNoAllocation no_allocation;
1585 int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
1586 for (RelocIterator it(stub, mask); !it.done(); it.next()) {
1587 RelocInfo* info = it.rinfo();
1588 Object* object = info->target_object();
1589 ASSERT(object->IsMap());
1590 result->Add(Handle<Map>(Map::cast(object)));
1591 }
1592 }
1593 return result;
1594 }
1595
1596
1597 MaybeObject* KeyedIC::ComputeKeyedIC(JSObject* receiver,
1598 bool is_store,
1599 StrictModeFlag strict_mode,
1600 Code* generic_stub) {
1601 State ic_state = target()->ic_state();
1602 Code* monomorphic_stub = generic_stub;
1603
1604 if (receiver->HasExternalArrayElements()) {
1605 MaybeObject* maybe_stub =
1606 isolate()->stub_cache()->ComputeKeyedLoadOrStoreExternalArray(
1607 receiver, is_store, strict_mode);
1608 if (maybe_stub->IsFailure()) return maybe_stub;
1609 monomorphic_stub = Code::cast(maybe_stub->ToObjectUnchecked());
1610 } else if (receiver->map()->has_fast_elements()) {
1611 HandleScope handle_scope;
Mads Ager (chromium) 2011/04/28 13:02:01 This looks really dangerous. Is this handle scope
1612 Code::Kind kind = this->kind();
1613 Code::Flags flags = Code::ComputeMonomorphicFlags(kind, NORMAL, strict_mode) ;
1614 String* name = GetStubNameForCache(MONOMORPHIC);
1615 Object* maybe_cached_stub = receiver->map()->FindInCodeCache(name, flags);
1616 if (maybe_cached_stub->IsUndefined()) {
1617 MaybeObject* maybe_stub = ConstructSpecializedKeyedIC(
1618 Handle<Map>(receiver->map()),
1619 strict_mode);
1620 if (!maybe_stub->To(&monomorphic_stub)) return maybe_stub;
1621
1622 MaybeObject* maybe_update = receiver->UpdateMapCodeCache(name, monomorphic _stub);
1623 if (maybe_update->IsFailure()) return maybe_update;
1624 } else {
1625 monomorphic_stub = Code::cast(maybe_cached_stub);
1626 }
1627 }
1628
1629 if (ic_state == UNINITIALIZED) {
1630 return monomorphic_stub;
1631 }
1632
1633 ZoneScope zone_scope(DELETE_ON_EXIT);
Mads Ager (chromium) 2011/04/28 13:02:01 The lists here do not seem big enough to require z
1634 HandleScope handle_scope;
Mads Ager (chromium) 2011/04/28 13:02:01 Let's not add HandleScopes here. That makes it ver
1635 // Determine the list of receiver maps that this call site has seen,
1636 // adding the map that was just encountered.
1637 ZoneMapList* target_receiver_maps = GetReceiverMapsForStub(target());
1638 if (!AddOneReceiverMapIfMissing(target_receiver_maps, receiver->map())) {
1639 // If the miss wasn't due to an unseen map, a MEGAMORPHIC stub
1640 // won't help, use the generic stub.
1641 return generic_stub;
1642 }
1643
1644 Code::Kind kind = this->kind();
1645 Code::Flags flags = Code::ComputeFlags(kind, NOT_IN_LOOP, MEGAMORPHIC, strict_ mode);
1646 String* megamorphic_name = GetStubNameForCache(MEGAMORPHIC);
1647 Object* maybe_cached_stub = receiver->map()->FindInCodeCache(megamorphic_name, flags);
1648
1649 // Create a set of all receiver maps that have been seen at the IC call site
1650 // and those seen by the MEGAMORPHIC cached stub, if that's the stub that's
1651 // been selected.
1652 ZoneMapList* receiver_maps = maybe_cached_stub->IsUndefined()
1653 ? new ZoneMapList(KeyedIC::kMaxKeyedPolymorphism)
1654 : GetReceiverMapsForStub(Code::cast(maybe_cached_stub));
1655 bool added_map = false;
1656 for (int i = 0; i < target_receiver_maps->length(); ++i) {
1657 if (AddOneReceiverMapIfMissing(receiver_maps,
1658 *(target_receiver_maps->at(i)))) {
1659 added_map = true;
1660 }
1661 }
1662
1663 // If the maximum number of receiver maps has been exceeded, use the Generic
1664 // version of the IC.
1665 if (receiver_maps->length() > KeyedIC::kMaxKeyedPolymorphism) {
1666 return generic_stub;
1667 }
1668
1669 // If no maps have been seen at the call site that aren't in the cached
1670 // stub, then use it.
1671 if (!added_map) {
1672 ASSERT(!maybe_cached_stub->IsUndefined());
1673 ASSERT(maybe_cached_stub->IsCode());
1674 return Code::cast(maybe_cached_stub);
1675 }
1676
1677 // Lookup all of the receiver maps in the cache, they should all already
Mads Ager (chromium) 2011/04/28 13:02:01 This introduces a dependency that I don't think we
1678 // have MONOMORPHIC stubs.
1679 ZoneCodeList* handler_ics = new ZoneCodeList(KeyedIC::kMaxKeyedPolymorphism);
1680 flags = Code::ComputeMonomorphicFlags(kind, NORMAL, strict_mode);
1681 String* monomorphic_name = GetStubNameForCache(MONOMORPHIC);
1682 for (int current = 0; current < receiver_maps->length(); ++current) {
1683 Handle<Map> receiver_map(receiver_maps->at(current));
1684 Object* maybe_cached_stub = receiver_map->FindInCodeCache(monomorphic_name, flags);
1685 if (maybe_cached_stub->IsUndefined()) {
1686 UNREACHABLE();
1687 return generic_stub;
1688 }
1689 handler_ics->Add(Handle<Code>(Code::cast(maybe_cached_stub)));
1690 }
1691
1692 Code* stub;
1693 // Build the MEGAMORPHIC stub.
1694 MaybeObject* maybe_stub = ConstructMegamorphicKeyedIC(receiver_maps,
1695 handler_ics,
1696 strict_mode);
1697 if (!maybe_stub->To(&stub)) return maybe_stub;
1698
1699 MaybeObject* maybe_update = receiver->UpdateMapCodeCache(
1700 megamorphic_name,
1701 stub);
1702 if (maybe_update->IsFailure()) return maybe_update;
1703 return stub;
1704 }
1705
1706
1707 String* KeyedStoreIC::GetStubNameForCache(IC::State ic_state) {
1708 if (ic_state == MONOMORPHIC) {
1709 return isolate()->heap()->KeyedStoreSpecializedMonomorphic_symbol();
1710 } else {
1711 ASSERT(ic_state == MEGAMORPHIC);
1712 return isolate()->heap()->KeyedStoreSpecializedPolymorphic_symbol();
1713 }
1714 }
1715
1716
1717 MaybeObject* KeyedStoreIC::ConstructSpecializedKeyedIC(
1718 Handle<Map> receiver_map,
1719 StrictModeFlag strict_mode) {
1720 Object* object;
1721 KeyedStoreStubCompiler compiler(strict_mode);
1722 MaybeObject* maybe_code = compiler.CompileStoreSpecialized(receiver_map);
1723 if (!maybe_code->ToObject(&object)) return maybe_code;
1724 PROFILE(isolate(), CodeCreateEvent(Logger::KEYED_STORE_IC_TAG,
1725 Code::cast(object), 0));
1726 return object;
1727 }
1728
1729
1730 MaybeObject* KeyedStoreIC::ConstructMegamorphicKeyedIC(
1731 ZoneMapList* receiver_maps,
1732 ZoneCodeList* targets,
1733 StrictModeFlag strict_mode) {
1734 Object* object;
1735 KeyedStoreStubCompiler compiler(strict_mode);
1736 MaybeObject* maybe_code = compiler.CompileStoreMegamorphic(receiver_maps, targ ets);
1737 if (!maybe_code->ToObject(&object)) return maybe_code;
1738 isolate()->counters()->keyed_store_polymorphic_stubs()->Increment();
1739 PROFILE(isolate(), CodeCreateEvent(
1740 Logger::KEYED_STORE_MEGAMORPHIC_IC_TAG,
1741 Code::cast(object), 0));
1742 return object;
1743 }
1744
1745
1485 MaybeObject* KeyedStoreIC::Store(State state, 1746 MaybeObject* KeyedStoreIC::Store(State state,
1486 StrictModeFlag strict_mode, 1747 StrictModeFlag strict_mode,
1487 Handle<Object> object, 1748 Handle<Object> object,
1488 Handle<Object> key, 1749 Handle<Object> key,
1489 Handle<Object> value) { 1750 Handle<Object> value,
1751 bool force_generic) {
1490 if (key->IsSymbol()) { 1752 if (key->IsSymbol()) {
1491 Handle<String> name = Handle<String>::cast(key); 1753 Handle<String> name = Handle<String>::cast(key);
1492 1754
1493 // If the object is undefined or null it's illegal to try to set any 1755 // If the object is undefined or null it's illegal to try to set any
1494 // properties on it; throw a TypeError in that case. 1756 // properties on it; throw a TypeError in that case.
1495 if (object->IsUndefined() || object->IsNull()) { 1757 if (object->IsUndefined() || object->IsNull()) {
1496 return TypeError("non_object_property_store", object, name); 1758 return TypeError("non_object_property_store", object, name);
1497 } 1759 }
1498 1760
1499 // Ignore stores where the receiver is not a JSObject. 1761 // Ignore stores where the receiver is not a JSObject.
(...skipping 20 matching lines...) Expand all
1520 1782
1521 // Set the property. 1783 // Set the property.
1522 return receiver->SetProperty(*name, *value, NONE, strict_mode); 1784 return receiver->SetProperty(*name, *value, NONE, strict_mode);
1523 } 1785 }
1524 1786
1525 // Do not use ICs for objects that require access checks (including 1787 // Do not use ICs for objects that require access checks (including
1526 // the global object). 1788 // the global object).
1527 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded(); 1789 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded();
1528 ASSERT(!(use_ic && object->IsJSGlobalProxy())); 1790 ASSERT(!(use_ic && object->IsJSGlobalProxy()));
1529 1791
1792 Code* stub = (strict_mode == kStrictMode)
1793 ? generic_stub_strict()
1794 : generic_stub();
1530 if (use_ic) { 1795 if (use_ic) {
1531 Code* stub = 1796 if (!force_generic) {
1532 (strict_mode == kStrictMode) ? generic_stub_strict() : generic_stub(); 1797 if (object->IsJSObject() && key->IsSmi()) {
1533 if (state == UNINITIALIZED) { 1798 JSObject* receiver = JSObject::cast(*object);
1534 if (object->IsJSObject()) { 1799 MaybeObject* maybe_stub = ComputeKeyedIC(receiver,
1535 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 1800 true,
1536 if (receiver->HasExternalArrayElements()) { 1801 strict_mode,
1537 MaybeObject* probe = 1802 stub);
1538 isolate()->stub_cache()->ComputeKeyedLoadOrStoreExternalArray( 1803 if (!maybe_stub->To(&stub)) return maybe_stub;
1539 *receiver, true, strict_mode);
1540 stub = probe->IsFailure() ?
1541 NULL : Code::cast(probe->ToObjectUnchecked());
1542 } else if (key->IsSmi() && receiver->map()->has_fast_elements()) {
1543 MaybeObject* probe =
1544 isolate()->stub_cache()->ComputeKeyedStoreSpecialized(
1545 *receiver, strict_mode);
1546 stub = probe->IsFailure() ?
1547 NULL : Code::cast(probe->ToObjectUnchecked());
1548 }
1549 } 1804 }
1550 } 1805 }
1551 if (stub != NULL) set_target(stub);
1552 } 1806 }
1553 1807
1808 #ifdef DEBUG
1809 TraceIC("KeyedStoreIC", key, state, stub);
1810 #endif
1811
1812 HandleScope handle_scope(isolate());
1813 Handle<Code> stub_handle(stub); // Survives possible GC below.
1814
1554 // Set the property. 1815 // Set the property.
1555 return Runtime::SetObjectProperty( 1816 MaybeObject* result = Runtime::SetObjectProperty(
1556 isolate(), object , key, value, NONE, strict_mode); 1817 isolate(), object , key, value, NONE, strict_mode);
1818
1819 ASSERT(!result->IsFailure());
1820 if (use_ic) {
1821 ASSERT(*stub_handle != NULL);
1822 set_target(*stub_handle);
1823 }
1824
1825 return result;
1557 } 1826 }
1558 1827
1559 1828
1560 void KeyedStoreIC::UpdateCaches(LookupResult* lookup, 1829 void KeyedStoreIC::UpdateCaches(LookupResult* lookup,
1561 State state, 1830 State state,
1562 StrictModeFlag strict_mode, 1831 StrictModeFlag strict_mode,
1563 Handle<JSObject> receiver, 1832 Handle<JSObject> receiver,
1564 Handle<String> name, 1833 Handle<String> name,
1565 Handle<Object> value) { 1834 Handle<Object> value) {
1566 // Skip JSGlobalProxy. 1835 // Skip JSGlobalProxy.
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
1712 return ic.Load(state, args.at<Object>(0), args.at<String>(1)); 1981 return ic.Load(state, args.at<Object>(0), args.at<String>(1));
1713 } 1982 }
1714 1983
1715 1984
1716 // Used from ic-<arch>.cc 1985 // Used from ic-<arch>.cc
1717 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_Miss) { 1986 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_Miss) {
1718 NoHandleAllocation na; 1987 NoHandleAllocation na;
1719 ASSERT(args.length() == 2); 1988 ASSERT(args.length() == 2);
1720 KeyedLoadIC ic(isolate); 1989 KeyedLoadIC ic(isolate);
1721 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); 1990 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
1722 return ic.Load(state, args.at<Object>(0), args.at<Object>(1)); 1991 return ic.Load(state, args.at<Object>(0), args.at<Object>(1), false);
1723 } 1992 }
1724 1993
1725 1994
1995 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissForceGeneric) {
1996 NoHandleAllocation na;
1997 ASSERT(args.length() == 2);
1998 KeyedLoadIC ic(isolate);
1999 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
2000 return ic.Load(state, args.at<Object>(0), args.at<Object>(1), true);
2001 }
2002
2003
1726 // Used from ic-<arch>.cc. 2004 // Used from ic-<arch>.cc.
1727 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Miss) { 2005 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Miss) {
1728 NoHandleAllocation na; 2006 NoHandleAllocation na;
1729 ASSERT(args.length() == 3); 2007 ASSERT(args.length() == 3);
1730 StoreIC ic(isolate); 2008 StoreIC ic(isolate);
1731 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); 2009 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
1732 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); 2010 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
1733 return ic.Store(state, 2011 return ic.Store(state,
1734 static_cast<StrictModeFlag>(extra_ic_state & kStrictMode), 2012 static_cast<StrictModeFlag>(extra_ic_state & kStrictMode),
1735 args.at<Object>(0), 2013 args.at<Object>(0),
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
1796 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Miss) { 2074 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Miss) {
1797 NoHandleAllocation na; 2075 NoHandleAllocation na;
1798 ASSERT(args.length() == 3); 2076 ASSERT(args.length() == 3);
1799 KeyedStoreIC ic(isolate); 2077 KeyedStoreIC ic(isolate);
1800 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); 2078 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
1801 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); 2079 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
1802 return ic.Store(state, 2080 return ic.Store(state,
1803 static_cast<StrictModeFlag>(extra_ic_state & kStrictMode), 2081 static_cast<StrictModeFlag>(extra_ic_state & kStrictMode),
1804 args.at<Object>(0), 2082 args.at<Object>(0),
1805 args.at<Object>(1), 2083 args.at<Object>(1),
1806 args.at<Object>(2)); 2084 args.at<Object>(2),
2085 false);
1807 } 2086 }
1808 2087
1809 2088
2089 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissForceGeneric) {
2090 NoHandleAllocation na;
2091 ASSERT(args.length() == 3);
2092 KeyedStoreIC ic(isolate);
2093 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
2094 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
2095 return ic.Store(state,
2096 static_cast<StrictModeFlag>(extra_ic_state & kStrictMode),
2097 args.at<Object>(0),
2098 args.at<Object>(1),
2099 args.at<Object>(2),
2100 true);
2101 }
2102
2103
1810 void TRBinaryOpIC::patch(Code* code) { 2104 void TRBinaryOpIC::patch(Code* code) {
1811 set_target(code); 2105 set_target(code);
1812 } 2106 }
1813 2107
1814 2108
1815 const char* TRBinaryOpIC::GetName(TypeInfo type_info) { 2109 const char* TRBinaryOpIC::GetName(TypeInfo type_info) {
1816 switch (type_info) { 2110 switch (type_info) {
1817 case UNINITIALIZED: return "Uninitialized"; 2111 case UNINITIALIZED: return "Uninitialized";
1818 case SMI: return "SMI"; 2112 case SMI: return "SMI";
1819 case INT32: return "Int32s"; 2113 case INT32: return "Int32s";
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after
2075 #undef ADDR 2369 #undef ADDR
2076 }; 2370 };
2077 2371
2078 2372
2079 Address IC::AddressFromUtilityId(IC::UtilityId id) { 2373 Address IC::AddressFromUtilityId(IC::UtilityId id) {
2080 return IC_utilities[id]; 2374 return IC_utilities[id];
2081 } 2375 }
2082 2376
2083 2377
2084 } } // namespace v8::internal 2378 } } // namespace v8::internal
OLDNEW
« src/ia32/stub-cache-ia32.cc ('K') | « src/ic.h ('k') | src/log.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698