Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/ic/accessor-assembler.h" | 5 #include "src/ic/accessor-assembler.h" |
| 6 | 6 |
| 7 #include "src/code-factory.h" | 7 #include "src/code-factory.h" |
| 8 #include "src/code-stubs.h" | 8 #include "src/code-stubs.h" |
| 9 #include "src/counters.h" | 9 #include "src/counters.h" |
| 10 #include "src/ic/handler-configuration.h" | 10 #include "src/ic/handler-configuration.h" |
| 11 #include "src/ic/ic.h" | |
| 11 #include "src/ic/stub-cache.h" | 12 #include "src/ic/stub-cache.h" |
| 12 #include "src/objects-inl.h" | 13 #include "src/objects-inl.h" |
| 13 | 14 |
| 14 namespace v8 { | 15 namespace v8 { |
| 15 namespace internal { | 16 namespace internal { |
| 16 | 17 |
| 17 using compiler::CodeAssemblerState; | 18 using compiler::CodeAssemblerState; |
| 18 using compiler::Node; | 19 using compiler::Node; |
| 19 | 20 |
| 20 //////////////////// Private helpers. | 21 //////////////////// Private helpers. |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 61 Comment("HandlePolymorphicCase"); | 62 Comment("HandlePolymorphicCase"); |
| 62 DCHECK_EQ(MachineRepresentation::kTagged, var_handler->rep()); | 63 DCHECK_EQ(MachineRepresentation::kTagged, var_handler->rep()); |
| 63 | 64 |
| 64 // Deferred so the unrolled case can omit frame construction in bytecode | 65 // Deferred so the unrolled case can omit frame construction in bytecode |
| 65 // handler. | 66 // handler. |
| 66 Label loop(this, Label::kDeferred); | 67 Label loop(this, Label::kDeferred); |
| 67 | 68 |
| 68 // Iterate {feedback} array. | 69 // Iterate {feedback} array. |
| 69 const int kEntrySize = 2; | 70 const int kEntrySize = 2; |
| 70 | 71 |
| 72 // Polymorphic IC feedback is guaranteed contain at least two (map, handler) | |
| 73 // pairs. | |
| 74 const int kMaxUnrollCountWithoutBoundsCheck = 2; | |
| 75 DCHECK_LE(unroll_count, IC::kMaxPolymorphicMapCount); | |
| 76 | |
| 77 Node* length = LoadAndUntagFixedArrayBaseLength(feedback); | |
|
Igor Sheludko
2017/03/07 13:24:01
We can delay loading of a length till (i == kMaxUn
| |
| 78 CSA_ASSERT(this, IntPtrGreaterThanOrEqual(length, IntPtrConstant(2))); | |
| 79 | |
| 71 for (int i = 0; i < unroll_count; i++) { | 80 for (int i = 0; i < unroll_count; i++) { |
| 81 int map_index = i * kEntrySize; | |
| 82 int handler_index = i * kEntrySize + 1; | |
| 83 | |
| 84 if (i >= kMaxUnrollCountWithoutBoundsCheck) { | |
| 85 GotoIf(IntPtrGreaterThanOrEqual(IntPtrConstant(handler_index), length), | |
| 86 if_miss); | |
| 87 } | |
| 88 | |
| 72 Label next_entry(this); | 89 Label next_entry(this); |
| 73 Node* cached_map = | 90 Node* cached_map = |
| 74 LoadWeakCellValue(LoadFixedArrayElement(feedback, i * kEntrySize)); | 91 LoadWeakCellValue(LoadFixedArrayElement(feedback, map_index)); |
| 75 GotoIf(WordNotEqual(receiver_map, cached_map), &next_entry); | 92 GotoIf(WordNotEqual(receiver_map, cached_map), &next_entry); |
| 76 | 93 |
| 77 // Found, now call handler. | 94 // Found, now call handler. |
| 78 Node* handler = LoadFixedArrayElement(feedback, i * kEntrySize + 1); | 95 Node* handler = LoadFixedArrayElement(feedback, handler_index); |
| 79 var_handler->Bind(handler); | 96 var_handler->Bind(handler); |
| 80 Goto(if_handler); | 97 Goto(if_handler); |
| 81 | 98 |
| 82 Bind(&next_entry); | 99 Bind(&next_entry); |
| 83 } | 100 } |
| 84 Goto(&loop); | 101 Goto(&loop); |
| 85 | 102 |
| 86 // Loop from {unroll_count}*kEntrySize to {length}. | 103 // Loop from {unroll_count}*kEntrySize to {length}. |
| 87 Bind(&loop); | 104 Bind(&loop); |
| 88 Node* init = IntPtrConstant(unroll_count * kEntrySize); | 105 Node* init = IntPtrConstant(unroll_count * kEntrySize); |
| 89 Node* length = LoadAndUntagFixedArrayBaseLength(feedback); | |
| 90 BuildFastLoop( | 106 BuildFastLoop( |
| 91 init, length, | 107 init, length, |
| 92 [this, receiver_map, feedback, if_handler, var_handler](Node* index) { | 108 [this, receiver_map, feedback, if_handler, var_handler](Node* index) { |
| 93 Node* cached_map = | 109 Node* cached_map = |
| 94 LoadWeakCellValue(LoadFixedArrayElement(feedback, index)); | 110 LoadWeakCellValue(LoadFixedArrayElement(feedback, index)); |
| 95 | 111 |
| 96 Label next_entry(this); | 112 Label next_entry(this); |
| 97 GotoIf(WordNotEqual(receiver_map, cached_map), &next_entry); | 113 GotoIf(WordNotEqual(receiver_map, cached_map), &next_entry); |
| 98 | 114 |
| 99 // Found, now call handler. | 115 // Found, now call handler. |
| (...skipping 1521 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1621 &var_handler, &try_polymorphic); | 1637 &var_handler, &try_polymorphic); |
| 1622 | 1638 |
| 1623 Bind(&if_handler); | 1639 Bind(&if_handler); |
| 1624 HandleLoadICHandlerCase(p, var_handler.value(), &miss, exit_point); | 1640 HandleLoadICHandlerCase(p, var_handler.value(), &miss, exit_point); |
| 1625 | 1641 |
| 1626 Bind(&try_polymorphic); | 1642 Bind(&try_polymorphic); |
| 1627 { | 1643 { |
| 1628 GotoIfNot(WordEqual(LoadMap(feedback), FixedArrayMapConstant()), | 1644 GotoIfNot(WordEqual(LoadMap(feedback), FixedArrayMapConstant()), |
| 1629 &stub_call); | 1645 &stub_call); |
| 1630 HandlePolymorphicCase(recv_map, feedback, &if_handler, &var_handler, | 1646 HandlePolymorphicCase(recv_map, feedback, &if_handler, &var_handler, |
| 1631 &miss, 2); | 1647 &miss, IC::kMaxPolymorphicMapCount); |
| 1632 } | 1648 } |
| 1633 } | 1649 } |
| 1634 | 1650 |
| 1635 Bind(&stub_call); | 1651 Bind(&stub_call); |
| 1636 { | 1652 { |
| 1637 Comment("LoadIC_BytecodeHandler_noninlined"); | 1653 Comment("LoadIC_BytecodeHandler_noninlined"); |
| 1638 | 1654 |
| 1639 // Call into the stub that implements the non-inlined parts of LoadIC. | 1655 // Call into the stub that implements the non-inlined parts of LoadIC. |
| 1640 Callable ic = CodeFactory::LoadICInOptimizedCode_Noninlined(isolate()); | 1656 Callable ic = CodeFactory::LoadICInOptimizedCode_Noninlined(isolate()); |
| 1641 Node* code_target = HeapConstant(ic.code()); | 1657 Node* code_target = HeapConstant(ic.code()); |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 1671 Bind(&if_handler); | 1687 Bind(&if_handler); |
| 1672 HandleLoadICHandlerCase(p, var_handler.value(), &miss, &direct_exit); | 1688 HandleLoadICHandlerCase(p, var_handler.value(), &miss, &direct_exit); |
| 1673 | 1689 |
| 1674 Bind(&try_polymorphic); | 1690 Bind(&try_polymorphic); |
| 1675 { | 1691 { |
| 1676 // Check polymorphic case. | 1692 // Check polymorphic case. |
| 1677 Comment("LoadIC_try_polymorphic"); | 1693 Comment("LoadIC_try_polymorphic"); |
| 1678 GotoIfNot(WordEqual(LoadMap(feedback), FixedArrayMapConstant()), | 1694 GotoIfNot(WordEqual(LoadMap(feedback), FixedArrayMapConstant()), |
| 1679 &non_inlined); | 1695 &non_inlined); |
| 1680 HandlePolymorphicCase(receiver_map, feedback, &if_handler, &var_handler, | 1696 HandlePolymorphicCase(receiver_map, feedback, &if_handler, &var_handler, |
| 1681 &miss, 2); | 1697 &miss, IC::kMaxPolymorphicMapCount); |
| 1682 } | 1698 } |
| 1683 | 1699 |
| 1684 Bind(&non_inlined); | 1700 Bind(&non_inlined); |
| 1685 LoadIC_Noninlined(p, receiver_map, feedback, &var_handler, &if_handler, &miss, | 1701 LoadIC_Noninlined(p, receiver_map, feedback, &var_handler, &if_handler, &miss, |
| 1686 &direct_exit); | 1702 &direct_exit); |
| 1687 | 1703 |
| 1688 Bind(&miss); | 1704 Bind(&miss); |
| 1689 direct_exit.ReturnCallRuntime(Runtime::kLoadIC_Miss, p->context, p->receiver, | 1705 direct_exit.ReturnCallRuntime(Runtime::kLoadIC_Miss, p->context, p->receiver, |
| 1690 p->name, p->slot, p->vector); | 1706 p->name, p->slot, p->vector); |
| 1691 } | 1707 } |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1903 kSupportElements); | 1919 kSupportElements); |
| 1904 } | 1920 } |
| 1905 | 1921 |
| 1906 Bind(&try_polymorphic); | 1922 Bind(&try_polymorphic); |
| 1907 { | 1923 { |
| 1908 // Check polymorphic case. | 1924 // Check polymorphic case. |
| 1909 Comment("KeyedLoadIC_try_polymorphic"); | 1925 Comment("KeyedLoadIC_try_polymorphic"); |
| 1910 GotoIfNot(WordEqual(LoadMap(feedback), FixedArrayMapConstant()), | 1926 GotoIfNot(WordEqual(LoadMap(feedback), FixedArrayMapConstant()), |
| 1911 &try_megamorphic); | 1927 &try_megamorphic); |
| 1912 HandlePolymorphicCase(receiver_map, feedback, &if_handler, &var_handler, | 1928 HandlePolymorphicCase(receiver_map, feedback, &if_handler, &var_handler, |
| 1913 &miss, 2); | 1929 &miss, IC::kMaxPolymorphicMapCount); |
| 1914 } | 1930 } |
| 1915 | 1931 |
| 1916 Bind(&try_megamorphic); | 1932 Bind(&try_megamorphic); |
| 1917 { | 1933 { |
| 1918 // Check megamorphic case. | 1934 // Check megamorphic case. |
| 1919 Comment("KeyedLoadIC_try_megamorphic"); | 1935 Comment("KeyedLoadIC_try_megamorphic"); |
| 1920 GotoIfNot(WordEqual(feedback, LoadRoot(Heap::kmegamorphic_symbolRootIndex)), | 1936 GotoIfNot(WordEqual(feedback, LoadRoot(Heap::kmegamorphic_symbolRootIndex)), |
| 1921 &try_polymorphic_name); | 1937 &try_polymorphic_name); |
| 1922 // TODO(jkummerow): Inline this? Or some of it? | 1938 // TODO(jkummerow): Inline this? Or some of it? |
| 1923 TailCallStub(CodeFactory::KeyedLoadIC_Megamorphic(isolate()), p->context, | 1939 TailCallStub(CodeFactory::KeyedLoadIC_Megamorphic(isolate()), p->context, |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1998 } | 2014 } |
| 1999 | 2015 |
| 2000 Bind(&try_polymorphic); | 2016 Bind(&try_polymorphic); |
| 2001 { | 2017 { |
| 2002 // Check polymorphic case. | 2018 // Check polymorphic case. |
| 2003 Comment("StoreIC_try_polymorphic"); | 2019 Comment("StoreIC_try_polymorphic"); |
| 2004 GotoIfNot( | 2020 GotoIfNot( |
| 2005 WordEqual(LoadMap(feedback), LoadRoot(Heap::kFixedArrayMapRootIndex)), | 2021 WordEqual(LoadMap(feedback), LoadRoot(Heap::kFixedArrayMapRootIndex)), |
| 2006 &try_megamorphic); | 2022 &try_megamorphic); |
| 2007 HandlePolymorphicCase(receiver_map, feedback, &if_handler, &var_handler, | 2023 HandlePolymorphicCase(receiver_map, feedback, &if_handler, &var_handler, |
| 2008 &miss, 2); | 2024 &miss, IC::kMaxPolymorphicMapCount); |
| 2009 } | 2025 } |
| 2010 | 2026 |
| 2011 Bind(&try_megamorphic); | 2027 Bind(&try_megamorphic); |
| 2012 { | 2028 { |
| 2013 // Check megamorphic case. | 2029 // Check megamorphic case. |
| 2014 GotoIfNot(WordEqual(feedback, LoadRoot(Heap::kmegamorphic_symbolRootIndex)), | 2030 GotoIfNot(WordEqual(feedback, LoadRoot(Heap::kmegamorphic_symbolRootIndex)), |
| 2015 &miss); | 2031 &miss); |
| 2016 | 2032 |
| 2017 TryProbeStubCache(isolate()->store_stub_cache(), p->receiver, p->name, | 2033 TryProbeStubCache(isolate()->store_stub_cache(), p->receiver, p->name, |
| 2018 &if_handler, &var_handler, &miss); | 2034 &if_handler, &var_handler, &miss); |
| (...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2358 Node* context = Parameter(Descriptor::kContext); | 2374 Node* context = Parameter(Descriptor::kContext); |
| 2359 Node* vector = LoadFeedbackVectorForStub(); | 2375 Node* vector = LoadFeedbackVectorForStub(); |
| 2360 | 2376 |
| 2361 Callable callable = | 2377 Callable callable = |
| 2362 CodeFactory::KeyedStoreICInOptimizedCode(isolate(), language_mode); | 2378 CodeFactory::KeyedStoreICInOptimizedCode(isolate(), language_mode); |
| 2363 TailCallStub(callable, context, receiver, name, value, slot, vector); | 2379 TailCallStub(callable, context, receiver, name, value, slot, vector); |
| 2364 } | 2380 } |
| 2365 | 2381 |
| 2366 } // namespace internal | 2382 } // namespace internal |
| 2367 } // namespace v8 | 2383 } // namespace v8 |
| OLD | NEW |