OLD | NEW |
1 // Copyright 2011 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 |
(...skipping 1225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1236 } else if (object->IsJSObject()) { | 1236 } else if (object->IsJSObject()) { |
1237 JSObject* receiver = JSObject::cast(*object); | 1237 JSObject* receiver = JSObject::cast(*object); |
1238 Heap* heap = Handle<JSObject>::cast(object)->GetHeap(); | 1238 Heap* heap = Handle<JSObject>::cast(object)->GetHeap(); |
1239 Map* elements_map = Handle<JSObject>::cast(object)->elements()->map(); | 1239 Map* elements_map = Handle<JSObject>::cast(object)->elements()->map(); |
1240 if (elements_map == heap->non_strict_arguments_elements_map()) { | 1240 if (elements_map == heap->non_strict_arguments_elements_map()) { |
1241 stub = non_strict_arguments_stub(); | 1241 stub = non_strict_arguments_stub(); |
1242 } else if (receiver->HasIndexedInterceptor()) { | 1242 } else if (receiver->HasIndexedInterceptor()) { |
1243 stub = indexed_interceptor_stub(); | 1243 stub = indexed_interceptor_stub(); |
1244 } else if (key->IsSmi() && (target() != non_strict_arguments_stub())) { | 1244 } else if (key->IsSmi() && (target() != non_strict_arguments_stub())) { |
1245 MaybeObject* maybe_stub = ComputeStub(receiver, | 1245 MaybeObject* maybe_stub = ComputeStub(receiver, |
1246 false, | 1246 LOAD, |
1247 kNonStrictMode, | 1247 kNonStrictMode, |
1248 stub); | 1248 stub); |
1249 stub = maybe_stub->IsFailure() ? | 1249 stub = maybe_stub->IsFailure() ? |
1250 NULL : Code::cast(maybe_stub->ToObjectUnchecked()); | 1250 NULL : Code::cast(maybe_stub->ToObjectUnchecked()); |
1251 } | 1251 } |
1252 } | 1252 } |
1253 } | 1253 } |
1254 if (stub != NULL) set_target(stub); | 1254 if (stub != NULL) set_target(stub); |
1255 } | 1255 } |
1256 | 1256 |
(...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1586 Object* object = info->target_object(); | 1586 Object* object = info->target_object(); |
1587 ASSERT(object->IsMap()); | 1587 ASSERT(object->IsMap()); |
1588 result->Add(Map::cast(object)); | 1588 result->Add(Map::cast(object)); |
1589 } | 1589 } |
1590 } | 1590 } |
1591 } | 1591 } |
1592 } | 1592 } |
1593 | 1593 |
1594 | 1594 |
1595 MaybeObject* KeyedIC::ComputeStub(JSObject* receiver, | 1595 MaybeObject* KeyedIC::ComputeStub(JSObject* receiver, |
1596 bool is_store, | 1596 StubKind stub_kind, |
1597 StrictModeFlag strict_mode, | 1597 StrictModeFlag strict_mode, |
1598 Code* generic_stub) { | 1598 Code* generic_stub) { |
1599 State ic_state = target()->ic_state(); | 1599 State ic_state = target()->ic_state(); |
1600 if (ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) { | 1600 if ((ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) && |
| 1601 !IsTransitionStubKind(stub_kind)) { |
1601 Code* monomorphic_stub; | 1602 Code* monomorphic_stub; |
1602 MaybeObject* maybe_stub = ComputeMonomorphicStub(receiver, | 1603 MaybeObject* maybe_stub = ComputeMonomorphicStub(receiver, |
1603 is_store, | 1604 stub_kind, |
1604 strict_mode, | 1605 strict_mode, |
1605 generic_stub); | 1606 generic_stub); |
1606 if (!maybe_stub->To(&monomorphic_stub)) return maybe_stub; | 1607 if (!maybe_stub->To(&monomorphic_stub)) return maybe_stub; |
1607 | 1608 |
1608 return monomorphic_stub; | 1609 return monomorphic_stub; |
1609 } | 1610 } |
1610 ASSERT(target() != generic_stub); | 1611 ASSERT(target() != generic_stub); |
1611 | 1612 |
1612 // Don't handle megamorphic property accesses for INTERCEPTORS or CALLBACKS | 1613 // Don't handle megamorphic property accesses for INTERCEPTORS or CALLBACKS |
1613 // via megamorphic stubs, since they don't have a map in their relocation info | 1614 // via megamorphic stubs, since they don't have a map in their relocation info |
1614 // and so the stubs can't be harvested for the object needed for a map check. | 1615 // and so the stubs can't be harvested for the object needed for a map check. |
1615 if (target()->type() != NORMAL) { | 1616 if (target()->type() != NORMAL) { |
1616 return generic_stub; | 1617 return generic_stub; |
1617 } | 1618 } |
1618 | 1619 |
1619 // Determine the list of receiver maps that this call site has seen, | 1620 // Determine the list of receiver maps that this call site has seen, |
1620 // adding the map that was just encountered. | 1621 // adding the map that was just encountered. |
1621 MapList target_receiver_maps; | 1622 MapList target_receiver_maps; |
1622 GetReceiverMapsForStub(target(), &target_receiver_maps); | 1623 if (ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) { |
1623 if (!AddOneReceiverMapIfMissing(&target_receiver_maps, receiver->map())) { | 1624 target_receiver_maps.Add(receiver->map()); |
| 1625 } else { |
| 1626 GetReceiverMapsForStub(target(), &target_receiver_maps); |
| 1627 } |
| 1628 Map* new_map = receiver->map(); |
| 1629 if (IsTransitionStubKind(stub_kind)) { |
| 1630 MaybeObject* maybe_map = ComputeTransitionedMap(receiver, stub_kind); |
| 1631 if (!maybe_map->To(&new_map)) return maybe_map; |
| 1632 } |
| 1633 if (!AddOneReceiverMapIfMissing(&target_receiver_maps, new_map)) { |
1624 // If the miss wasn't due to an unseen map, a MEGAMORPHIC stub | 1634 // If the miss wasn't due to an unseen map, a MEGAMORPHIC stub |
1625 // won't help, use the generic stub. | 1635 // won't help, use the generic stub. |
1626 return generic_stub; | 1636 return generic_stub; |
1627 } | 1637 } |
1628 | 1638 |
1629 // If the maximum number of receiver maps has been exceeded, use the generic | 1639 // If the maximum number of receiver maps has been exceeded, use the generic |
1630 // version of the IC. | 1640 // version of the IC. |
1631 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) { | 1641 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) { |
1632 return generic_stub; | 1642 return generic_stub; |
1633 } | 1643 } |
1634 | 1644 |
1635 PolymorphicCodeCache* cache = isolate()->heap()->polymorphic_code_cache(); | 1645 PolymorphicCodeCache* cache = isolate()->heap()->polymorphic_code_cache(); |
1636 Code::Flags flags = Code::ComputeFlags(this->kind(), | 1646 Code::Flags flags = Code::ComputeFlags(this->kind(), |
1637 MEGAMORPHIC, | 1647 MEGAMORPHIC, |
1638 strict_mode); | 1648 strict_mode); |
1639 Object* maybe_cached_stub = cache->Lookup(&target_receiver_maps, flags); | 1649 Object* maybe_cached_stub = cache->Lookup(&target_receiver_maps, flags); |
1640 // If there is a cached stub, use it. | 1650 // If there is a cached stub, use it. |
1641 if (!maybe_cached_stub->IsUndefined()) { | 1651 if (!maybe_cached_stub->IsUndefined()) { |
1642 ASSERT(maybe_cached_stub->IsCode()); | 1652 ASSERT(maybe_cached_stub->IsCode()); |
1643 return Code::cast(maybe_cached_stub); | 1653 return Code::cast(maybe_cached_stub); |
1644 } | 1654 } |
1645 // Collect MONOMORPHIC stubs for all target_receiver_maps. | 1655 MaybeObject* maybe_stub = NULL; |
1646 CodeList handler_ics(target_receiver_maps.length()); | 1656 if (IsTransitionStubKind(stub_kind)) { |
1647 for (int i = 0; i < target_receiver_maps.length(); ++i) { | 1657 maybe_stub = ComputePolymorphicStubWithTransition( |
1648 Map* receiver_map(target_receiver_maps.at(i)); | 1658 receiver, &target_receiver_maps, new_map, strict_mode); |
1649 MaybeObject* maybe_cached_stub = ComputeMonomorphicStubWithoutMapCheck( | 1659 } else { |
1650 receiver_map, strict_mode); | 1660 maybe_stub = ComputePolymorphicStub(&target_receiver_maps, strict_mode); |
1651 Code* cached_stub; | |
1652 if (!maybe_cached_stub->To(&cached_stub)) return maybe_cached_stub; | |
1653 handler_ics.Add(cached_stub); | |
1654 } | 1661 } |
1655 // Build the MEGAMORPHIC stub. | |
1656 Code* stub; | 1662 Code* stub; |
1657 MaybeObject* maybe_stub = ConstructMegamorphicStub(&target_receiver_maps, | |
1658 &handler_ics, | |
1659 strict_mode); | |
1660 if (!maybe_stub->To(&stub)) return maybe_stub; | 1663 if (!maybe_stub->To(&stub)) return maybe_stub; |
1661 MaybeObject* maybe_update = cache->Update(&target_receiver_maps, flags, stub); | 1664 MaybeObject* maybe_update = cache->Update(&target_receiver_maps, flags, stub); |
1662 if (maybe_update->IsFailure()) return maybe_update; | 1665 if (maybe_update->IsFailure()) return maybe_update; |
1663 return stub; | 1666 return stub; |
1664 } | 1667 } |
1665 | 1668 |
1666 | 1669 |
1667 MaybeObject* KeyedIC::ComputeMonomorphicStubWithoutMapCheck( | 1670 MaybeObject* KeyedIC::ComputeMonomorphicStubWithoutMapCheck( |
1668 Map* receiver_map, | 1671 Map* receiver_map, |
1669 StrictModeFlag strict_mode) { | 1672 StrictModeFlag strict_mode) { |
1670 if ((receiver_map->instance_type() & kNotStringTag) == 0) { | 1673 if ((receiver_map->instance_type() & kNotStringTag) == 0) { |
1671 ASSERT(string_stub() != NULL); | 1674 ASSERT(string_stub() != NULL); |
1672 return string_stub(); | 1675 return string_stub(); |
1673 } else { | 1676 } else { |
1674 ASSERT(receiver_map->has_dictionary_elements() || | 1677 ASSERT(receiver_map->has_dictionary_elements() || |
1675 receiver_map->has_fast_elements() || | 1678 receiver_map->has_fast_elements() || |
1676 receiver_map->has_fast_smi_only_elements() || | 1679 receiver_map->has_fast_smi_only_elements() || |
1677 receiver_map->has_fast_double_elements() || | 1680 receiver_map->has_fast_double_elements() || |
1678 receiver_map->has_external_array_elements()); | 1681 receiver_map->has_external_array_elements()); |
1679 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; | 1682 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; |
1680 return GetElementStubWithoutMapCheck(is_js_array, | 1683 return GetElementStubWithoutMapCheck(is_js_array, |
1681 receiver_map->elements_kind()); | 1684 receiver_map->elements_kind()); |
1682 } | 1685 } |
1683 } | 1686 } |
1684 | 1687 |
1685 | 1688 |
1686 MaybeObject* KeyedIC::ComputeMonomorphicStub(JSObject* receiver, | 1689 MaybeObject* KeyedIC::ComputeMonomorphicStub(JSObject* receiver, |
1687 bool is_store, | 1690 StubKind stub_kind, |
1688 StrictModeFlag strict_mode, | 1691 StrictModeFlag strict_mode, |
1689 Code* generic_stub) { | 1692 Code* generic_stub) { |
1690 Code* result = NULL; | 1693 Code* result = NULL; |
1691 if (receiver->HasFastElements() || | 1694 if (receiver->HasFastElements() || |
1692 receiver->HasFastSmiOnlyElements() || | 1695 receiver->HasFastSmiOnlyElements() || |
1693 receiver->HasExternalArrayElements() || | 1696 receiver->HasExternalArrayElements() || |
1694 receiver->HasFastDoubleElements() || | 1697 receiver->HasFastDoubleElements() || |
1695 receiver->HasDictionaryElements()) { | 1698 receiver->HasDictionaryElements()) { |
1696 MaybeObject* maybe_stub = | 1699 MaybeObject* maybe_stub = |
1697 isolate()->stub_cache()->ComputeKeyedLoadOrStoreElement( | 1700 isolate()->stub_cache()->ComputeKeyedLoadOrStoreElement( |
1698 receiver, is_store, strict_mode); | 1701 receiver, stub_kind, strict_mode); |
1699 if (!maybe_stub->To(&result)) return maybe_stub; | 1702 if (!maybe_stub->To(&result)) return maybe_stub; |
1700 } else { | 1703 } else { |
1701 result = generic_stub; | 1704 result = generic_stub; |
1702 } | 1705 } |
1703 return result; | 1706 return result; |
1704 } | 1707 } |
1705 | 1708 |
1706 | 1709 |
| 1710 MaybeObject* KeyedIC::ComputePolymorphicStubWithTransition( |
| 1711 JSObject* receiver, |
| 1712 MapList* receiver_maps, |
| 1713 Map* new_map, |
| 1714 StrictModeFlag strict_mode) { |
| 1715 Map* existing_transitionable_map = NULL; |
| 1716 for (int i = 0; i < receiver_maps->length(); ++i) { |
| 1717 Map* map = receiver_maps->at(i); |
| 1718 if (map != receiver->map() && map != new_map) { |
| 1719 existing_transitionable_map = map; |
| 1720 break; |
| 1721 } |
| 1722 } |
| 1723 KeyedStoreStubCompiler compiler(strict_mode); |
| 1724 return compiler.CompileStoreElementWithTransition( |
| 1725 new_map, |
| 1726 receiver->map(), |
| 1727 existing_transitionable_map); |
| 1728 } |
| 1729 |
| 1730 |
| 1731 MaybeObject* KeyedIC::ComputePolymorphicStub( |
| 1732 MapList* receiver_maps, |
| 1733 StrictModeFlag strict_mode) { |
| 1734 // Collect MONOMORPHIC stubs for all target_receiver_maps. |
| 1735 CodeList handler_ics(receiver_maps->length()); |
| 1736 for (int i = 0; i < receiver_maps->length(); ++i) { |
| 1737 Map* receiver_map(receiver_maps->at(i)); |
| 1738 MaybeObject* maybe_cached_stub = ComputeMonomorphicStubWithoutMapCheck( |
| 1739 receiver_map, strict_mode); |
| 1740 Code* cached_stub; |
| 1741 if (!maybe_cached_stub->To(&cached_stub)) return maybe_cached_stub; |
| 1742 handler_ics.Add(cached_stub); |
| 1743 } |
| 1744 // Build the MEGAMORPHIC stub. |
| 1745 return ConstructMegamorphicStub(receiver_maps, &handler_ics, strict_mode); |
| 1746 } |
| 1747 |
| 1748 |
| 1749 MaybeObject* KeyedIC::ComputeTransitionedMap(JSObject* receiver, |
| 1750 StubKind stub_kind) { |
| 1751 switch (stub_kind) { |
| 1752 case KeyedIC::STORE_TRANSITION_SMI_TO_OBJECT: |
| 1753 case KeyedIC::STORE_TRANSITION_DOUBLE_TO_OBJECT: |
| 1754 return receiver->GetElementsTransitionMap(FAST_ELEMENTS); |
| 1755 case KeyedIC::STORE_TRANSITION_SMI_TO_DOUBLE: |
| 1756 return receiver->GetElementsTransitionMap(FAST_DOUBLE_ELEMENTS); |
| 1757 default: |
| 1758 UNREACHABLE(); |
| 1759 return NULL; |
| 1760 } |
| 1761 } |
| 1762 |
| 1763 |
1707 MaybeObject* KeyedStoreIC::GetElementStubWithoutMapCheck( | 1764 MaybeObject* KeyedStoreIC::GetElementStubWithoutMapCheck( |
1708 bool is_js_array, | 1765 bool is_js_array, |
1709 ElementsKind elements_kind) { | 1766 ElementsKind elements_kind) { |
1710 return KeyedStoreElementStub(is_js_array, elements_kind).TryGetCode(); | 1767 return KeyedStoreElementStub(is_js_array, elements_kind).TryGetCode(); |
1711 } | 1768 } |
1712 | 1769 |
1713 | 1770 |
1714 MaybeObject* KeyedStoreIC::ConstructMegamorphicStub( | 1771 MaybeObject* KeyedStoreIC::ConstructMegamorphicStub( |
1715 MapList* receiver_maps, | 1772 MapList* receiver_maps, |
1716 CodeList* targets, | 1773 CodeList* targets, |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1779 ? generic_stub_strict() | 1836 ? generic_stub_strict() |
1780 : generic_stub(); | 1837 : generic_stub(); |
1781 if (object->IsJSObject()) { | 1838 if (object->IsJSObject()) { |
1782 JSObject* receiver = JSObject::cast(*object); | 1839 JSObject* receiver = JSObject::cast(*object); |
1783 Heap* heap = Handle<JSObject>::cast(object)->GetHeap(); | 1840 Heap* heap = Handle<JSObject>::cast(object)->GetHeap(); |
1784 Map* elements_map = Handle<JSObject>::cast(object)->elements()->map(); | 1841 Map* elements_map = Handle<JSObject>::cast(object)->elements()->map(); |
1785 if (elements_map == heap->non_strict_arguments_elements_map()) { | 1842 if (elements_map == heap->non_strict_arguments_elements_map()) { |
1786 stub = non_strict_arguments_stub(); | 1843 stub = non_strict_arguments_stub(); |
1787 } else if (!force_generic) { | 1844 } else if (!force_generic) { |
1788 if (key->IsSmi() && (target() != non_strict_arguments_stub())) { | 1845 if (key->IsSmi() && (target() != non_strict_arguments_stub())) { |
| 1846 StubKind stub_kind = STORE_NO_TRANSITION; |
| 1847 if (receiver->GetElementsKind() == FAST_SMI_ONLY_ELEMENTS) { |
| 1848 if (value->IsHeapNumber()) { |
| 1849 stub_kind = STORE_TRANSITION_SMI_TO_DOUBLE; |
| 1850 } else if (value->IsHeapObject()) { |
| 1851 stub_kind = STORE_TRANSITION_SMI_TO_OBJECT; |
| 1852 } |
| 1853 } else if (receiver->GetElementsKind() == FAST_DOUBLE_ELEMENTS) { |
| 1854 if (!value->IsSmi() && !value->IsHeapNumber()) { |
| 1855 stub_kind = STORE_TRANSITION_DOUBLE_TO_OBJECT; |
| 1856 } |
| 1857 } |
1789 HandleScope scope(isolate()); | 1858 HandleScope scope(isolate()); |
1790 MaybeObject* maybe_stub = ComputeStub(receiver, | 1859 MaybeObject* maybe_stub = ComputeStub(receiver, |
1791 true, | 1860 stub_kind, |
1792 strict_mode, | 1861 strict_mode, |
1793 stub); | 1862 stub); |
1794 stub = maybe_stub->IsFailure() ? | 1863 stub = maybe_stub->IsFailure() ? |
1795 NULL : Code::cast(maybe_stub->ToObjectUnchecked()); | 1864 NULL : Code::cast(maybe_stub->ToObjectUnchecked()); |
1796 } | 1865 } |
1797 } | 1866 } |
1798 } | 1867 } |
1799 if (stub != NULL) set_target(stub); | 1868 if (stub != NULL) set_target(stub); |
1800 } | 1869 } |
1801 | 1870 |
(...skipping 706 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2508 #undef ADDR | 2577 #undef ADDR |
2509 }; | 2578 }; |
2510 | 2579 |
2511 | 2580 |
2512 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2581 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
2513 return IC_utilities[id]; | 2582 return IC_utilities[id]; |
2514 } | 2583 } |
2515 | 2584 |
2516 | 2585 |
2517 } } // namespace v8::internal | 2586 } } // namespace v8::internal |
OLD | NEW |