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 |