OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |