OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 |
(...skipping 945 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
956 return ReferenceError("not_defined", name); | 956 return ReferenceError("not_defined", name); |
957 } | 957 } |
958 return *result; | 958 return *result; |
959 } | 959 } |
960 | 960 |
961 // Get the property. | 961 // Get the property. |
962 return object->GetProperty(*object, &lookup, *name, &attr); | 962 return object->GetProperty(*object, &lookup, *name, &attr); |
963 } | 963 } |
964 | 964 |
965 | 965 |
966 void LoadIC::UpdateCaches(LookupResult* lookup, | 966 void IC::PatchCache(State state, |
967 State state, | 967 StrictModeFlag strict_mode, |
968 Handle<Object> object, | 968 Handle<JSObject> receiver, |
969 Handle<String> name) { | 969 Handle<String> name, |
970 // Bail out if the result is not cacheable. | 970 Handle<Code> code) { |
971 if (!lookup->IsCacheable()) return; | |
972 | |
973 // Loading properties from values is not common, so don't try to | |
974 // deal with non-JS objects here. | |
975 if (!object->IsJSObject()) return; | |
976 | |
977 if (HasNormalObjectsInPrototypeChain(isolate(), lookup, *object)) return; | |
978 | |
979 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | |
980 Handle<Code> code; | |
981 if (state == UNINITIALIZED) { | |
982 // This is the first time we execute this inline cache. | |
983 // Set the target to the pre monomorphic stub to delay | |
984 // setting the monomorphic state. | |
985 code = pre_monomorphic_stub(); | |
986 } else { | |
987 code = ComputeLoadMonomorphic(lookup, receiver, name); | |
988 if (code.is_null()) return; | |
989 } | |
990 | |
991 // Patch the call site depending on the state of the cache. | |
992 switch (state) { | 971 switch (state) { |
993 case UNINITIALIZED: | 972 case UNINITIALIZED: |
994 case PREMONOMORPHIC: | 973 case PREMONOMORPHIC: |
995 case MONOMORPHIC_PROTOTYPE_FAILURE: | 974 case MONOMORPHIC_PROTOTYPE_FAILURE: |
| 975 case POLYMORPHIC: |
996 set_target(*code); | 976 set_target(*code); |
997 break; | 977 break; |
998 case MONOMORPHIC: | 978 case MONOMORPHIC: |
| 979 // Only move to megamorphic if the target changes. |
999 if (target() != *code) { | 980 if (target() != *code) { |
1000 // We are transitioning from monomorphic to megamorphic case. | 981 // We are transitioning from monomorphic to megamorphic case. |
1001 // Place the current monomorphic stub and stub compiled for | 982 // Place the current monomorphic stub and stub compiled for |
1002 // the receiver into stub cache. | 983 // the receiver into stub cache. |
1003 Map* map = target()->FindFirstMap(); | 984 Map* map = target()->FindFirstMap(); |
1004 if (map != NULL) { | 985 if (map != NULL) { |
1005 UpdateMegamorphicCache(map, *name, target()); | 986 UpdateMegamorphicCache(map, *name, target()); |
1006 } | 987 } |
1007 UpdateMegamorphicCache(receiver->map(), *name, *code); | 988 UpdateMegamorphicCache(receiver->map(), *name, *code); |
1008 set_target(*megamorphic_stub()); | 989 set_target((strict_mode == kStrictMode) |
| 990 ? *megamorphic_stub_strict() |
| 991 : *megamorphic_stub()); |
1009 } | 992 } |
1010 break; | 993 break; |
1011 case MEGAMORPHIC: | 994 case MEGAMORPHIC: |
| 995 // Update the stub cache. |
1012 UpdateMegamorphicCache(receiver->map(), *name, *code); | 996 UpdateMegamorphicCache(receiver->map(), *name, *code); |
1013 break; | 997 break; |
| 998 case GENERIC: |
1014 case DEBUG_STUB: | 999 case DEBUG_STUB: |
1015 break; | 1000 break; |
1016 case POLYMORPHIC: | 1001 } |
1017 case GENERIC: | 1002 } |
1018 UNREACHABLE(); | 1003 |
1019 break; | 1004 |
| 1005 void LoadIC::UpdateCaches(LookupResult* lookup, |
| 1006 State state, |
| 1007 Handle<Object> object, |
| 1008 Handle<String> name) { |
| 1009 // Bail out if the result is not cacheable. |
| 1010 if (!lookup->IsCacheable()) return; |
| 1011 |
| 1012 // Loading properties from values is not common, so don't try to |
| 1013 // deal with non-JS objects here. |
| 1014 if (!object->IsJSObject()) return; |
| 1015 |
| 1016 if (HasNormalObjectsInPrototypeChain(isolate(), lookup, *object)) return; |
| 1017 |
| 1018 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
| 1019 Handle<Code> code; |
| 1020 if (state == UNINITIALIZED) { |
| 1021 // This is the first time we execute this inline cache. |
| 1022 // Set the target to the pre monomorphic stub to delay |
| 1023 // setting the monomorphic state. |
| 1024 code = pre_monomorphic_stub(); |
| 1025 } else { |
| 1026 code = ComputeLoadMonomorphic(lookup, receiver, name); |
| 1027 if (code.is_null()) return; |
1020 } | 1028 } |
1021 | 1029 |
| 1030 PatchCache(state, kNonStrictMode, receiver, name, code); |
1022 TRACE_IC("LoadIC", name, state, target()); | 1031 TRACE_IC("LoadIC", name, state, target()); |
1023 } | 1032 } |
1024 | 1033 |
1025 | 1034 |
1026 void LoadIC::UpdateMegamorphicCache(Map* map, String* name, Code* code) { | 1035 void IC::UpdateMegamorphicCache(Map* map, String* name, Code* code) { |
1027 // Cache code holding map should be consistent with | 1036 // Cache code holding map should be consistent with |
1028 // GenerateMonomorphicCacheProbe. | 1037 // GenerateMonomorphicCacheProbe. |
1029 isolate()->stub_cache()->Set(name, map, code); | 1038 isolate()->stub_cache()->Set(name, map, code); |
1030 } | 1039 } |
1031 | 1040 |
1032 | 1041 |
1033 Handle<Code> LoadIC::ComputeLoadMonomorphic(LookupResult* lookup, | 1042 Handle<Code> LoadIC::ComputeLoadMonomorphic(LookupResult* lookup, |
1034 Handle<JSObject> receiver, | 1043 Handle<JSObject> receiver, |
1035 Handle<String> name) { | 1044 Handle<String> name) { |
1036 if (!lookup->IsProperty()) { | 1045 if (!lookup->IsProperty()) { |
(...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1417 : global_proxy_stub(); | 1426 : global_proxy_stub(); |
1418 set_target(*stub); | 1427 set_target(*stub); |
1419 TRACE_IC("StoreIC", name, state, *stub); | 1428 TRACE_IC("StoreIC", name, state, *stub); |
1420 } | 1429 } |
1421 return receiver->SetProperty(*name, *value, NONE, strict_mode, store_mode); | 1430 return receiver->SetProperty(*name, *value, NONE, strict_mode, store_mode); |
1422 } | 1431 } |
1423 | 1432 |
1424 LookupResult lookup(isolate()); | 1433 LookupResult lookup(isolate()); |
1425 if (LookupForWrite(receiver, name, &lookup)) { | 1434 if (LookupForWrite(receiver, name, &lookup)) { |
1426 if (FLAG_use_ic) { | 1435 if (FLAG_use_ic) { |
1427 UpdateStoreCaches(&lookup, state, strict_mode, receiver, name, value); | 1436 UpdateCaches(&lookup, state, strict_mode, receiver, name, value); |
1428 } | 1437 } |
1429 } else if (strict_mode == kStrictMode && | 1438 } else if (strict_mode == kStrictMode && |
1430 !(lookup.IsProperty() && lookup.IsReadOnly()) && | 1439 !(lookup.IsProperty() && lookup.IsReadOnly()) && |
1431 IsUndeclaredGlobal(object)) { | 1440 IsUndeclaredGlobal(object)) { |
1432 // Strict mode doesn't allow setting non-existent global property. | 1441 // Strict mode doesn't allow setting non-existent global property. |
1433 return ReferenceError("not_defined", name); | 1442 return ReferenceError("not_defined", name); |
1434 } | 1443 } |
1435 | 1444 |
1436 // Set the property. | 1445 // Set the property. |
1437 return receiver->SetProperty(*name, *value, NONE, strict_mode, store_mode); | 1446 return receiver->SetProperty(*name, *value, NONE, strict_mode, store_mode); |
1438 } | 1447 } |
1439 | 1448 |
1440 | 1449 |
1441 void StoreIC::UpdateStoreCaches(LookupResult* lookup, | 1450 void StoreIC::UpdateCaches(LookupResult* lookup, |
1442 State state, | 1451 State state, |
1443 StrictModeFlag strict_mode, | 1452 StrictModeFlag strict_mode, |
1444 Handle<JSObject> receiver, | 1453 Handle<JSObject> receiver, |
1445 Handle<String> name, | 1454 Handle<String> name, |
1446 Handle<Object> value) { | 1455 Handle<Object> value) { |
1447 ASSERT(!receiver->IsJSGlobalProxy()); | 1456 ASSERT(!receiver->IsJSGlobalProxy()); |
1448 ASSERT(StoreICableLookup(lookup)); | 1457 ASSERT(StoreICableLookup(lookup)); |
1449 ASSERT(lookup->IsFound()); | 1458 ASSERT(lookup->IsFound()); |
1450 | 1459 |
1451 // These are not cacheable, so we never see such LookupResults here. | 1460 // These are not cacheable, so we never see such LookupResults here. |
1452 ASSERT(!lookup->IsHandler()); | 1461 ASSERT(!lookup->IsHandler()); |
1453 | 1462 |
1454 // If the property has a non-field type allowing map transitions | 1463 Handle<Code> code = |
1455 // where there is extra room in the object, we leave the IC in its | 1464 ComputeStoreMonomorphic(lookup, strict_mode, receiver, name); |
1456 // current state. | 1465 if (code.is_null()) return; |
1457 PropertyType type = lookup->type(); | |
1458 | 1466 |
1459 // Compute the code stub for this store; used for rewriting to | 1467 PatchCache(state, strict_mode, receiver, name, code); |
1460 // monomorphic state and making sure that the code stub is in the | 1468 TRACE_IC("StoreIC", name, state, target()); |
1461 // stub cache. | 1469 } |
| 1470 |
| 1471 |
| 1472 Handle<Code> StoreIC::ComputeStoreMonomorphic(LookupResult* lookup, |
| 1473 StrictModeFlag strict_mode, |
| 1474 Handle<JSObject> receiver, |
| 1475 Handle<String> name) { |
1462 Handle<JSObject> holder(lookup->holder()); | 1476 Handle<JSObject> holder(lookup->holder()); |
1463 Handle<Code> code; | 1477 switch (lookup->type()) { |
1464 switch (type) { | |
1465 case FIELD: | 1478 case FIELD: |
1466 code = isolate()->stub_cache()->ComputeStoreField( | 1479 return isolate()->stub_cache()->ComputeStoreField( |
1467 name, receiver, lookup->GetFieldIndex().field_index(), | 1480 name, receiver, lookup->GetFieldIndex().field_index(), |
1468 Handle<Map>::null(), strict_mode); | 1481 Handle<Map>::null(), strict_mode); |
1469 break; | |
1470 case NORMAL: | 1482 case NORMAL: |
1471 if (receiver->IsGlobalObject()) { | 1483 if (receiver->IsGlobalObject()) { |
1472 // The stub generated for the global object picks the value directly | 1484 // The stub generated for the global object picks the value directly |
1473 // from the property cell. So the property must be directly on the | 1485 // from the property cell. So the property must be directly on the |
1474 // global object. | 1486 // global object. |
1475 Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver); | 1487 Handle<GlobalObject> global = Handle<GlobalObject>::cast(receiver); |
1476 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(lookup)); | 1488 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(lookup)); |
1477 code = isolate()->stub_cache()->ComputeStoreGlobal( | 1489 return isolate()->stub_cache()->ComputeStoreGlobal( |
1478 name, global, cell, strict_mode); | 1490 name, global, cell, strict_mode); |
1479 } else { | |
1480 if (!holder.is_identical_to(receiver)) return; | |
1481 code = isolate()->stub_cache()->ComputeStoreNormal(strict_mode); | |
1482 } | 1491 } |
1483 break; | 1492 if (!holder.is_identical_to(receiver)) break; |
| 1493 return isolate()->stub_cache()->ComputeStoreNormal(strict_mode); |
1484 case CALLBACKS: { | 1494 case CALLBACKS: { |
1485 Handle<Object> callback(lookup->GetCallbackObject()); | 1495 Handle<Object> callback(lookup->GetCallbackObject()); |
1486 if (callback->IsAccessorInfo()) { | 1496 if (callback->IsAccessorInfo()) { |
1487 Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(callback); | 1497 Handle<AccessorInfo> info = Handle<AccessorInfo>::cast(callback); |
1488 if (v8::ToCData<Address>(info->setter()) == 0) return; | 1498 if (v8::ToCData<Address>(info->setter()) == 0) break; |
1489 if (!holder->HasFastProperties()) return; | 1499 if (!holder->HasFastProperties()) break; |
1490 if (!info->IsCompatibleReceiver(*receiver)) return; | 1500 if (!info->IsCompatibleReceiver(*receiver)) break; |
1491 code = isolate()->stub_cache()->ComputeStoreCallback( | 1501 return isolate()->stub_cache()->ComputeStoreCallback( |
1492 name, receiver, holder, info, strict_mode); | 1502 name, receiver, holder, info, strict_mode); |
1493 } else if (callback->IsAccessorPair()) { | 1503 } else if (callback->IsAccessorPair()) { |
1494 Handle<Object> setter(Handle<AccessorPair>::cast(callback)->setter()); | 1504 Handle<Object> setter(Handle<AccessorPair>::cast(callback)->setter()); |
1495 if (!setter->IsJSFunction()) return; | 1505 if (!setter->IsJSFunction()) break; |
1496 if (holder->IsGlobalObject()) return; | 1506 if (holder->IsGlobalObject()) break; |
1497 if (!holder->HasFastProperties()) return; | 1507 if (!holder->HasFastProperties()) break; |
1498 code = isolate()->stub_cache()->ComputeStoreViaSetter( | 1508 return isolate()->stub_cache()->ComputeStoreViaSetter( |
1499 name, receiver, holder, Handle<JSFunction>::cast(setter), | 1509 name, receiver, holder, Handle<JSFunction>::cast(setter), |
1500 strict_mode); | 1510 strict_mode); |
1501 } else { | |
1502 ASSERT(callback->IsForeign()); | |
1503 // No IC support for old-style native accessors. | |
1504 return; | |
1505 } | 1511 } |
| 1512 ASSERT(callback->IsForeign()); |
| 1513 // No IC support for old-style native accessors. |
1506 break; | 1514 break; |
1507 } | 1515 } |
1508 case INTERCEPTOR: | 1516 case INTERCEPTOR: |
1509 ASSERT(!receiver->GetNamedInterceptor()->setter()->IsUndefined()); | 1517 ASSERT(!receiver->GetNamedInterceptor()->setter()->IsUndefined()); |
1510 code = isolate()->stub_cache()->ComputeStoreInterceptor( | 1518 return isolate()->stub_cache()->ComputeStoreInterceptor( |
1511 name, receiver, strict_mode); | 1519 name, receiver, strict_mode); |
| 1520 case CONSTANT_FUNCTION: |
1512 break; | 1521 break; |
1513 case CONSTANT_FUNCTION: | |
1514 return; | |
1515 case TRANSITION: { | 1522 case TRANSITION: { |
1516 Handle<Map> transition(lookup->GetTransitionTarget()); | 1523 Handle<Map> transition(lookup->GetTransitionTarget()); |
1517 int descriptor = transition->LastAdded(); | 1524 int descriptor = transition->LastAdded(); |
1518 | 1525 |
1519 DescriptorArray* target_descriptors = transition->instance_descriptors(); | 1526 DescriptorArray* target_descriptors = transition->instance_descriptors(); |
1520 PropertyDetails details = target_descriptors->GetDetails(descriptor); | 1527 PropertyDetails details = target_descriptors->GetDetails(descriptor); |
1521 | 1528 |
1522 if (details.type() != FIELD || details.attributes() != NONE) return; | 1529 if (details.type() != FIELD || details.attributes() != NONE) break; |
1523 | 1530 |
1524 int field_index = target_descriptors->GetFieldIndex(descriptor); | 1531 int field_index = target_descriptors->GetFieldIndex(descriptor); |
1525 code = isolate()->stub_cache()->ComputeStoreField( | 1532 return isolate()->stub_cache()->ComputeStoreField( |
1526 name, receiver, field_index, transition, strict_mode); | 1533 name, receiver, field_index, transition, strict_mode); |
1527 | |
1528 break; | |
1529 } | 1534 } |
1530 case NONEXISTENT: | 1535 case NONEXISTENT: |
1531 case HANDLER: | 1536 case HANDLER: |
1532 UNREACHABLE(); | 1537 UNREACHABLE(); |
1533 return; | |
1534 } | |
1535 | |
1536 // Patch the call site depending on the state of the cache. | |
1537 switch (state) { | |
1538 case UNINITIALIZED: | |
1539 case PREMONOMORPHIC: | |
1540 case MONOMORPHIC_PROTOTYPE_FAILURE: | |
1541 set_target(*code); | |
1542 break; | |
1543 case MONOMORPHIC: | |
1544 // Only move to megamorphic if the target changes. | |
1545 if (target() != *code) { | |
1546 // We are transitioning from monomorphic to megamorphic case. | |
1547 // Place the current monomorphic stub and stub compiled for | |
1548 // the receiver into stub cache. | |
1549 Map* map = target()->FindFirstMap(); | |
1550 if (map != NULL) { | |
1551 isolate()->stub_cache()->Set(*name, map, target()); | |
1552 } | |
1553 isolate()->stub_cache()->Set(*name, receiver->map(), *code); | |
1554 set_target((strict_mode == kStrictMode) | |
1555 ? *megamorphic_stub_strict() | |
1556 : *megamorphic_stub()); | |
1557 } | |
1558 break; | |
1559 case MEGAMORPHIC: | |
1560 // Update the stub cache. | |
1561 isolate()->stub_cache()->Set(*name, receiver->map(), *code); | |
1562 break; | |
1563 case DEBUG_STUB: | |
1564 break; | |
1565 case POLYMORPHIC: | |
1566 case GENERIC: | |
1567 UNREACHABLE(); | |
1568 break; | 1538 break; |
1569 } | 1539 } |
1570 | 1540 return Handle<Code>::null(); |
1571 TRACE_IC("StoreIC", name, state, target()); | |
1572 } | 1541 } |
1573 | 1542 |
1574 | 1543 |
1575 Handle<Code> KeyedStoreIC::StoreElementStub(Handle<JSObject> receiver, | 1544 Handle<Code> KeyedStoreIC::StoreElementStub(Handle<JSObject> receiver, |
1576 StubKind stub_kind, | 1545 StubKind stub_kind, |
1577 StrictModeFlag strict_mode) { | 1546 StrictModeFlag strict_mode) { |
1578 State ic_state = target()->ic_state(); | 1547 State ic_state = target()->ic_state(); |
1579 KeyedAccessGrowMode grow_mode = IsGrowStubKind(stub_kind) | 1548 KeyedAccessGrowMode grow_mode = IsGrowStubKind(stub_kind) |
1580 ? ALLOW_JSARRAY_GROWTH | 1549 ? ALLOW_JSARRAY_GROWTH |
1581 : DO_NOT_ALLOW_JSARRAY_GROWTH; | 1550 : DO_NOT_ALLOW_JSARRAY_GROWTH; |
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1797 } | 1766 } |
1798 | 1767 |
1799 TRACE_IC("KeyedStoreIC", key, state, target()); | 1768 TRACE_IC("KeyedStoreIC", key, state, target()); |
1800 | 1769 |
1801 // Set the property. | 1770 // Set the property. |
1802 return Runtime::SetObjectProperty( | 1771 return Runtime::SetObjectProperty( |
1803 isolate(), object , key, value, NONE, strict_mode); | 1772 isolate(), object , key, value, NONE, strict_mode); |
1804 } | 1773 } |
1805 | 1774 |
1806 | 1775 |
1807 void KeyedStoreIC::UpdateStoreCaches(LookupResult* lookup, | 1776 Handle<Code> KeyedStoreIC::ComputeStoreMonomorphic(LookupResult* lookup, |
1808 State state, | 1777 StrictModeFlag strict_mode, |
1809 StrictModeFlag strict_mode, | 1778 Handle<JSObject> receiver, |
1810 Handle<JSObject> receiver, | 1779 Handle<String> name) { |
1811 Handle<String> name, | |
1812 Handle<Object> value) { | |
1813 ASSERT(!receiver->IsJSGlobalProxy()); | |
1814 ASSERT(StoreICableLookup(lookup)); | |
1815 ASSERT(lookup->IsFound()); | |
1816 | |
1817 // These are not cacheable, so we never see such LookupResults here. | |
1818 ASSERT(!lookup->IsHandler()); | |
1819 | |
1820 // If the property has a non-field type allowing map transitions | 1780 // If the property has a non-field type allowing map transitions |
1821 // where there is extra room in the object, we leave the IC in its | 1781 // where there is extra room in the object, we leave the IC in its |
1822 // current state. | 1782 // current state. |
1823 PropertyType type = lookup->type(); | 1783 switch (lookup->type()) { |
1824 | |
1825 // Compute the code stub for this store; used for rewriting to | |
1826 // monomorphic state and making sure that the code stub is in the | |
1827 // stub cache. | |
1828 Handle<Code> code; | |
1829 | |
1830 switch (type) { | |
1831 case FIELD: | 1784 case FIELD: |
1832 code = isolate()->stub_cache()->ComputeKeyedStoreField( | 1785 return isolate()->stub_cache()->ComputeKeyedStoreField( |
1833 name, receiver, lookup->GetFieldIndex().field_index(), | 1786 name, receiver, lookup->GetFieldIndex().field_index(), |
1834 Handle<Map>::null(), strict_mode); | 1787 Handle<Map>::null(), strict_mode); |
1835 break; | |
1836 case TRANSITION: { | 1788 case TRANSITION: { |
1837 Handle<Map> transition(lookup->GetTransitionTarget()); | 1789 Handle<Map> transition(lookup->GetTransitionTarget()); |
1838 int descriptor = transition->LastAdded(); | 1790 int descriptor = transition->LastAdded(); |
1839 | 1791 |
1840 DescriptorArray* target_descriptors = transition->instance_descriptors(); | 1792 DescriptorArray* target_descriptors = transition->instance_descriptors(); |
1841 PropertyDetails details = target_descriptors->GetDetails(descriptor); | 1793 PropertyDetails details = target_descriptors->GetDetails(descriptor); |
1842 | 1794 |
1843 if (details.type() == FIELD && details.attributes() == NONE) { | 1795 if (details.type() == FIELD && details.attributes() == NONE) { |
1844 int field_index = target_descriptors->GetFieldIndex(descriptor); | 1796 int field_index = target_descriptors->GetFieldIndex(descriptor); |
1845 code = isolate()->stub_cache()->ComputeKeyedStoreField( | 1797 return isolate()->stub_cache()->ComputeKeyedStoreField( |
1846 name, receiver, field_index, transition, strict_mode); | 1798 name, receiver, field_index, transition, strict_mode); |
1847 break; | |
1848 } | 1799 } |
1849 // fall through. | 1800 // fall through. |
1850 } | 1801 } |
1851 case NORMAL: | 1802 case NORMAL: |
1852 case CONSTANT_FUNCTION: | 1803 case CONSTANT_FUNCTION: |
1853 case CALLBACKS: | 1804 case CALLBACKS: |
1854 case INTERCEPTOR: | 1805 case INTERCEPTOR: |
1855 // Always rewrite to the generic case so that we do not | 1806 // Always rewrite to the generic case so that we do not |
1856 // repeatedly try to rewrite. | 1807 // repeatedly try to rewrite. |
1857 code = (strict_mode == kStrictMode) | 1808 return (strict_mode == kStrictMode) |
1858 ? generic_stub_strict() | 1809 ? generic_stub_strict() |
1859 : generic_stub(); | 1810 : generic_stub(); |
1860 break; | |
1861 case HANDLER: | 1811 case HANDLER: |
1862 case NONEXISTENT: | 1812 case NONEXISTENT: |
1863 UNREACHABLE(); | 1813 UNREACHABLE(); |
1864 return; | |
1865 } | |
1866 | |
1867 ASSERT(!code.is_null()); | |
1868 | |
1869 // Patch the call site depending on the state of the cache. | |
1870 switch (state) { | |
1871 case UNINITIALIZED: | |
1872 case PREMONOMORPHIC: | |
1873 case POLYMORPHIC: | |
1874 set_target(*code); | |
1875 break; | |
1876 case MONOMORPHIC: | |
1877 // Only move to megamorphic if the target changes. | |
1878 if (target() != *code) { | |
1879 set_target((strict_mode == kStrictMode) | |
1880 ? *megamorphic_stub_strict() | |
1881 : *megamorphic_stub()); | |
1882 } | |
1883 break; | |
1884 case MEGAMORPHIC: | |
1885 case GENERIC: | |
1886 case DEBUG_STUB: | |
1887 break; | |
1888 case MONOMORPHIC_PROTOTYPE_FAILURE: | |
1889 UNREACHABLE(); | |
1890 break; | 1814 break; |
1891 } | 1815 } |
1892 | 1816 return Handle<Code>::null(); |
1893 TRACE_IC("KeyedStoreIC", name, state, target()); | |
1894 } | 1817 } |
1895 | 1818 |
1896 | 1819 |
1897 #undef TRACE_IC | 1820 #undef TRACE_IC |
1898 | 1821 |
1899 | 1822 |
1900 // ---------------------------------------------------------------------------- | 1823 // ---------------------------------------------------------------------------- |
1901 // Static IC stub generators. | 1824 // Static IC stub generators. |
1902 // | 1825 // |
1903 | 1826 |
(...skipping 731 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2635 #undef ADDR | 2558 #undef ADDR |
2636 }; | 2559 }; |
2637 | 2560 |
2638 | 2561 |
2639 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2562 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
2640 return IC_utilities[id]; | 2563 return IC_utilities[id]; |
2641 } | 2564 } |
2642 | 2565 |
2643 | 2566 |
2644 } } // namespace v8::internal | 2567 } } // namespace v8::internal |
OLD | NEW |