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

Side by Side Diff: src/ic.cc

Issue 8233011: Refactor and fix polymorphic KeyedStoreIC creation (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: fix nits Created 9 years, 2 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/mips/stub-cache-mips.cc » ('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 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 1066 matching lines...) Expand 10 before | Expand all | Expand 10 after
1077 } 1077 }
1078 1078
1079 1079
1080 MaybeObject* KeyedLoadIC::GetElementStubWithoutMapCheck( 1080 MaybeObject* KeyedLoadIC::GetElementStubWithoutMapCheck(
1081 bool is_js_array, 1081 bool is_js_array,
1082 ElementsKind elements_kind) { 1082 ElementsKind elements_kind) {
1083 return KeyedLoadElementStub(elements_kind).TryGetCode(); 1083 return KeyedLoadElementStub(elements_kind).TryGetCode();
1084 } 1084 }
1085 1085
1086 1086
1087 MaybeObject* KeyedLoadIC::ConstructMegamorphicStub( 1087 MaybeObject* KeyedLoadIC::ComputePolymorphicStub(
1088 MapList* receiver_maps, 1088 MapList* receiver_maps,
1089 CodeList* targets,
1090 StrictModeFlag strict_mode) { 1089 StrictModeFlag strict_mode) {
1090 CodeList handler_ics(receiver_maps->length());
1091 for (int i = 0; i < receiver_maps->length(); ++i) {
1092 Map* receiver_map(receiver_maps->at(i));
1093 MaybeObject* maybe_cached_stub = ComputeMonomorphicStubWithoutMapCheck(
1094 receiver_map, strict_mode);
1095 Code* cached_stub;
1096 if (!maybe_cached_stub->To(&cached_stub)) return maybe_cached_stub;
1097 handler_ics.Add(cached_stub);
1098 }
1091 Object* object; 1099 Object* object;
1092 KeyedLoadStubCompiler compiler; 1100 KeyedLoadStubCompiler compiler;
1093 MaybeObject* maybe_code = compiler.CompileLoadMegamorphic(receiver_maps, 1101 MaybeObject* maybe_code = compiler.CompileLoadPolymorphic(receiver_maps,
1094 targets); 1102 &handler_ics);
1095 if (!maybe_code->ToObject(&object)) return maybe_code; 1103 if (!maybe_code->ToObject(&object)) return maybe_code;
1096 isolate()->counters()->keyed_load_polymorphic_stubs()->Increment(); 1104 isolate()->counters()->keyed_load_polymorphic_stubs()->Increment();
1097 PROFILE(isolate(), CodeCreateEvent( 1105 PROFILE(isolate(), CodeCreateEvent(
1098 Logger::KEYED_LOAD_MEGAMORPHIC_IC_TAG, 1106 Logger::KEYED_LOAD_MEGAMORPHIC_IC_TAG,
1099 Code::cast(object), 0)); 1107 Code::cast(object), 0));
1100 return object; 1108 return object;
1101 } 1109 }
1102 1110
1103 1111
1104 MaybeObject* KeyedLoadIC::Load(State state, 1112 MaybeObject* KeyedLoadIC::Load(State state,
(...skipping 513 matching lines...) Expand 10 before | Expand all | Expand 10 after
1618 } 1626 }
1619 1627
1620 // Determine the list of receiver maps that this call site has seen, 1628 // Determine the list of receiver maps that this call site has seen,
1621 // adding the map that was just encountered. 1629 // adding the map that was just encountered.
1622 MapList target_receiver_maps; 1630 MapList target_receiver_maps;
1623 if (ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) { 1631 if (ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) {
1624 target_receiver_maps.Add(receiver->map()); 1632 target_receiver_maps.Add(receiver->map());
1625 } else { 1633 } else {
1626 GetReceiverMapsForStub(target(), &target_receiver_maps); 1634 GetReceiverMapsForStub(target(), &target_receiver_maps);
1627 } 1635 }
1628 Map* new_map = receiver->map(); 1636 bool map_added =
1637 AddOneReceiverMapIfMissing(&target_receiver_maps, receiver->map());
1629 if (IsTransitionStubKind(stub_kind)) { 1638 if (IsTransitionStubKind(stub_kind)) {
1630 MaybeObject* maybe_map = ComputeTransitionedMap(receiver, stub_kind); 1639 MaybeObject* maybe_map = ComputeTransitionedMap(receiver, stub_kind);
1640 Map* new_map = NULL;
1631 if (!maybe_map->To(&new_map)) return maybe_map; 1641 if (!maybe_map->To(&new_map)) return maybe_map;
1642 map_added |= AddOneReceiverMapIfMissing(&target_receiver_maps, new_map);
1632 } 1643 }
1633 if (!AddOneReceiverMapIfMissing(&target_receiver_maps, new_map)) { 1644 if (!map_added) {
1634 // If the miss wasn't due to an unseen map, a MEGAMORPHIC stub 1645 // If the miss wasn't due to an unseen map, a polymorphic stub
1635 // won't help, use the generic stub. 1646 // won't help, use the generic stub.
1636 return generic_stub; 1647 return generic_stub;
1637 } 1648 }
1638 1649
1639 // If the maximum number of receiver maps has been exceeded, use the generic 1650 // If the maximum number of receiver maps has been exceeded, use the generic
1640 // version of the IC. 1651 // version of the IC.
1641 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) { 1652 if (target_receiver_maps.length() > kMaxKeyedPolymorphism) {
1642 return generic_stub; 1653 return generic_stub;
1643 } 1654 }
1644 1655
1645 PolymorphicCodeCache* cache = isolate()->heap()->polymorphic_code_cache(); 1656 PolymorphicCodeCache* cache = isolate()->heap()->polymorphic_code_cache();
1646 Code::Flags flags = Code::ComputeFlags(this->kind(), 1657 Code::Flags flags = Code::ComputeFlags(this->kind(),
1647 MEGAMORPHIC, 1658 MEGAMORPHIC,
1648 strict_mode); 1659 strict_mode);
1649 Object* maybe_cached_stub = cache->Lookup(&target_receiver_maps, flags); 1660 Object* maybe_cached_stub = cache->Lookup(&target_receiver_maps, flags);
1650 // If there is a cached stub, use it. 1661 // If there is a cached stub, use it.
1651 if (!maybe_cached_stub->IsUndefined()) { 1662 if (!maybe_cached_stub->IsUndefined()) {
1652 ASSERT(maybe_cached_stub->IsCode()); 1663 ASSERT(maybe_cached_stub->IsCode());
1653 return Code::cast(maybe_cached_stub); 1664 return Code::cast(maybe_cached_stub);
1654 } 1665 }
1655 MaybeObject* maybe_stub = NULL; 1666 MaybeObject* maybe_stub =
1656 if (IsTransitionStubKind(stub_kind)) { 1667 ComputePolymorphicStub(&target_receiver_maps, strict_mode);
1657 maybe_stub = ComputePolymorphicStubWithTransition(
1658 receiver, &target_receiver_maps, new_map, strict_mode);
1659 } else {
1660 maybe_stub = ComputePolymorphicStub(&target_receiver_maps, strict_mode);
1661 }
1662 Code* stub; 1668 Code* stub;
1663 if (!maybe_stub->To(&stub)) return maybe_stub; 1669 if (!maybe_stub->To(&stub)) return maybe_stub;
1664 MaybeObject* maybe_update = cache->Update(&target_receiver_maps, flags, stub); 1670 MaybeObject* maybe_update = cache->Update(&target_receiver_maps, flags, stub);
1665 if (maybe_update->IsFailure()) return maybe_update; 1671 if (maybe_update->IsFailure()) return maybe_update;
1666 return stub; 1672 return stub;
1667 } 1673 }
1668 1674
1669 1675
1670 MaybeObject* KeyedIC::ComputeMonomorphicStubWithoutMapCheck( 1676 MaybeObject* KeyedIC::ComputeMonomorphicStubWithoutMapCheck(
1671 Map* receiver_map, 1677 Map* receiver_map,
(...skipping 28 matching lines...) Expand all
1700 isolate()->stub_cache()->ComputeKeyedLoadOrStoreElement( 1706 isolate()->stub_cache()->ComputeKeyedLoadOrStoreElement(
1701 receiver, stub_kind, strict_mode); 1707 receiver, stub_kind, strict_mode);
1702 if (!maybe_stub->To(&result)) return maybe_stub; 1708 if (!maybe_stub->To(&result)) return maybe_stub;
1703 } else { 1709 } else {
1704 result = generic_stub; 1710 result = generic_stub;
1705 } 1711 }
1706 return result; 1712 return result;
1707 } 1713 }
1708 1714
1709 1715
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, 1716 MaybeObject* KeyedIC::ComputeTransitionedMap(JSObject* receiver,
1750 StubKind stub_kind) { 1717 StubKind stub_kind) {
1751 switch (stub_kind) { 1718 switch (stub_kind) {
1752 case KeyedIC::STORE_TRANSITION_SMI_TO_OBJECT: 1719 case KeyedIC::STORE_TRANSITION_SMI_TO_OBJECT:
1753 case KeyedIC::STORE_TRANSITION_DOUBLE_TO_OBJECT: 1720 case KeyedIC::STORE_TRANSITION_DOUBLE_TO_OBJECT:
1754 return receiver->GetElementsTransitionMap(FAST_ELEMENTS); 1721 return receiver->GetElementsTransitionMap(FAST_ELEMENTS);
1755 case KeyedIC::STORE_TRANSITION_SMI_TO_DOUBLE: 1722 case KeyedIC::STORE_TRANSITION_SMI_TO_DOUBLE:
1756 return receiver->GetElementsTransitionMap(FAST_DOUBLE_ELEMENTS); 1723 return receiver->GetElementsTransitionMap(FAST_DOUBLE_ELEMENTS);
1757 default: 1724 default:
1758 UNREACHABLE(); 1725 UNREACHABLE();
1759 return NULL; 1726 return NULL;
1760 } 1727 }
1761 } 1728 }
1762 1729
1763 1730
1764 MaybeObject* KeyedStoreIC::GetElementStubWithoutMapCheck( 1731 MaybeObject* KeyedStoreIC::GetElementStubWithoutMapCheck(
1765 bool is_js_array, 1732 bool is_js_array,
1766 ElementsKind elements_kind) { 1733 ElementsKind elements_kind) {
1767 return KeyedStoreElementStub(is_js_array, elements_kind).TryGetCode(); 1734 return KeyedStoreElementStub(is_js_array, elements_kind).TryGetCode();
1768 } 1735 }
1769 1736
1770 1737
1771 MaybeObject* KeyedStoreIC::ConstructMegamorphicStub( 1738 // If |map| is contained in |maps_list|, returns |map|; otherwise returns NULL.
1739 Map* GetMapIfPresent(Map* map, MapList* maps_list) {
1740 for (int i = 0; i < maps_list->length(); ++i) {
1741 if (maps_list->at(i) == map) return map;
1742 }
1743 return NULL;
1744 }
1745
1746
1747 // Returns the most generic transitioned map for |map| that's found in
1748 // |maps_list|, or NULL if no transitioned map for |map| is found at all.
1749 Map* GetTransitionedMap(Map* map, MapList* maps_list) {
1750 ElementsKind elements_kind = map->elements_kind();
1751 if (elements_kind == FAST_ELEMENTS) {
1752 return NULL;
1753 }
1754 if (elements_kind == FAST_DOUBLE_ELEMENTS) {
1755 bool dummy = true;
1756 Map* fast_map = map->LookupElementsTransitionMap(FAST_ELEMENTS, &dummy);
1757 if (fast_map == NULL) return NULL;
1758 return GetMapIfPresent(fast_map, maps_list);
1759 }
1760 if (elements_kind == FAST_SMI_ONLY_ELEMENTS) {
1761 bool dummy = true;
1762 Map* double_map = map->LookupElementsTransitionMap(FAST_DOUBLE_ELEMENTS,
1763 &dummy);
1764 // In the current implementation, if the DOUBLE map doesn't exist, the
1765 // FAST map can't exist either.
1766 if (double_map == NULL) return NULL;
1767 Map* fast_map = map->LookupElementsTransitionMap(FAST_ELEMENTS, &dummy);
1768 if (fast_map == NULL) {
1769 return GetMapIfPresent(double_map, maps_list);
1770 }
1771 // Both double_map and fast_map are non-NULL. Return fast_map if it's in
1772 // maps_list, double_map otherwise.
1773 Map* fast_map_present = GetMapIfPresent(fast_map, maps_list);
1774 if (fast_map_present != NULL) return fast_map_present;
1775 return GetMapIfPresent(double_map, maps_list);
1776 }
1777 return NULL;
1778 }
1779
1780
1781 MaybeObject* KeyedStoreIC::ComputePolymorphicStub(
1772 MapList* receiver_maps, 1782 MapList* receiver_maps,
1773 CodeList* targets,
1774 StrictModeFlag strict_mode) { 1783 StrictModeFlag strict_mode) {
1784 // TODO(yangguo): <remove>
1785 Code* generic_stub = (strict_mode == kStrictMode)
1786 ? isolate()->builtins()->builtin(Builtins::kKeyedStoreIC_Generic_Strict)
1787 : isolate()->builtins()->builtin(Builtins::kKeyedStoreIC_Generic);
1788 // </remove>
1789
1790 // Collect MONOMORPHIC stubs for all target_receiver_maps.
1791 CodeList handler_ics(receiver_maps->length());
1792 MapList transitioned_maps(receiver_maps->length());
1793 for (int i = 0; i < receiver_maps->length(); ++i) {
1794 Map* receiver_map(receiver_maps->at(i));
1795 MaybeObject* maybe_cached_stub = NULL;
1796 Map* transitioned_map = GetTransitionedMap(receiver_map, receiver_maps);
1797 if (transitioned_map != NULL) {
1798 // TODO(yangguo): Enable this code!
1799 // maybe_cached_stub = FastElementsConversionStub(
1800 // receiver_map->elements_kind(), // original elements_kind
1801 // transitioned_map->elements_kind(),
1802 // receiver_map->instance_type() == JS_ARRAY_TYPE, // is_js_array
1803 // strict_mode_).TryGetCode();
1804 // TODO(yangguo): <remove>
1805 maybe_cached_stub = generic_stub;
1806 // </remove>
1807 } else {
1808 maybe_cached_stub = ComputeMonomorphicStubWithoutMapCheck(
1809 receiver_map, strict_mode);
1810 }
1811 Code* cached_stub;
1812 if (!maybe_cached_stub->To(&cached_stub)) return maybe_cached_stub;
1813 handler_ics.Add(cached_stub);
1814 transitioned_maps.Add(transitioned_map);
1815 }
1775 Object* object; 1816 Object* object;
1776 KeyedStoreStubCompiler compiler(strict_mode); 1817 KeyedStoreStubCompiler compiler(strict_mode);
1777 MaybeObject* maybe_code = compiler.CompileStoreMegamorphic(receiver_maps, 1818 MaybeObject* maybe_code = compiler.CompileStorePolymorphic(
1778 targets); 1819 receiver_maps, &handler_ics, &transitioned_maps);
1779 if (!maybe_code->ToObject(&object)) return maybe_code; 1820 if (!maybe_code->ToObject(&object)) return maybe_code;
1780 isolate()->counters()->keyed_store_polymorphic_stubs()->Increment(); 1821 isolate()->counters()->keyed_store_polymorphic_stubs()->Increment();
1781 PROFILE(isolate(), CodeCreateEvent( 1822 PROFILE(isolate(), CodeCreateEvent(
1782 Logger::KEYED_STORE_MEGAMORPHIC_IC_TAG, 1823 Logger::KEYED_STORE_MEGAMORPHIC_IC_TAG,
1783 Code::cast(object), 0)); 1824 Code::cast(object), 0));
1784 return object; 1825 return object;
1785 } 1826 }
1786 1827
1787 1828
1788 MaybeObject* KeyedStoreIC::Store(State state, 1829 MaybeObject* KeyedStoreIC::Store(State state,
(...skipping 788 matching lines...) Expand 10 before | Expand all | Expand 10 after
2577 #undef ADDR 2618 #undef ADDR
2578 }; 2619 };
2579 2620
2580 2621
2581 Address IC::AddressFromUtilityId(IC::UtilityId id) { 2622 Address IC::AddressFromUtilityId(IC::UtilityId id) {
2582 return IC_utilities[id]; 2623 return IC_utilities[id];
2583 } 2624 }
2584 2625
2585 2626
2586 } } // namespace v8::internal 2627 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ic.h ('k') | src/mips/stub-cache-mips.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698