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

Side by Side Diff: src/ic.cc

Issue 7060010: Merge bleeding edge into the GC branch up to 7948. The asserts (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/gc/
Patch Set: Created 9 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ic.h ('k') | src/isolate.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 604 matching lines...) Expand 10 before | Expand all | Expand 10 after
896 } 920 }
897 LOG(isolate(), SuspectReadEvent(*name, *object)); 921 LOG(isolate(), SuspectReadEvent(*name, *object));
898 } 922 }
899 923
900 // Update inline cache and stub cache. 924 // Update inline cache and stub cache.
901 if (FLAG_use_ic) { 925 if (FLAG_use_ic) {
902 UpdateCaches(&lookup, state, object, name); 926 UpdateCaches(&lookup, state, object, name);
903 } 927 }
904 928
905 PropertyAttributes attr; 929 PropertyAttributes attr;
906 if (lookup.IsProperty() && lookup.type() == INTERCEPTOR) { 930 if (lookup.IsProperty() &&
931 (lookup.type() == INTERCEPTOR || lookup.type() == HANDLER)) {
907 // Get the property. 932 // Get the property.
908 Object* result; 933 Object* result;
909 { MaybeObject* maybe_result = 934 { MaybeObject* maybe_result =
910 object->GetProperty(*object, &lookup, *name, &attr); 935 object->GetProperty(*object, &lookup, *name, &attr);
911 if (!maybe_result->ToObject(&result)) return maybe_result; 936 if (!maybe_result->ToObject(&result)) return maybe_result;
912 } 937 }
913 // If the property is not present, check if we need to throw an 938 // If the property is not present, check if we need to throw an
914 // exception. 939 // exception.
915 if (attr == ABSENT && IsContextual(object)) { 940 if (attr == ABSENT && IsContextual(object)) {
916 return ReferenceError("not_defined", name); 941 return ReferenceError("not_defined", name);
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
1024 1049
1025 isolate()->stub_cache()->Set(*name, map, Code::cast(code)); 1050 isolate()->stub_cache()->Set(*name, map, Code::cast(code));
1026 } 1051 }
1027 1052
1028 #ifdef DEBUG 1053 #ifdef DEBUG
1029 TraceIC("LoadIC", name, state, target()); 1054 TraceIC("LoadIC", name, state, target());
1030 #endif 1055 #endif
1031 } 1056 }
1032 1057
1033 1058
1059 String* KeyedLoadIC::GetStubNameForCache(IC::State ic_state) {
1060 if (ic_state == MONOMORPHIC) {
1061 return isolate()->heap()->KeyedLoadSpecializedMonomorphic_symbol();
1062 } else {
1063 ASSERT(ic_state == MEGAMORPHIC);
1064 return isolate()->heap()->KeyedLoadSpecializedPolymorphic_symbol();
1065 }
1066 }
1067
1068
1069 MaybeObject* KeyedLoadIC::GetFastElementStubWithoutMapCheck(
1070 bool is_js_array) {
1071 return KeyedLoadFastElementStub().TryGetCode();
1072 }
1073
1074
1075 MaybeObject* KeyedLoadIC::GetExternalArrayStubWithoutMapCheck(
1076 ExternalArrayType array_type) {
1077 return KeyedLoadExternalArrayStub(array_type).TryGetCode();
1078 }
1079
1080
1081 MaybeObject* KeyedLoadIC::ConstructMegamorphicStub(
1082 MapList* receiver_maps,
1083 CodeList* targets,
1084 StrictModeFlag strict_mode) {
1085 Object* object;
1086 KeyedLoadStubCompiler compiler;
1087 MaybeObject* maybe_code = compiler.CompileLoadMegamorphic(receiver_maps,
1088 targets);
1089 if (!maybe_code->ToObject(&object)) return maybe_code;
1090 isolate()->counters()->keyed_load_polymorphic_stubs()->Increment();
1091 PROFILE(isolate(), CodeCreateEvent(
1092 Logger::KEYED_LOAD_MEGAMORPHIC_IC_TAG,
1093 Code::cast(object), 0));
1094 return object;
1095 }
1096
1097
1034 MaybeObject* KeyedLoadIC::Load(State state, 1098 MaybeObject* KeyedLoadIC::Load(State state,
1035 Handle<Object> object, 1099 Handle<Object> object,
1036 Handle<Object> key) { 1100 Handle<Object> key,
1101 bool force_generic_stub) {
1037 // Check for values that can be converted into a symbol. 1102 // Check for values that can be converted into a symbol.
1038 // TODO(1295): Remove this code. 1103 // TODO(1295): Remove this code.
1039 HandleScope scope(isolate()); 1104 HandleScope scope(isolate());
1040 if (key->IsHeapNumber() && 1105 if (key->IsHeapNumber() &&
1041 isnan(HeapNumber::cast(*key)->value())) { 1106 isnan(HeapNumber::cast(*key)->value())) {
1042 key = isolate()->factory()->nan_symbol(); 1107 key = isolate()->factory()->nan_symbol();
1043 } else if (key->IsUndefined()) { 1108 } else if (key->IsUndefined()) {
1044 key = isolate()->factory()->undefined_symbol(); 1109 key = isolate()->factory()->undefined_symbol();
1045 } 1110 }
1046 1111
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
1152 1217
1153 return object->GetProperty(*object, &lookup, *name, &attr); 1218 return object->GetProperty(*object, &lookup, *name, &attr);
1154 } 1219 }
1155 1220
1156 // Do not use ICs for objects that require access checks (including 1221 // Do not use ICs for objects that require access checks (including
1157 // the global object). 1222 // the global object).
1158 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded(); 1223 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded();
1159 1224
1160 if (use_ic) { 1225 if (use_ic) {
1161 Code* stub = generic_stub(); 1226 Code* stub = generic_stub();
1162 if (state == UNINITIALIZED) { 1227 if (!force_generic_stub) {
1163 if (object->IsString() && key->IsNumber()) { 1228 if (object->IsString() && key->IsNumber()) {
1164 stub = string_stub(); 1229 if (state == UNINITIALIZED) {
1230 stub = string_stub();
1231 }
1165 } else if (object->IsJSObject()) { 1232 } else if (object->IsJSObject()) {
1166 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 1233 JSObject* receiver = JSObject::cast(*object);
1167 if (receiver->HasExternalArrayElements()) { 1234 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(); 1235 stub = indexed_interceptor_stub();
1175 } else if (key->IsSmi() && 1236 } else if (key->IsSmi()) {
1176 receiver->map()->has_fast_elements()) { 1237 MaybeObject* maybe_stub = ComputeStub(receiver,
1177 MaybeObject* probe = 1238 false,
1178 isolate()->stub_cache()->ComputeKeyedLoadSpecialized(*receiver); 1239 kNonStrictMode,
1179 stub = probe->IsFailure() ? 1240 stub);
1180 NULL : Code::cast(probe->ToObjectUnchecked()); 1241 stub = maybe_stub->IsFailure() ?
1242 NULL : Code::cast(maybe_stub->ToObjectUnchecked());
1181 } 1243 }
1182 } 1244 }
1183 } 1245 }
1184 if (stub != NULL) set_target(stub); 1246 if (stub != NULL) set_target(stub);
1247 }
1185 1248
1186 #ifdef DEBUG 1249 #ifdef DEBUG
1187 TraceIC("KeyedLoadIC", key, state, target()); 1250 TraceIC("KeyedLoadIC", key, state, target());
1188 #endif // DEBUG 1251 #endif // DEBUG
1189 }
1190 1252
1191 // Get the property. 1253 // Get the property.
1192 return Runtime::GetObjectProperty(isolate(), object, key); 1254 return Runtime::GetObjectProperty(isolate(), object, key);
1193 } 1255 }
1194 1256
1195 1257
1196 void KeyedLoadIC::UpdateCaches(LookupResult* lookup, State state, 1258 void KeyedLoadIC::UpdateCaches(LookupResult* lookup, State state,
1197 Handle<Object> object, Handle<String> name) { 1259 Handle<Object> object, Handle<String> name) {
1198 // Bail out if we didn't find a result. 1260 // Bail out if we didn't find a result.
1199 if (!lookup->IsProperty() || !lookup->IsCacheable()) return; 1261 if (!lookup->IsProperty() || !lookup->IsCacheable()) return;
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after
1476 receiver->map(), 1538 receiver->map(),
1477 Code::cast(code)); 1539 Code::cast(code));
1478 } 1540 }
1479 1541
1480 #ifdef DEBUG 1542 #ifdef DEBUG
1481 TraceIC("StoreIC", name, state, target()); 1543 TraceIC("StoreIC", name, state, target());
1482 #endif 1544 #endif
1483 } 1545 }
1484 1546
1485 1547
1548 static bool AddOneReceiverMapIfMissing(MapList* receiver_maps,
1549 Map* new_receiver_map) {
1550 for (int current = 0; current < receiver_maps->length(); ++current) {
1551 if (receiver_maps->at(current) == new_receiver_map) {
1552 return false;
1553 }
1554 }
1555 receiver_maps->Add(new_receiver_map);
1556 return true;
1557 }
1558
1559
1560 void KeyedIC::GetReceiverMapsForStub(Code* stub, MapList* result) {
1561 ASSERT(stub->is_inline_cache_stub());
1562 if (stub == string_stub()) {
1563 return result->Add(isolate()->heap()->string_map());
1564 } else if (stub->is_keyed_load_stub() || stub->is_keyed_store_stub()) {
1565 if (stub->ic_state() == MONOMORPHIC) {
1566 result->Add(Map::cast(stub->FindFirstMap()));
1567 } else {
1568 ASSERT(stub->ic_state() == MEGAMORPHIC);
1569 AssertNoAllocation no_allocation;
1570 int mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT);
1571 for (RelocIterator it(stub, mask); !it.done(); it.next()) {
1572 RelocInfo* info = it.rinfo();
1573 Object* object = info->target_object();
1574 ASSERT(object->IsMap());
1575 result->Add(Map::cast(object));
1576 }
1577 }
1578 }
1579 }
1580
1581
1582 MaybeObject* KeyedIC::ComputeStub(JSObject* receiver,
1583 bool is_store,
1584 StrictModeFlag strict_mode,
1585 Code* generic_stub) {
1586 State ic_state = target()->ic_state();
1587 Code* monomorphic_stub;
1588 // Always compute the MONOMORPHIC stub, even if the MEGAMORPHIC stub ends up
1589 // being used. This is necessary because the megamorphic stub needs to have
1590 // access to more information than what is stored in the receiver map in some
1591 // cases (external arrays need the array type from the MONOMORPHIC stub).
1592 MaybeObject* maybe_stub = ComputeMonomorphicStub(receiver,
1593 is_store,
1594 strict_mode,
1595 generic_stub);
1596 if (!maybe_stub->To(&monomorphic_stub)) return maybe_stub;
1597
1598 if (ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) {
1599 return monomorphic_stub;
1600 }
1601 ASSERT(target() != generic_stub);
1602
1603 // Don't handle megamorphic property accesses for INTERCEPTORS or CALLBACKS
1604 // via megamorphic stubs, since they don't have a map in their relocation info
1605 // and so the stubs can't be harvested for the object needed for a map check.
1606 if (target()->type() != NORMAL) {
1607 return generic_stub;
1608 }
1609
1610 // Determine the list of receiver maps that this call site has seen,
1611 // adding the map that was just encountered.
1612 MapList target_receiver_maps;
1613 GetReceiverMapsForStub(target(), &target_receiver_maps);
1614 if (!AddOneReceiverMapIfMissing(&target_receiver_maps, receiver->map())) {
1615 // If the miss wasn't due to an unseen map, a MEGAMORPHIC stub
1616 // won't help, use the generic stub.
1617 return generic_stub;
1618 }
1619
1620 // TODO(1385): Currently MEGAMORPHIC stubs are cached in the receiver map stub
1621 // cache, but that can put receiver types together from unrelated call sites
1622 // into the same stub--they always handle the union of all receiver maps seen
1623 // at all call sites involving the receiver map. This is only an
1624 // approximation: ideally, there would be a global cache that mapped sets of
1625 // receiver maps to MEGAMORPHIC stubs. The complexity of the MEGAMORPHIC stub
1626 // computation also leads to direct manipulation of the stub cache from the IC
1627 // code, which the global cache solution would avoid.
1628 Code::Kind kind = this->kind();
1629 Code::Flags flags = Code::ComputeFlags(kind,
1630 NOT_IN_LOOP,
1631 MEGAMORPHIC,
1632 strict_mode);
1633 String* megamorphic_name = GetStubNameForCache(MEGAMORPHIC);
1634 Object* maybe_cached_stub = receiver->map()->FindInCodeCache(megamorphic_name,
1635 flags);
1636
1637 // Create a set of all receiver maps that have been seen at the IC call site
1638 // and those seen by the MEGAMORPHIC cached stub, if that's the stub that's
1639 // been selected.
1640 MapList receiver_maps;
1641 if (!maybe_cached_stub->IsUndefined()) {
1642 GetReceiverMapsForStub(Code::cast(maybe_cached_stub), &receiver_maps);
1643 }
1644 bool added_map = false;
1645 for (int i = 0; i < target_receiver_maps.length(); ++i) {
1646 if (AddOneReceiverMapIfMissing(&receiver_maps,
1647 target_receiver_maps.at(i))) {
1648 added_map = true;
1649 }
1650 }
1651 ASSERT(receiver_maps.length() > 0);
1652
1653 // If the maximum number of receiver maps has been exceeded, use the Generic
1654 // version of the IC.
1655 if (receiver_maps.length() > KeyedIC::kMaxKeyedPolymorphism) {
1656 return generic_stub;
1657 }
1658
1659 // If no maps have been seen at the call site that aren't in the cached
1660 // stub, then use it.
1661 if (!added_map) {
1662 ASSERT(!maybe_cached_stub->IsUndefined());
1663 ASSERT(maybe_cached_stub->IsCode());
1664 return Code::cast(maybe_cached_stub);
1665 }
1666
1667 // Lookup all of the receiver maps in the cache, they should all already
1668 // have MONOMORPHIC stubs.
1669 CodeList handler_ics(KeyedIC::kMaxKeyedPolymorphism);
1670 for (int current = 0; current < receiver_maps.length(); ++current) {
1671 Map* receiver_map(receiver_maps.at(current));
1672 MaybeObject* maybe_cached_stub = ComputeMonomorphicStubWithoutMapCheck(
1673 receiver_map,
1674 strict_mode,
1675 generic_stub);
1676 Code* cached_stub;
1677 if (!maybe_cached_stub->To(&cached_stub)) {
1678 return maybe_cached_stub;
1679 }
1680 handler_ics.Add(cached_stub);
1681 }
1682
1683 Code* stub;
1684 // Build the MEGAMORPHIC stub.
1685 maybe_stub = ConstructMegamorphicStub(&receiver_maps,
1686 &handler_ics,
1687 strict_mode);
1688 if (!maybe_stub->To(&stub)) return maybe_stub;
1689
1690 MaybeObject* maybe_update = receiver->UpdateMapCodeCache(
1691 megamorphic_name,
1692 stub);
1693 if (maybe_update->IsFailure()) return maybe_update;
1694 return stub;
1695 }
1696
1697
1698 MaybeObject* KeyedIC::ComputeMonomorphicStubWithoutMapCheck(
1699 Map* receiver_map,
1700 StrictModeFlag strict_mode,
1701 Code* generic_stub) {
1702 if ((receiver_map->instance_type() & kNotStringTag) == 0) {
1703 ASSERT(string_stub() != NULL);
1704 return string_stub();
1705 } else if (receiver_map->has_external_array_elements()) {
1706 // Determine the array type from the default MONOMORPHIC already generated
1707 // stub. There is no other way to determine the type of the external array
1708 // directly from the receiver type.
1709 Code::Kind kind = this->kind();
1710 Code::Flags flags = Code::ComputeMonomorphicFlags(kind,
1711 NORMAL,
1712 strict_mode);
1713 String* monomorphic_name = GetStubNameForCache(MONOMORPHIC);
1714 Object* maybe_default_stub = receiver_map->FindInCodeCache(monomorphic_name,
1715 flags);
1716 if (maybe_default_stub->IsUndefined()) {
1717 return generic_stub;
1718 }
1719 Code* default_stub = Code::cast(maybe_default_stub);
1720 return GetExternalArrayStubWithoutMapCheck(
1721 default_stub->external_array_type());
1722 } else if (receiver_map->has_fast_elements()) {
1723 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
1724 return GetFastElementStubWithoutMapCheck(is_js_array);
1725 } else {
1726 return generic_stub;
1727 }
1728 }
1729
1730
1731 MaybeObject* KeyedIC::ComputeMonomorphicStub(JSObject* receiver,
1732 bool is_store,
1733 StrictModeFlag strict_mode,
1734 Code* generic_stub) {
1735 Code* result = NULL;
1736 if (receiver->HasExternalArrayElements()) {
1737 MaybeObject* maybe_stub =
1738 isolate()->stub_cache()->ComputeKeyedLoadOrStoreExternalArray(
1739 receiver, is_store, strict_mode);
1740 if (!maybe_stub->To(&result)) return maybe_stub;
1741 } else if (receiver->map()->has_fast_elements()) {
1742 MaybeObject* maybe_stub =
1743 isolate()->stub_cache()->ComputeKeyedLoadOrStoreFastElement(
1744 receiver, is_store, strict_mode);
1745 if (!maybe_stub->To(&result)) return maybe_stub;
1746 } else {
1747 result = generic_stub;
1748 }
1749 return result;
1750 }
1751
1752
1753 String* KeyedStoreIC::GetStubNameForCache(IC::State ic_state) {
1754 if (ic_state == MONOMORPHIC) {
1755 return isolate()->heap()->KeyedStoreSpecializedMonomorphic_symbol();
1756 } else {
1757 ASSERT(ic_state == MEGAMORPHIC);
1758 return isolate()->heap()->KeyedStoreSpecializedPolymorphic_symbol();
1759 }
1760 }
1761
1762
1763 MaybeObject* KeyedStoreIC::GetFastElementStubWithoutMapCheck(
1764 bool is_js_array) {
1765 return KeyedStoreFastElementStub(is_js_array).TryGetCode();
1766 }
1767
1768
1769 MaybeObject* KeyedStoreIC::GetExternalArrayStubWithoutMapCheck(
1770 ExternalArrayType array_type) {
1771 return KeyedStoreExternalArrayStub(array_type).TryGetCode();
1772 }
1773
1774
1775 MaybeObject* KeyedStoreIC::ConstructMegamorphicStub(
1776 MapList* receiver_maps,
1777 CodeList* targets,
1778 StrictModeFlag strict_mode) {
1779 Object* object;
1780 KeyedStoreStubCompiler compiler(strict_mode);
1781 MaybeObject* maybe_code = compiler.CompileStoreMegamorphic(receiver_maps,
1782 targets);
1783 if (!maybe_code->ToObject(&object)) return maybe_code;
1784 isolate()->counters()->keyed_store_polymorphic_stubs()->Increment();
1785 PROFILE(isolate(), CodeCreateEvent(
1786 Logger::KEYED_STORE_MEGAMORPHIC_IC_TAG,
1787 Code::cast(object), 0));
1788 return object;
1789 }
1790
1791
1486 MaybeObject* KeyedStoreIC::Store(State state, 1792 MaybeObject* KeyedStoreIC::Store(State state,
1487 StrictModeFlag strict_mode, 1793 StrictModeFlag strict_mode,
1488 Handle<Object> object, 1794 Handle<Object> object,
1489 Handle<Object> key, 1795 Handle<Object> key,
1490 Handle<Object> value) { 1796 Handle<Object> value,
1797 bool force_generic) {
1491 if (key->IsSymbol()) { 1798 if (key->IsSymbol()) {
1492 Handle<String> name = Handle<String>::cast(key); 1799 Handle<String> name = Handle<String>::cast(key);
1493 1800
1494 // If the object is undefined or null it's illegal to try to set any 1801 // If the object is undefined or null it's illegal to try to set any
1495 // properties on it; throw a TypeError in that case. 1802 // properties on it; throw a TypeError in that case.
1496 if (object->IsUndefined() || object->IsNull()) { 1803 if (object->IsUndefined() || object->IsNull()) {
1497 return TypeError("non_object_property_store", object, name); 1804 return TypeError("non_object_property_store", object, name);
1498 } 1805 }
1499 1806
1500 // Ignore stores where the receiver is not a JSObject. 1807 // Ignore stores where the receiver is not a JSObject.
(...skipping 21 matching lines...) Expand all
1522 // Set the property. 1829 // Set the property.
1523 return receiver->SetProperty(*name, *value, NONE, strict_mode); 1830 return receiver->SetProperty(*name, *value, NONE, strict_mode);
1524 } 1831 }
1525 1832
1526 // Do not use ICs for objects that require access checks (including 1833 // Do not use ICs for objects that require access checks (including
1527 // the global object). 1834 // the global object).
1528 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded(); 1835 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded();
1529 ASSERT(!(use_ic && object->IsJSGlobalProxy())); 1836 ASSERT(!(use_ic && object->IsJSGlobalProxy()));
1530 1837
1531 if (use_ic) { 1838 if (use_ic) {
1532 Code* stub = 1839 Code* stub = (strict_mode == kStrictMode)
1533 (strict_mode == kStrictMode) ? generic_stub_strict() : generic_stub(); 1840 ? generic_stub_strict()
1534 if (state == UNINITIALIZED) { 1841 : generic_stub();
1535 if (object->IsJSObject()) { 1842 if (!force_generic) {
1536 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 1843 if (object->IsJSObject() && key->IsSmi()) {
1537 if (receiver->HasExternalArrayElements()) { 1844 JSObject* receiver = JSObject::cast(*object);
1538 MaybeObject* probe = 1845 MaybeObject* maybe_stub = ComputeStub(receiver,
1539 isolate()->stub_cache()->ComputeKeyedLoadOrStoreExternalArray( 1846 true,
1540 *receiver, true, strict_mode); 1847 strict_mode,
1541 stub = probe->IsFailure() ? 1848 stub);
1542 NULL : Code::cast(probe->ToObjectUnchecked()); 1849 stub = maybe_stub->IsFailure() ?
1543 } else if (key->IsSmi() && receiver->map()->has_fast_elements()) { 1850 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 } 1851 }
1551 } 1852 }
1552 if (stub != NULL) set_target(stub); 1853 if (stub != NULL) set_target(stub);
1553 } 1854 }
1554 1855
1856 #ifdef DEBUG
1857 TraceIC("KeyedStoreIC", key, state, target());
1858 #endif
1859
1555 // Set the property. 1860 // Set the property.
1556 return Runtime::SetObjectProperty( 1861 return Runtime::SetObjectProperty(
1557 isolate(), object , key, value, NONE, strict_mode); 1862 isolate(), object , key, value, NONE, strict_mode);
1558 } 1863 }
1559 1864
1560 1865
1561 void KeyedStoreIC::UpdateCaches(LookupResult* lookup, 1866 void KeyedStoreIC::UpdateCaches(LookupResult* lookup,
1562 State state, 1867 State state,
1563 StrictModeFlag strict_mode, 1868 StrictModeFlag strict_mode,
1564 Handle<JSObject> receiver, 1869 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)); 2018 return ic.Load(state, args.at<Object>(0), args.at<String>(1));
1714 } 2019 }
1715 2020
1716 2021
1717 // Used from ic-<arch>.cc 2022 // Used from ic-<arch>.cc
1718 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_Miss) { 2023 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_Miss) {
1719 NoHandleAllocation na; 2024 NoHandleAllocation na;
1720 ASSERT(args.length() == 2); 2025 ASSERT(args.length() == 2);
1721 KeyedLoadIC ic(isolate); 2026 KeyedLoadIC ic(isolate);
1722 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); 2027 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
1723 return ic.Load(state, args.at<Object>(0), args.at<Object>(1)); 2028 return ic.Load(state, args.at<Object>(0), args.at<Object>(1), false);
2029 }
2030
2031
2032 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_MissForceGeneric) {
2033 NoHandleAllocation na;
2034 ASSERT(args.length() == 2);
2035 KeyedLoadIC ic(isolate);
2036 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
2037 return ic.Load(state, args.at<Object>(0), args.at<Object>(1), true);
1724 } 2038 }
1725 2039
1726 2040
1727 // Used from ic-<arch>.cc. 2041 // Used from ic-<arch>.cc.
1728 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Miss) { 2042 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Miss) {
1729 NoHandleAllocation na; 2043 NoHandleAllocation na;
1730 ASSERT(args.length() == 3); 2044 ASSERT(args.length() == 3);
1731 StoreIC ic(isolate); 2045 StoreIC ic(isolate);
1732 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); 2046 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
1733 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); 2047 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
1797 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Miss) { 2111 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Miss) {
1798 NoHandleAllocation na; 2112 NoHandleAllocation na;
1799 ASSERT(args.length() == 3); 2113 ASSERT(args.length() == 3);
1800 KeyedStoreIC ic(isolate); 2114 KeyedStoreIC ic(isolate);
1801 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); 2115 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
1802 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); 2116 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
1803 return ic.Store(state, 2117 return ic.Store(state,
1804 static_cast<StrictModeFlag>(extra_ic_state & kStrictMode), 2118 static_cast<StrictModeFlag>(extra_ic_state & kStrictMode),
1805 args.at<Object>(0), 2119 args.at<Object>(0),
1806 args.at<Object>(1), 2120 args.at<Object>(1),
1807 args.at<Object>(2)); 2121 args.at<Object>(2),
2122 false);
2123 }
2124
2125
2126 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Slow) {
2127 NoHandleAllocation na;
2128 ASSERT(args.length() == 3);
2129 KeyedStoreIC ic(isolate);
2130 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
2131 Handle<Object> object = args.at<Object>(0);
2132 Handle<Object> key = args.at<Object>(1);
2133 Handle<Object> value = args.at<Object>(2);
2134 StrictModeFlag strict_mode =
2135 static_cast<StrictModeFlag>(extra_ic_state & kStrictMode);
2136 return Runtime::SetObjectProperty(isolate,
2137 object,
2138 key,
2139 value,
2140 NONE,
2141 strict_mode);
2142 }
2143
2144
2145 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissForceGeneric) {
2146 NoHandleAllocation na;
2147 ASSERT(args.length() == 3);
2148 KeyedStoreIC ic(isolate);
2149 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
2150 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
2151 return ic.Store(state,
2152 static_cast<StrictModeFlag>(extra_ic_state & kStrictMode),
2153 args.at<Object>(0),
2154 args.at<Object>(1),
2155 args.at<Object>(2),
2156 true);
1808 } 2157 }
1809 2158
1810 2159
1811 void TRUnaryOpIC::patch(Code* code) { 2160 void TRUnaryOpIC::patch(Code* code) {
1812 set_target(code); 2161 set_target(code);
1813 } 2162 }
1814 2163
1815 2164
1816 const char* TRUnaryOpIC::GetName(TypeInfo type_info) { 2165 const char* TRUnaryOpIC::GetName(TypeInfo type_info) {
1817 switch (type_info) { 2166 switch (type_info) {
(...skipping 26 matching lines...) Expand all
1844 if (operand_type.IsSmi()) { 2193 if (operand_type.IsSmi()) {
1845 return SMI; 2194 return SMI;
1846 } else if (operand_type.IsNumber()) { 2195 } else if (operand_type.IsNumber()) {
1847 return HEAP_NUMBER; 2196 return HEAP_NUMBER;
1848 } else { 2197 } else {
1849 return GENERIC; 2198 return GENERIC;
1850 } 2199 }
1851 } 2200 }
1852 2201
1853 2202
1854 TRUnaryOpIC::TypeInfo TRUnaryOpIC::JoinTypes(TRUnaryOpIC::TypeInfo x, 2203 TRUnaryOpIC::TypeInfo TRUnaryOpIC::ComputeNewType(
1855 TRUnaryOpIC::TypeInfo y) { 2204 TRUnaryOpIC::TypeInfo type,
1856 return x >= y ? x : y; 2205 TRUnaryOpIC::TypeInfo previous) {
2206 switch (previous) {
2207 case TRUnaryOpIC::UNINITIALIZED:
2208 return type;
2209 case TRUnaryOpIC::SMI:
2210 return (type == TRUnaryOpIC::GENERIC)
2211 ? TRUnaryOpIC::GENERIC
2212 : TRUnaryOpIC::HEAP_NUMBER;
2213 case TRUnaryOpIC::HEAP_NUMBER:
2214 return TRUnaryOpIC::GENERIC;
2215 case TRUnaryOpIC::GENERIC:
2216 // We should never do patching if we are in GENERIC state.
2217 UNREACHABLE();
2218 return TRUnaryOpIC::GENERIC;
2219 }
2220 UNREACHABLE();
2221 return TRUnaryOpIC::GENERIC;
1857 } 2222 }
1858 2223
1859 2224
1860 void TRBinaryOpIC::patch(Code* code) { 2225 void TRBinaryOpIC::patch(Code* code) {
1861 set_target(code); 2226 set_target(code);
1862 } 2227 }
1863 2228
1864 2229
1865 const char* TRBinaryOpIC::GetName(TypeInfo type_info) { 2230 const char* TRBinaryOpIC::GetName(TypeInfo type_info) {
1866 switch (type_info) { 2231 switch (type_info) {
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
1958 ASSERT(args.length() == 4); 2323 ASSERT(args.length() == 4);
1959 2324
1960 HandleScope scope(isolate); 2325 HandleScope scope(isolate);
1961 Handle<Object> operand = args.at<Object>(0); 2326 Handle<Object> operand = args.at<Object>(0);
1962 int key = Smi::cast(args[1])->value(); 2327 int key = Smi::cast(args[1])->value();
1963 Token::Value op = static_cast<Token::Value>(Smi::cast(args[2])->value()); 2328 Token::Value op = static_cast<Token::Value>(Smi::cast(args[2])->value());
1964 TRUnaryOpIC::TypeInfo previous_type = 2329 TRUnaryOpIC::TypeInfo previous_type =
1965 static_cast<TRUnaryOpIC::TypeInfo>(Smi::cast(args[3])->value()); 2330 static_cast<TRUnaryOpIC::TypeInfo>(Smi::cast(args[3])->value());
1966 2331
1967 TRUnaryOpIC::TypeInfo type = TRUnaryOpIC::GetTypeInfo(operand); 2332 TRUnaryOpIC::TypeInfo type = TRUnaryOpIC::GetTypeInfo(operand);
1968 type = TRUnaryOpIC::JoinTypes(type, previous_type); 2333 type = TRUnaryOpIC::ComputeNewType(type, previous_type);
1969 2334
1970 Handle<Code> code = GetTypeRecordingUnaryOpStub(key, type); 2335 Handle<Code> code = GetTypeRecordingUnaryOpStub(key, type);
1971 if (!code.is_null()) { 2336 if (!code.is_null()) {
1972 if (FLAG_trace_ic) { 2337 if (FLAG_trace_ic) {
1973 PrintF("[TypeRecordingUnaryOpIC (%s->%s)#%s]\n", 2338 PrintF("[TypeRecordingUnaryOpIC (%s->%s)#%s]\n",
1974 TRUnaryOpIC::GetName(previous_type), 2339 TRUnaryOpIC::GetName(previous_type),
1975 TRUnaryOpIC::GetName(type), 2340 TRUnaryOpIC::GetName(type),
1976 Token::Name(op)); 2341 Token::Name(op));
1977 } 2342 }
1978 TRUnaryOpIC ic(isolate); 2343 TRUnaryOpIC ic(isolate);
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
2023 static_cast<TRBinaryOpIC::TypeInfo>(Smi::cast(args[4])->value()); 2388 static_cast<TRBinaryOpIC::TypeInfo>(Smi::cast(args[4])->value());
2024 2389
2025 TRBinaryOpIC::TypeInfo type = TRBinaryOpIC::GetTypeInfo(left, right); 2390 TRBinaryOpIC::TypeInfo type = TRBinaryOpIC::GetTypeInfo(left, right);
2026 type = TRBinaryOpIC::JoinTypes(type, previous_type); 2391 type = TRBinaryOpIC::JoinTypes(type, previous_type);
2027 TRBinaryOpIC::TypeInfo result_type = TRBinaryOpIC::UNINITIALIZED; 2392 TRBinaryOpIC::TypeInfo result_type = TRBinaryOpIC::UNINITIALIZED;
2028 if ((type == TRBinaryOpIC::STRING || type == TRBinaryOpIC::BOTH_STRING) && 2393 if ((type == TRBinaryOpIC::STRING || type == TRBinaryOpIC::BOTH_STRING) &&
2029 op != Token::ADD) { 2394 op != Token::ADD) {
2030 type = TRBinaryOpIC::GENERIC; 2395 type = TRBinaryOpIC::GENERIC;
2031 } 2396 }
2032 if (type == TRBinaryOpIC::SMI && previous_type == TRBinaryOpIC::SMI) { 2397 if (type == TRBinaryOpIC::SMI && previous_type == TRBinaryOpIC::SMI) {
2033 if (op == Token::DIV || op == Token::MUL || kSmiValueSize == 32) { 2398 if (op == Token::DIV ||
2399 op == Token::MUL ||
2400 op == Token::SHR ||
2401 kSmiValueSize == 32) {
2034 // Arithmetic on two Smi inputs has yielded a heap number. 2402 // Arithmetic on two Smi inputs has yielded a heap number.
2035 // That is the only way to get here from the Smi stub. 2403 // That is the only way to get here from the Smi stub.
2036 // With 32-bit Smis, all overflows give heap numbers, but with 2404 // With 32-bit Smis, all overflows give heap numbers, but with
2037 // 31-bit Smis, most operations overflow to int32 results. 2405 // 31-bit Smis, most operations overflow to int32 results.
2038 result_type = TRBinaryOpIC::HEAP_NUMBER; 2406 result_type = TRBinaryOpIC::HEAP_NUMBER;
2039 } else { 2407 } else {
2040 // Other operations on SMIs that overflow yield int32s. 2408 // Other operations on SMIs that overflow yield int32s.
2041 result_type = TRBinaryOpIC::INT32; 2409 result_type = TRBinaryOpIC::INT32;
2042 } 2410 }
2043 } 2411 }
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
2134 return static_cast<State>(target->compare_state()); 2502 return static_cast<State>(target->compare_state());
2135 } 2503 }
2136 2504
2137 2505
2138 const char* CompareIC::GetStateName(State state) { 2506 const char* CompareIC::GetStateName(State state) {
2139 switch (state) { 2507 switch (state) {
2140 case UNINITIALIZED: return "UNINITIALIZED"; 2508 case UNINITIALIZED: return "UNINITIALIZED";
2141 case SMIS: return "SMIS"; 2509 case SMIS: return "SMIS";
2142 case HEAP_NUMBERS: return "HEAP_NUMBERS"; 2510 case HEAP_NUMBERS: return "HEAP_NUMBERS";
2143 case OBJECTS: return "OBJECTS"; 2511 case OBJECTS: return "OBJECTS";
2512 case SYMBOLS: return "SYMBOLS";
2144 case STRINGS: return "STRINGS"; 2513 case STRINGS: return "STRINGS";
2145 case GENERIC: return "GENERIC"; 2514 case GENERIC: return "GENERIC";
2146 default: 2515 default:
2147 UNREACHABLE(); 2516 UNREACHABLE();
2148 return NULL; 2517 return NULL;
2149 } 2518 }
2150 } 2519 }
2151 2520
2152 2521
2153 CompareIC::State CompareIC::TargetState(State state, 2522 CompareIC::State CompareIC::TargetState(State state,
2154 bool has_inlined_smi_code, 2523 bool has_inlined_smi_code,
2155 Handle<Object> x, 2524 Handle<Object> x,
2156 Handle<Object> y) { 2525 Handle<Object> y) {
2157 if (!has_inlined_smi_code && state != UNINITIALIZED) return GENERIC; 2526 if (!has_inlined_smi_code && state != UNINITIALIZED && state != SYMBOLS) {
2527 return GENERIC;
2528 }
2158 if (state == UNINITIALIZED && x->IsSmi() && y->IsSmi()) return SMIS; 2529 if (state == UNINITIALIZED && x->IsSmi() && y->IsSmi()) return SMIS;
2159 if ((state == UNINITIALIZED || (state == SMIS && has_inlined_smi_code)) && 2530 if ((state == UNINITIALIZED || (state == SMIS && has_inlined_smi_code)) &&
2160 x->IsNumber() && y->IsNumber()) return HEAP_NUMBERS; 2531 x->IsNumber() && y->IsNumber()) return HEAP_NUMBERS;
2161 if (op_ != Token::EQ && op_ != Token::EQ_STRICT) return GENERIC; 2532 if (op_ != Token::EQ && op_ != Token::EQ_STRICT) return GENERIC;
2162 if (state == UNINITIALIZED && 2533 if (state == UNINITIALIZED &&
2534 x->IsSymbol() && y->IsSymbol()) return SYMBOLS;
2535 if ((state == UNINITIALIZED || state == SYMBOLS) &&
2163 x->IsString() && y->IsString()) return STRINGS; 2536 x->IsString() && y->IsString()) return STRINGS;
2164 if (state == UNINITIALIZED && 2537 if (state == UNINITIALIZED &&
2165 x->IsJSObject() && y->IsJSObject()) return OBJECTS; 2538 x->IsJSObject() && y->IsJSObject()) return OBJECTS;
2166 return GENERIC; 2539 return GENERIC;
2167 } 2540 }
2168 2541
2169 2542
2170 // Used from ic_<arch>.cc. 2543 // Used from ic_<arch>.cc.
2171 RUNTIME_FUNCTION(Code*, CompareIC_Miss) { 2544 RUNTIME_FUNCTION(Code*, CompareIC_Miss) {
2172 NoHandleAllocation na; 2545 NoHandleAllocation na;
(...skipping 11 matching lines...) Expand all
2184 #undef ADDR 2557 #undef ADDR
2185 }; 2558 };
2186 2559
2187 2560
2188 Address IC::AddressFromUtilityId(IC::UtilityId id) { 2561 Address IC::AddressFromUtilityId(IC::UtilityId id) {
2189 return IC_utilities[id]; 2562 return IC_utilities[id];
2190 } 2563 }
2191 2564
2192 2565
2193 } } // namespace v8::internal 2566 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ic.h ('k') | src/isolate.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698