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

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: merge with latest 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
« src/ic.h ('K') | « src/ic.h ('k') | src/log.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 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::ComputeMonomorphicBuiltinFastElementStub(
1069 bool is_js_array) {
1070 if (is_js_array) {
Mads Ager (chromium) 2011/05/10 13:38:06 If you simplify the stub hierarchy this can be jus
danno 2011/05/11 14:20:19 Done.
1071 JSArrayKeyedLoadStub stub;
1072 return stub.TryGetCode();
1073 } else {
1074 ObjectKeyedLoadStub stub;
1075 return stub.TryGetCode();
1076 }
1077 }
1078
1079
1080 MaybeObject* KeyedLoadIC::ComputeMonomorphicBuiltinExternalArrayStub(
1081 ExternalArrayType array_type) {
1082 switch (array_type) {
Mads Ager (chromium) 2011/05/10 13:38:06 ExternalArrayLoadStub stub(array_type); return stu
danno 2011/05/11 14:20:19 Done.
1083 case kExternalByteArray: {
1084 ExternalByteArrayLoadStub stub;
1085 return stub.TryGetCode();
1086 break;
1087 }
1088 case kExternalUnsignedByteArray: {
1089 ExternalUnsignedByteArrayLoadStub stub;
1090 return stub.TryGetCode();
1091 break;
1092 }
1093 case kExternalShortArray: {
1094 ExternalShortArrayLoadStub stub;
1095 return stub.TryGetCode();
1096 break;
1097 }
1098 case kExternalUnsignedShortArray: {
1099 ExternalUnsignedShortArrayLoadStub stub;
1100 return stub.TryGetCode();
1101 break;
1102 }
1103 case kExternalIntArray: {
1104 ExternalIntArrayLoadStub stub;
1105 return stub.TryGetCode();
1106 break;
1107 }
1108 case kExternalUnsignedIntArray: {
1109 ExternalUnsignedIntArrayLoadStub stub;
1110 return stub.TryGetCode();
1111 break;
1112 }
1113 case kExternalDoubleArray: {
1114 ExternalDoubleArrayLoadStub stub;
1115 return stub.TryGetCode();
1116 break;
1117 }
1118 case kExternalFloatArray: {
1119 ExternalFloatArrayLoadStub stub;
1120 return stub.TryGetCode();
1121 break;
1122 }
1123 case kExternalPixelArray: {
1124 ExternalPixelArrayLoadStub stub;
1125 return stub.TryGetCode();
1126 break;
1127 }
1128 }
1129 UNREACHABLE();
1130 return NULL;
1131 }
1132
1133
1134 MaybeObject* KeyedLoadIC::ConstructMonomorphicFastElementStub(
1135 Map* receiver_map,
1136 StrictModeFlag strict_mode) {
1137 Object* object;
1138 KeyedLoadStubCompiler compiler;
1139 MaybeObject* maybe_code = compiler.CompileLoadFastElement(receiver_map);
1140 if (!maybe_code->ToObject(&object)) return maybe_code;
1141 PROFILE(isolate(), CodeCreateEvent(Logger::KEYED_LOAD_IC_TAG,
1142 Code::cast(object), 0));
1143 return object;
1144 }
1145
1146
1147 MaybeObject* KeyedLoadIC::ConstructMegamorphicStub(
1148 MapList* receiver_maps,
1149 CodeList* targets,
1150 StrictModeFlag strict_mode) {
1151 Object* object;
1152 KeyedLoadStubCompiler compiler;
1153 MaybeObject* maybe_code = compiler.CompileLoadMegamorphic(receiver_maps,
1154 targets);
1155 if (!maybe_code->ToObject(&object)) return maybe_code;
1156 isolate()->counters()->keyed_load_polymorphic_stubs()->Increment();
1157 PROFILE(isolate(), CodeCreateEvent(
1158 Logger::KEYED_LOAD_MEGAMORPHIC_IC_TAG,
1159 Code::cast(object), 0));
1160 return object;
1161 }
1162
1163
1034 MaybeObject* KeyedLoadIC::Load(State state, 1164 MaybeObject* KeyedLoadIC::Load(State state,
1035 Handle<Object> object, 1165 Handle<Object> object,
1036 Handle<Object> key) { 1166 Handle<Object> key,
1167 bool force_generic_stub) {
1037 // Check for values that can be converted into a symbol. 1168 // Check for values that can be converted into a symbol.
1038 // TODO(1295): Remove this code. 1169 // TODO(1295): Remove this code.
1039 HandleScope scope(isolate()); 1170 HandleScope scope(isolate());
1040 if (key->IsHeapNumber() && 1171 if (key->IsHeapNumber() &&
1041 isnan(HeapNumber::cast(*key)->value())) { 1172 isnan(HeapNumber::cast(*key)->value())) {
1042 key = isolate()->factory()->nan_symbol(); 1173 key = isolate()->factory()->nan_symbol();
1043 } else if (key->IsUndefined()) { 1174 } else if (key->IsUndefined()) {
1044 key = isolate()->factory()->undefined_symbol(); 1175 key = isolate()->factory()->undefined_symbol();
1045 } 1176 }
1046 1177
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
1152 1283
1153 return object->GetProperty(*object, &lookup, *name, &attr); 1284 return object->GetProperty(*object, &lookup, *name, &attr);
1154 } 1285 }
1155 1286
1156 // Do not use ICs for objects that require access checks (including 1287 // Do not use ICs for objects that require access checks (including
1157 // the global object). 1288 // the global object).
1158 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded(); 1289 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded();
1159 1290
1160 if (use_ic) { 1291 if (use_ic) {
1161 Code* stub = generic_stub(); 1292 Code* stub = generic_stub();
1162 if (state == UNINITIALIZED) { 1293 if (!force_generic_stub) {
1163 if (object->IsString() && key->IsNumber()) { 1294 if (object->IsString() && key->IsNumber()) {
1164 stub = string_stub(); 1295 if (state == UNINITIALIZED) {
1296 stub = string_stub();
1297 }
1165 } else if (object->IsJSObject()) { 1298 } else if (object->IsJSObject()) {
1166 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 1299 JSObject* receiver = JSObject::cast(*object);
1167 if (receiver->HasExternalArrayElements()) { 1300 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(); 1301 stub = indexed_interceptor_stub();
1175 } else if (key->IsSmi() && 1302 } else if (key->IsSmi()) {
1176 receiver->map()->has_fast_elements()) { 1303 MaybeObject* maybe_stub = ComputeStub(receiver,
1177 MaybeObject* probe = 1304 false,
1178 isolate()->stub_cache()->ComputeKeyedLoadSpecialized(*receiver); 1305 kNonStrictMode,
1179 stub = probe->IsFailure() ? 1306 stub);
1180 NULL : Code::cast(probe->ToObjectUnchecked()); 1307 stub = maybe_stub->IsFailure() ?
1308 NULL : Code::cast(maybe_stub->ToObjectUnchecked());
1181 } 1309 }
1182 } 1310 }
1183 } 1311 }
1184 if (stub != NULL) set_target(stub); 1312 if (stub != NULL) set_target(stub);
1313 }
1185 1314
1186 #ifdef DEBUG 1315 #ifdef DEBUG
1187 TraceIC("KeyedLoadIC", key, state, target()); 1316 TraceIC("KeyedLoadIC", key, state, target());
1188 #endif // DEBUG 1317 #endif // DEBUG
1189 }
1190 1318
1191 // Get the property. 1319 // Get the property.
1192 return Runtime::GetObjectProperty(isolate(), object, key); 1320 return Runtime::GetObjectProperty(isolate(), object, key);
1193 } 1321 }
1194 1322
1195 1323
1196 void KeyedLoadIC::UpdateCaches(LookupResult* lookup, State state, 1324 void KeyedLoadIC::UpdateCaches(LookupResult* lookup, State state,
1197 Handle<Object> object, Handle<String> name) { 1325 Handle<Object> object, Handle<String> name) {
1198 // Bail out if we didn't find a result. 1326 // Bail out if we didn't find a result.
1199 if (!lookup->IsProperty() || !lookup->IsCacheable()) return; 1327 if (!lookup->IsProperty() || !lookup->IsCacheable()) return;
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after
1476 receiver->map(), 1604 receiver->map(),
1477 Code::cast(code)); 1605 Code::cast(code));
1478 } 1606 }
1479 1607
1480 #ifdef DEBUG 1608 #ifdef DEBUG
1481 TraceIC("StoreIC", name, state, target()); 1609 TraceIC("StoreIC", name, state, target());
1482 #endif 1610 #endif
1483 } 1611 }
1484 1612
1485 1613
1614 static bool AddOneReceiverMapIfMissing(MapList* receiver_maps,
1615 Map* new_receiver_map) {
1616 for (int current = 0; current < receiver_maps->length(); ++current) {
1617 if (receiver_maps->at(current) == new_receiver_map) {
1618 return false;
1619 }
1620 }
1621 receiver_maps->Add(new_receiver_map);
1622 return true;
1623 }
1624
1625
1626 void KeyedIC::GetReceiverMapsForStub(Code* stub, MapList* result) {
1627 ASSERT(stub->is_inline_cache_stub());
1628 if (stub == string_stub()) {
1629 return result->Add(isolate()->heap()->string_map());
1630 } else if (stub->is_keyed_load_stub() || stub->is_keyed_store_stub()) {
1631 if (stub->ic_state() == MONOMORPHIC) {
1632 result->Add(Map::cast(stub->FindFirstMap()));
1633 } else {
1634 ASSERT(stub->ic_state() == MEGAMORPHIC);
1635 AssertNoAllocation no_allocation;
1636 int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
1637 for (RelocIterator it(stub, mask); !it.done(); it.next()) {
1638 RelocInfo* info = it.rinfo();
1639 Object* object = info->target_object();
1640 ASSERT(object->IsMap());
1641 result->Add(Map::cast(object));
1642 }
1643 }
1644 }
1645 }
1646
1647
1648 MaybeObject* KeyedIC::ComputeStub(JSObject* receiver,
1649 bool is_store,
1650 StrictModeFlag strict_mode,
1651 Code* generic_stub) {
1652 State ic_state = target()->ic_state();
1653 Code* monomorphic_stub;
1654 // Always compute the MONOMORPHIC stub, even if the MEGAMORPHIC stub ends up
1655 // being used. This is necessary because the megamorphic stub needs to have
1656 // the MONOMORPHIC stubs to jump into for all of the receiver types that it
Mads Ager (chromium) 2011/05/10 13:38:06 Is this comment correct any more? You might need t
danno 2011/05/11 14:20:19 Done.
1657 // handles.
1658 MaybeObject* maybe_stub = ComputeMonomorphicStub(receiver,
1659 is_store,
1660 strict_mode,
1661 generic_stub);
1662 if (!maybe_stub->To(&monomorphic_stub)) return maybe_stub;
1663
1664 if (ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) {
1665 return monomorphic_stub;
1666 }
1667 ASSERT(target() != generic_stub);
1668
1669 // Don't handle megamorphic property accesses for INTERCEPTORS or CALLBACKS
1670 // via megamorphic stubs, since they don't have a map in their relocation info
1671 // and so the stubs can't be harvested for the object needed for a map check.
1672 if (target()->type() != NORMAL) {
1673 return generic_stub;
1674 }
1675
1676 // Determine the list of receiver maps that this call site has seen,
1677 // adding the map that was just encountered.
1678 MapList target_receiver_maps;
1679 GetReceiverMapsForStub(target(), &target_receiver_maps);
1680 if (!AddOneReceiverMapIfMissing(&target_receiver_maps, receiver->map())) {
1681 // If the miss wasn't due to an unseen map, a MEGAMORPHIC stub
1682 // won't help, use the generic stub.
1683 return generic_stub;
1684 }
1685
1686 Code::Kind kind = this->kind();
1687 Code::Flags flags = Code::ComputeFlags(kind,
1688 NOT_IN_LOOP,
1689 MEGAMORPHIC,
1690 strict_mode);
1691 String* megamorphic_name = GetStubNameForCache(MEGAMORPHIC);
1692 Object* maybe_cached_stub = receiver->map()->FindInCodeCache(megamorphic_name,
Mads Ager (chromium) 2011/05/10 13:38:06 I'm not sure I understand why you cache this stub
danno 2011/05/11 14:20:19 Yes, we should have a global cache instead of cach
1693 flags);
1694
1695 // Create a set of all receiver maps that have been seen at the IC call site
1696 // and those seen by the MEGAMORPHIC cached stub, if that's the stub that's
1697 // been selected.
1698 MapList receiver_maps;
1699 if (!maybe_cached_stub->IsUndefined()) {
1700 GetReceiverMapsForStub(Code::cast(maybe_cached_stub), &receiver_maps);
1701 }
1702 bool added_map = false;
1703 for (int i = 0; i < target_receiver_maps.length(); ++i) {
1704 if (AddOneReceiverMapIfMissing(&receiver_maps,
1705 target_receiver_maps.at(i))) {
1706 added_map = true;
1707 }
1708 }
1709 ASSERT(receiver_maps.length() > 0);
1710
1711 // If the maximum number of receiver maps has been exceeded, use the Generic
1712 // version of the IC.
1713 if (receiver_maps.length() > KeyedIC::kMaxKeyedPolymorphism) {
1714 return generic_stub;
1715 }
1716
1717 // If no maps have been seen at the call site that aren't in the cached
1718 // stub, then use it.
1719 if (!added_map) {
1720 ASSERT(!maybe_cached_stub->IsUndefined());
1721 ASSERT(maybe_cached_stub->IsCode());
1722 return Code::cast(maybe_cached_stub);
1723 }
1724
1725 // Lookup all of the receiver maps in the cache, they should all already
1726 // have MONOMORPHIC stubs.
1727 CodeList handler_ics(KeyedIC::kMaxKeyedPolymorphism);
1728 for (int current = 0; current < receiver_maps.length(); ++current) {
1729 Map* receiver_map(receiver_maps.at(current));
1730 MaybeObject* maybe_cached_stub = ComputeMonomorphicStubWithoutMapCheck(
1731 receiver_map,
1732 strict_mode,
1733 generic_stub);
1734 Code* cached_stub;
1735 if (!maybe_cached_stub->To(&cached_stub)) {
1736 return maybe_cached_stub;
1737 }
1738 handler_ics.Add(cached_stub);
1739 }
1740
1741 Code* stub;
1742 // Build the MEGAMORPHIC stub.
1743 maybe_stub = ConstructMegamorphicStub(&receiver_maps,
1744 &handler_ics,
1745 strict_mode);
1746 if (!maybe_stub->To(&stub)) return maybe_stub;
1747
1748 MaybeObject* maybe_update = receiver->UpdateMapCodeCache(
1749 megamorphic_name,
1750 stub);
1751 if (maybe_update->IsFailure()) return maybe_update;
1752 return stub;
1753 }
1754
1755
1756 MaybeObject* KeyedIC::ComputeMonomorphicStubWithoutMapCheck(
1757 Map* receiver_map,
1758 StrictModeFlag strict_mode,
1759 Code* generic_stub) {
1760 if ((receiver_map->instance_type() & kNotStringTag) == 0) {
1761 ASSERT(string_stub() != NULL);
1762 return string_stub();
1763 } else if (receiver_map->has_external_array_elements()) {
1764 // Determine the array type from the default MONOMORPHIC already generated
1765 // stub. There is no other way to determine the type of the external array
1766 // directly from the receiver type.
1767 Code::Kind kind = this->kind();
1768 Code::Flags flags = Code::ComputeMonomorphicFlags(kind,
1769 NORMAL,
1770 strict_mode);
1771 String* monomorphic_name = GetStubNameForCache(MONOMORPHIC);
1772 Object* maybe_default_stub = receiver_map->FindInCodeCache(monomorphic_name,
1773 flags);
1774 if (maybe_default_stub->IsUndefined()) {
1775 return generic_stub;
1776 }
1777 Code* default_stub = Code::cast(maybe_default_stub);
1778 return ComputeMonomorphicBuiltinExternalArrayStub(
1779 default_stub->external_array_type());
1780 } else if (receiver_map->has_fast_elements()) {
1781 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
1782 return ComputeMonomorphicBuiltinFastElementStub(is_js_array);
1783 } else {
1784 return generic_stub;
1785 }
1786 }
1787
1788
1789 MaybeObject* KeyedIC::ComputeMonomorphicStub(JSObject* receiver,
1790 bool is_store,
1791 StrictModeFlag strict_mode,
1792 Code* generic_stub) {
1793 Code* result = NULL;
1794 if (receiver->HasExternalArrayElements()) {
1795 MaybeObject* maybe_stub =
1796 isolate()->stub_cache()->ComputeKeyedLoadOrStoreExternalArray(
1797 receiver, is_store, strict_mode);
1798 if (!maybe_stub->To(&result)) return maybe_stub;
1799 } else if (receiver->map()->has_fast_elements()) {
1800 Code::Kind kind = this->kind();
1801 Code::Flags flags = Code::ComputeMonomorphicFlags(kind,
1802 NORMAL,
1803 strict_mode);
1804 String* name = GetStubNameForCache(MONOMORPHIC);
1805 Object* maybe_cached_stub = receiver->map()->FindInCodeCache(name, flags);
1806 if (maybe_cached_stub->IsUndefined()) {
1807 MaybeObject* maybe_stub = ConstructMonomorphicFastElementStub(
1808 receiver->map(),
1809 strict_mode);
1810 if (maybe_stub->To(&result)) return maybe_stub;
1811 MaybeObject* maybe_update = receiver->UpdateMapCodeCache(name, result);
Mads Ager (chromium) 2011/05/10 13:38:06 It seems to me that something like this should be
danno 2011/05/11 14:20:19 Done for the Monomorphic stubs. The megamorphic st
1812 if (maybe_update->IsFailure()) return maybe_update;
1813 } else {
1814 result = Code::cast(maybe_cached_stub);
1815 }
1816 } else {
1817 result = generic_stub;
1818 }
1819 return result;
1820 }
1821
1822
1823 String* KeyedStoreIC::GetStubNameForCache(IC::State ic_state) {
1824 if (ic_state == MONOMORPHIC) {
1825 return isolate()->heap()->KeyedStoreSpecializedMonomorphic_symbol();
1826 } else {
1827 ASSERT(ic_state == MEGAMORPHIC);
1828 return isolate()->heap()->KeyedStoreSpecializedPolymorphic_symbol();
1829 }
1830 }
1831
1832
1833 MaybeObject* KeyedStoreIC::ComputeMonomorphicBuiltinFastElementStub(
1834 bool is_js_array) {
1835 if (is_js_array) {
1836 JSArrayKeyedStoreStub stub;
1837 return stub.TryGetCode();
1838 } else {
1839 ObjectKeyedStoreStub stub;
1840 return stub.TryGetCode();
1841 }
1842 }
1843
1844
1845 MaybeObject* KeyedStoreIC::ComputeMonomorphicBuiltinExternalArrayStub(
1846 ExternalArrayType array_type) {
1847 switch (array_type) {
1848 case kExternalByteArray: {
1849 ExternalByteArrayStoreStub stub;
1850 return stub.TryGetCode();
1851 }
1852 case kExternalUnsignedByteArray: {
1853 ExternalUnsignedByteArrayStoreStub stub;
1854 return stub.TryGetCode();
1855 }
1856 case kExternalShortArray: {
1857 ExternalShortArrayStoreStub stub;
1858 return stub.TryGetCode();
1859 }
1860 case kExternalUnsignedShortArray: {
1861 ExternalUnsignedShortArrayStoreStub stub;
1862 return stub.TryGetCode();
1863 }
1864 case kExternalIntArray: {
1865 ExternalIntArrayStoreStub stub;
1866 return stub.TryGetCode();
1867 }
1868 case kExternalUnsignedIntArray: {
1869 ExternalUnsignedIntArrayStoreStub stub;
1870 return stub.TryGetCode();
1871 }
1872 case kExternalDoubleArray: {
1873 ExternalDoubleArrayStoreStub stub;
1874 return stub.TryGetCode();
1875 }
1876 case kExternalFloatArray: {
1877 ExternalFloatArrayStoreStub stub;
1878 return stub.TryGetCode();
1879 }
1880 case kExternalPixelArray: {
1881 ExternalPixelArrayStoreStub stub;
1882 return stub.TryGetCode();
1883 }
1884 }
1885 UNREACHABLE();
1886 return NULL;
1887 }
1888
1889
1890 MaybeObject* KeyedStoreIC::ConstructMonomorphicFastElementStub(
1891 Map* receiver_map,
1892 StrictModeFlag strict_mode) {
1893 Object* object;
1894 KeyedStoreStubCompiler compiler(strict_mode);
1895 MaybeObject* maybe_code = compiler.CompileStoreFastElement(receiver_map);
1896 if (!maybe_code->ToObject(&object)) return maybe_code;
1897 PROFILE(isolate(), CodeCreateEvent(Logger::KEYED_STORE_IC_TAG,
1898 Code::cast(object), 0));
1899 return object;
1900 }
1901
1902
1903 MaybeObject* KeyedStoreIC::ConstructMegamorphicStub(
1904 MapList* receiver_maps,
1905 CodeList* targets,
1906 StrictModeFlag strict_mode) {
1907 Object* object;
1908 KeyedStoreStubCompiler compiler(strict_mode);
1909 MaybeObject* maybe_code = compiler.CompileStoreMegamorphic(receiver_maps,
1910 targets);
1911 if (!maybe_code->ToObject(&object)) return maybe_code;
1912 isolate()->counters()->keyed_store_polymorphic_stubs()->Increment();
1913 PROFILE(isolate(), CodeCreateEvent(
1914 Logger::KEYED_STORE_MEGAMORPHIC_IC_TAG,
1915 Code::cast(object), 0));
1916 return object;
1917 }
1918
1919
1486 MaybeObject* KeyedStoreIC::Store(State state, 1920 MaybeObject* KeyedStoreIC::Store(State state,
1487 StrictModeFlag strict_mode, 1921 StrictModeFlag strict_mode,
1488 Handle<Object> object, 1922 Handle<Object> object,
1489 Handle<Object> key, 1923 Handle<Object> key,
1490 Handle<Object> value) { 1924 Handle<Object> value,
1925 bool force_generic) {
1491 if (key->IsSymbol()) { 1926 if (key->IsSymbol()) {
1492 Handle<String> name = Handle<String>::cast(key); 1927 Handle<String> name = Handle<String>::cast(key);
1493 1928
1494 // If the object is undefined or null it's illegal to try to set any 1929 // 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. 1930 // properties on it; throw a TypeError in that case.
1496 if (object->IsUndefined() || object->IsNull()) { 1931 if (object->IsUndefined() || object->IsNull()) {
1497 return TypeError("non_object_property_store", object, name); 1932 return TypeError("non_object_property_store", object, name);
1498 } 1933 }
1499 1934
1500 // Ignore stores where the receiver is not a JSObject. 1935 // Ignore stores where the receiver is not a JSObject.
(...skipping 21 matching lines...) Expand all
1522 // Set the property. 1957 // Set the property.
1523 return receiver->SetProperty(*name, *value, NONE, strict_mode); 1958 return receiver->SetProperty(*name, *value, NONE, strict_mode);
1524 } 1959 }
1525 1960
1526 // Do not use ICs for objects that require access checks (including 1961 // Do not use ICs for objects that require access checks (including
1527 // the global object). 1962 // the global object).
1528 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded(); 1963 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded();
1529 ASSERT(!(use_ic && object->IsJSGlobalProxy())); 1964 ASSERT(!(use_ic && object->IsJSGlobalProxy()));
1530 1965
1531 if (use_ic) { 1966 if (use_ic) {
1532 Code* stub = 1967 Code* stub = (strict_mode == kStrictMode)
1533 (strict_mode == kStrictMode) ? generic_stub_strict() : generic_stub(); 1968 ? generic_stub_strict()
1534 if (state == UNINITIALIZED) { 1969 : generic_stub();
1535 if (object->IsJSObject()) { 1970 if (!force_generic) {
1536 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 1971 if (object->IsJSObject() && key->IsSmi()) {
1537 if (receiver->HasExternalArrayElements()) { 1972 JSObject* receiver = JSObject::cast(*object);
1538 MaybeObject* probe = 1973 MaybeObject* maybe_stub = ComputeStub(receiver,
1539 isolate()->stub_cache()->ComputeKeyedLoadOrStoreExternalArray( 1974 true,
1540 *receiver, true, strict_mode); 1975 strict_mode,
1541 stub = probe->IsFailure() ? 1976 stub);
1542 NULL : Code::cast(probe->ToObjectUnchecked()); 1977 stub = maybe_stub->IsFailure() ?
1543 } else if (key->IsSmi() && receiver->map()->has_fast_elements()) { 1978 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 } 1979 }
1551 } 1980 }
1552 if (stub != NULL) set_target(stub); 1981 if (stub != NULL) set_target(stub);
1553 } 1982 }
1554 1983
1984 #ifdef DEBUG
1985 TraceIC("KeyedStoreIC", key, state, target());
1986 #endif
1987
1555 // Set the property. 1988 // Set the property.
1556 return Runtime::SetObjectProperty( 1989 return Runtime::SetObjectProperty(
1557 isolate(), object , key, value, NONE, strict_mode); 1990 isolate(), object , key, value, NONE, strict_mode);
1558 } 1991 }
1559 1992
1560 1993
1561 void KeyedStoreIC::UpdateCaches(LookupResult* lookup, 1994 void KeyedStoreIC::UpdateCaches(LookupResult* lookup,
1562 State state, 1995 State state,
1563 StrictModeFlag strict_mode, 1996 StrictModeFlag strict_mode,
1564 Handle<JSObject> receiver, 1997 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)); 2146 return ic.Load(state, args.at<Object>(0), args.at<String>(1));
1714 } 2147 }
1715 2148
1716 2149
1717 // Used from ic-<arch>.cc 2150 // Used from ic-<arch>.cc
1718 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_Miss) { 2151 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_Miss) {
1719 NoHandleAllocation na; 2152 NoHandleAllocation na;
1720 ASSERT(args.length() == 2); 2153 ASSERT(args.length() == 2);
1721 KeyedLoadIC ic(isolate); 2154 KeyedLoadIC ic(isolate);
1722 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); 2155 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
1723 return ic.Load(state, args.at<Object>(0), args.at<Object>(1)); 2156 return ic.Load(state, args.at<Object>(0), args.at<Object>(1), false);
1724 } 2157 }
1725 2158
1726 2159
2160 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissForceGeneric) {
2161 NoHandleAllocation na;
2162 ASSERT(args.length() == 2);
2163 KeyedLoadIC ic(isolate);
2164 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
2165 return ic.Load(state, args.at<Object>(0), args.at<Object>(1), true);
2166 }
2167
2168
1727 // Used from ic-<arch>.cc. 2169 // Used from ic-<arch>.cc.
1728 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Miss) { 2170 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Miss) {
1729 NoHandleAllocation na; 2171 NoHandleAllocation na;
1730 ASSERT(args.length() == 3); 2172 ASSERT(args.length() == 3);
1731 StoreIC ic(isolate); 2173 StoreIC ic(isolate);
1732 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); 2174 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
1733 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); 2175 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
1734 return ic.Store(state, 2176 return ic.Store(state,
1735 static_cast<StrictModeFlag>(extra_ic_state & kStrictMode), 2177 static_cast<StrictModeFlag>(extra_ic_state & kStrictMode),
1736 args.at<Object>(0), 2178 args.at<Object>(0),
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
1797 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Miss) { 2239 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Miss) {
1798 NoHandleAllocation na; 2240 NoHandleAllocation na;
1799 ASSERT(args.length() == 3); 2241 ASSERT(args.length() == 3);
1800 KeyedStoreIC ic(isolate); 2242 KeyedStoreIC ic(isolate);
1801 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); 2243 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
1802 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); 2244 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
1803 return ic.Store(state, 2245 return ic.Store(state,
1804 static_cast<StrictModeFlag>(extra_ic_state & kStrictMode), 2246 static_cast<StrictModeFlag>(extra_ic_state & kStrictMode),
1805 args.at<Object>(0), 2247 args.at<Object>(0),
1806 args.at<Object>(1), 2248 args.at<Object>(1),
1807 args.at<Object>(2)); 2249 args.at<Object>(2),
2250 false);
1808 } 2251 }
1809 2252
1810 2253
2254 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Slow) {
2255 NoHandleAllocation na;
2256 ASSERT(args.length() == 3);
2257 KeyedStoreIC ic(isolate);
2258 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
2259 Handle<Object> object = args.at<Object>(0);
2260 Handle<Object> key = args.at<Object>(1);
2261 Handle<Object> value = args.at<Object>(2);
2262 StrictModeFlag strict_mode =
2263 static_cast<StrictModeFlag>(extra_ic_state & kStrictMode);
2264 return Runtime::SetObjectProperty(isolate,
2265 object,
2266 key,
2267 value,
2268 NONE,
2269 strict_mode);
2270 }
2271
2272
2273 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissForceGeneric) {
2274 NoHandleAllocation na;
2275 ASSERT(args.length() == 3);
2276 KeyedStoreIC ic(isolate);
2277 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
2278 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
2279 return ic.Store(state,
2280 static_cast<StrictModeFlag>(extra_ic_state & kStrictMode),
2281 args.at<Object>(0),
2282 args.at<Object>(1),
2283 args.at<Object>(2),
2284 true);
2285 }
2286
2287
1811 void TRUnaryOpIC::patch(Code* code) { 2288 void TRUnaryOpIC::patch(Code* code) {
1812 set_target(code); 2289 set_target(code);
1813 } 2290 }
1814 2291
1815 2292
1816 const char* TRUnaryOpIC::GetName(TypeInfo type_info) { 2293 const char* TRUnaryOpIC::GetName(TypeInfo type_info) {
1817 switch (type_info) { 2294 switch (type_info) {
1818 case UNINITIALIZED: return "Uninitialized"; 2295 case UNINITIALIZED: return "Uninitialized";
1819 case SMI: return "Smi"; 2296 case SMI: return "Smi";
1820 case HEAP_NUMBER: return "HeapNumbers"; 2297 case HEAP_NUMBER: return "HeapNumbers";
(...skipping 368 matching lines...) Expand 10 before | Expand all | Expand 10 after
2189 #undef ADDR 2666 #undef ADDR
2190 }; 2667 };
2191 2668
2192 2669
2193 Address IC::AddressFromUtilityId(IC::UtilityId id) { 2670 Address IC::AddressFromUtilityId(IC::UtilityId id) {
2194 return IC_utilities[id]; 2671 return IC_utilities[id];
2195 } 2672 }
2196 2673
2197 2674
2198 } } // namespace v8::internal 2675 } } // namespace v8::internal
OLDNEW
« src/ic.h ('K') | « src/ic.h ('k') | src/log.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698