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

Side by Side Diff: runtime/vm/regexp_assembler_ir.cc

Issue 2951053003: VM(RegExp): Allow OSR optimization of RegExp :matcher functions. (Closed)
Patch Set: Fix bugs with stack growing and block pruning Created 3 years, 6 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
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/regexp_assembler_ir.h" 5 #include "vm/regexp_assembler_ir.h"
6 6
7 #include "vm/bit_vector.h" 7 #include "vm/bit_vector.h"
8 #include "vm/compiler.h" 8 #include "vm/compiler.h"
9 #include "vm/dart_entry.h" 9 #include "vm/dart_entry.h"
10 #include "vm/flow_graph_builder.h" 10 #include "vm/flow_graph_builder.h"
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
71 * indices of -1 denote non-matched groups. Note that we store these indices 71 * indices of -1 denote non-matched groups. Note that we store these indices
72 * as a negative offset from the end of the string in registers_array_ 72 * as a negative offset from the end of the string in registers_array_
73 * during processing, and convert them to standard indexes when copying them 73 * during processing, and convert them to standard indexes when copying them
74 * to matches_param_ on successful match. 74 * to matches_param_ on successful match.
75 */ 75 */
76 IRRegExpMacroAssembler::IRRegExpMacroAssembler( 76 IRRegExpMacroAssembler::IRRegExpMacroAssembler(
77 intptr_t specialization_cid, 77 intptr_t specialization_cid,
78 intptr_t capture_count, 78 intptr_t capture_count,
79 const ParsedFunction* parsed_function, 79 const ParsedFunction* parsed_function,
80 const ZoneGrowableArray<const ICData*>& ic_data_array, 80 const ZoneGrowableArray<const ICData*>& ic_data_array,
81 intptr_t osr_id,
81 Zone* zone) 82 Zone* zone)
82 : RegExpMacroAssembler(zone), 83 : RegExpMacroAssembler(zone),
83 thread_(Thread::Current()), 84 thread_(Thread::Current()),
84 specialization_cid_(specialization_cid), 85 specialization_cid_(specialization_cid),
85 parsed_function_(parsed_function), 86 parsed_function_(parsed_function),
86 ic_data_array_(ic_data_array), 87 ic_data_array_(ic_data_array),
87 current_instruction_(NULL), 88 current_instruction_(NULL),
88 stack_(NULL), 89 stack_(NULL),
89 stack_pointer_(NULL), 90 stack_pointer_(NULL),
90 current_character_(NULL), 91 current_character_(NULL),
91 current_position_(NULL), 92 current_position_(NULL),
92 string_param_(NULL), 93 string_param_(NULL),
93 string_param_length_(NULL), 94 string_param_length_(NULL),
94 start_index_param_(NULL), 95 start_index_param_(NULL),
95 registers_count_(0), 96 registers_count_(0),
96 saved_registers_count_((capture_count + 1) * 2), 97 saved_registers_count_((capture_count + 1) * 2),
97 stack_array_cell_(Array::ZoneHandle(zone, Array::New(1, Heap::kOld))), 98 stack_array_cell_(Array::ZoneHandle(zone, Array::New(1, Heap::kOld))),
98 // The registers array is allocated at a fixed size after assembly. 99 // The registers array is allocated at a fixed size after assembly.
99 registers_array_(TypedData::ZoneHandle(zone, TypedData::null())) { 100 registers_array_(TypedData::ZoneHandle(zone, TypedData::null())),
101 // B0 is taken by GraphEntry thus block ids must start at 1.
102 block_id_(1) {
100 switch (specialization_cid) { 103 switch (specialization_cid) {
101 case kOneByteStringCid: 104 case kOneByteStringCid:
102 case kExternalOneByteStringCid: 105 case kExternalOneByteStringCid:
103 mode_ = ASCII; 106 mode_ = ASCII;
104 break; 107 break;
105 case kTwoByteStringCid: 108 case kTwoByteStringCid:
106 case kExternalTwoByteStringCid: 109 case kExternalTwoByteStringCid:
107 mode_ = UC16; 110 mode_ = UC16;
108 break; 111 break;
109 default: 112 default:
110 UNREACHABLE(); 113 UNREACHABLE();
111 } 114 }
112 115
113 InitializeLocals(); 116 InitializeLocals();
114 117
115 // Allocate an initial stack backing of the minimum stack size. The stack 118 // Allocate an initial stack backing of the minimum stack size. The stack
116 // backing is indirectly referred to so we can reuse it on subsequent matches 119 // backing is indirectly referred to so we can reuse it on subsequent matches
117 // even in the case where the backing has been enlarged and thus reallocated. 120 // even in the case where the backing has been enlarged and thus reallocated.
118 stack_array_cell_.SetAt( 121 stack_array_cell_.SetAt(
119 0, 122 0,
120 TypedData::Handle(zone, TypedData::New(kTypedDataInt32ArrayCid, 123 TypedData::Handle(zone, TypedData::New(kTypedDataInt32ArrayCid,
121 kMinStackSize / 4, Heap::kOld))); 124 kMinStackSize / 4, Heap::kOld)));
122 125
123 // Create and generate all preset blocks. 126 // Create and generate all preset blocks.
124 entry_block_ = new (zone) GraphEntryInstr( 127 entry_block_ = new (zone) GraphEntryInstr(
125 *parsed_function_, 128 *parsed_function_,
126 new (zone) TargetEntryInstr(block_id_.Alloc(), kInvalidTryIndex, 129 new (zone) TargetEntryInstr(block_id_.Alloc(), kInvalidTryIndex,
127 GetNextDeoptId()), 130 GetNextDeoptId()),
128 Compiler::kNoOSRDeoptId); 131 osr_id);
129 start_block_ = new (zone) 132 start_block_ = new (zone)
130 JoinEntryInstr(block_id_.Alloc(), kInvalidTryIndex, GetNextDeoptId()); 133 JoinEntryInstr(block_id_.Alloc(), kInvalidTryIndex, GetNextDeoptId());
131 success_block_ = new (zone) 134 success_block_ = new (zone)
132 JoinEntryInstr(block_id_.Alloc(), kInvalidTryIndex, GetNextDeoptId()); 135 JoinEntryInstr(block_id_.Alloc(), kInvalidTryIndex, GetNextDeoptId());
133 backtrack_block_ = new (zone) 136 backtrack_block_ = new (zone)
134 JoinEntryInstr(block_id_.Alloc(), kInvalidTryIndex, GetNextDeoptId()); 137 JoinEntryInstr(block_id_.Alloc(), kInvalidTryIndex, GetNextDeoptId());
135 exit_block_ = new (zone) 138 exit_block_ = new (zone)
136 JoinEntryInstr(block_id_.Alloc(), kInvalidTryIndex, GetNextDeoptId()); 139 JoinEntryInstr(block_id_.Alloc(), kInvalidTryIndex, GetNextDeoptId());
137 140
138 GenerateEntryBlock(); 141 GenerateEntryBlock();
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
216 StoreLocal(stack_pointer_, Bind(Int64Constant(-1))); 219 StoreLocal(stack_pointer_, Bind(Int64Constant(-1)));
217 220
218 // Jump to the start block. 221 // Jump to the start block.
219 current_instruction_->Goto(start_block_); 222 current_instruction_->Goto(start_block_);
220 } 223 }
221 224
222 225
223 void IRRegExpMacroAssembler::GenerateBacktrackBlock() { 226 void IRRegExpMacroAssembler::GenerateBacktrackBlock() {
224 set_current_instruction(backtrack_block_); 227 set_current_instruction(backtrack_block_);
225 TAG(); 228 TAG();
226 CheckPreemption(); 229 CheckPreemption(/*is_backtrack=*/true);
227 230
228 const intptr_t entries_count = entry_block_->indirect_entries().length(); 231 const intptr_t entries_count = entry_block_->indirect_entries().length();
229 232
230 TypedData& offsets = TypedData::ZoneHandle( 233 TypedData& offsets = TypedData::ZoneHandle(
231 Z, TypedData::New(kTypedDataInt32ArrayCid, entries_count, Heap::kOld)); 234 Z, TypedData::New(kTypedDataInt32ArrayCid, entries_count, Heap::kOld));
232 235
233 PushArgumentInstr* block_offsets_push = 236 PushArgumentInstr* block_offsets_push =
234 PushArgument(Bind(new (Z) ConstantInstr(offsets))); 237 PushArgument(Bind(new (Z) ConstantInstr(offsets)));
235 PushArgumentInstr* block_id_push = PushArgument(Bind(PopStack())); 238 PushArgumentInstr* block_id_push = PushArgument(Bind(PopStack()));
236 239
(...skipping 1350 matching lines...) Expand 10 before | Expand all | Expand 10 after
1587 1590
1588 BindBlock(&grow_stack); 1591 BindBlock(&grow_stack);
1589 GrowStack(); 1592 GrowStack();
1590 1593
1591 BindBlock(&fallthrough); 1594 BindBlock(&fallthrough);
1592 } 1595 }
1593 1596
1594 1597
1595 void IRRegExpMacroAssembler::GrowStack() { 1598 void IRRegExpMacroAssembler::GrowStack() {
1596 TAG(); 1599 TAG();
1597 Value* cell = Bind(new (Z) ConstantInstr(stack_array_cell_)); 1600 const Library& lib = Library::Handle(Library::InternalLibrary());
1598 StoreLocal(stack_, Bind(new (Z) GrowRegExpStackInstr(cell))); 1601 const Function& grow_function = Function::ZoneHandle(
1602 Z, lib.LookupFunctionAllowPrivate(Symbols::GrowRegExpStack()));
1603 StoreLocal(stack_, Bind(StaticCall(grow_function, PushLocal(stack_))));
1604
1605 // Note: :stack and stack_array_cell content might diverge because each
1606 // instance of :matcher code has its own stack_array_cell embedded into it
1607 // as a constant but :stack is a local variable and its value might be
1608 // comming from OSR or deoptimization. This means we should never use
1609 // stack_array_cell in the body of the :matcher to reload the :stack.
1610 PushArgumentInstr* stack_cell_push =
1611 PushArgument(Bind(new (Z) ConstantInstr(stack_array_cell_)));
1612 PushArgumentInstr* index_push = PushArgument(Bind(Uint64Constant(0)));
1613 PushArgumentInstr* stack_push = PushLocal(stack_);
1614 Do(InstanceCall(InstanceCallDescriptor::FromToken(Token::kASSIGN_INDEX),
1615 stack_cell_push, index_push, stack_push));
1599 } 1616 }
1600 1617
1601 1618
1602 void IRRegExpMacroAssembler::ReadCurrentPositionFromRegister(intptr_t reg) { 1619 void IRRegExpMacroAssembler::ReadCurrentPositionFromRegister(intptr_t reg) {
1603 TAG(); 1620 TAG();
1604 StoreLocal(current_position_, LoadRegister(reg)); 1621 StoreLocal(current_position_, LoadRegister(reg));
1605 } 1622 }
1606 1623
1607 // Resets the tip of the stack to the value stored in reg. 1624 // Resets the tip of the stack to the value stored in reg.
1608 void IRRegExpMacroAssembler::ReadStackPointerFromRegister(intptr_t reg) { 1625 void IRRegExpMacroAssembler::ReadStackPointerFromRegister(intptr_t reg) {
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after
1760 new (Z) IndirectEntryInstr(block_id_.Alloc(), indirect_id_.Alloc(), 1777 new (Z) IndirectEntryInstr(block_id_.Alloc(), indirect_id_.Alloc(),
1761 kInvalidTryIndex, GetNextDeoptId()); 1778 kInvalidTryIndex, GetNextDeoptId());
1762 blocks_.Add(target); 1779 blocks_.Add(target);
1763 1780
1764 target->AppendInstruction(new (Z) GotoInstr(dst, GetNextDeoptId())); 1781 target->AppendInstruction(new (Z) GotoInstr(dst, GetNextDeoptId()));
1765 1782
1766 return target; 1783 return target;
1767 } 1784 }
1768 1785
1769 1786
1770 void IRRegExpMacroAssembler::CheckPreemption() { 1787 void IRRegExpMacroAssembler::CheckPreemption(bool is_backtrack) {
1771 TAG(); 1788 TAG();
1772 AppendInstruction(new (Z) CheckStackOverflowInstr(TokenPosition::kNoSource, 0, 1789
1773 GetNextDeoptId())); 1790 // We don't have the loop_depth available when compiling regexps, but
1791 // we set loop_depth to a non-zero value because this instruction does
1792 // not act as an OSR entry outside loops.
1793 AppendInstruction(new (Z) CheckStackOverflowInstr(
1794 TokenPosition::kNoSource,
1795 /*loop_depth=*/1, GetNextDeoptId(),
1796 is_backtrack ? CheckStackOverflowInstr::kOsrAndPreemption
1797 : CheckStackOverflowInstr::kOsrOnly));
1774 } 1798 }
1775 1799
1776 1800
1777 Definition* IRRegExpMacroAssembler::Add(PushArgumentInstr* lhs, 1801 Definition* IRRegExpMacroAssembler::Add(PushArgumentInstr* lhs,
1778 PushArgumentInstr* rhs) { 1802 PushArgumentInstr* rhs) {
1779 return InstanceCall(InstanceCallDescriptor::FromToken(Token::kADD), lhs, rhs); 1803 return InstanceCall(InstanceCallDescriptor::FromToken(Token::kADD), lhs, rhs);
1780 } 1804 }
1781 1805
1782 1806
1783 Definition* IRRegExpMacroAssembler::Sub(PushArgumentInstr* lhs, 1807 Definition* IRRegExpMacroAssembler::Sub(PushArgumentInstr* lhs,
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
1852 1876
1853 return Bind(new (Z) LoadCodeUnitsInstr(pattern_val, index_val, characters, 1877 return Bind(new (Z) LoadCodeUnitsInstr(pattern_val, index_val, characters,
1854 specialization_cid_, 1878 specialization_cid_,
1855 TokenPosition::kNoSource)); 1879 TokenPosition::kNoSource));
1856 } 1880 }
1857 1881
1858 1882
1859 #undef __ 1883 #undef __
1860 1884
1861 } // namespace dart 1885 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698