OLD | NEW |
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.h" | 5 #include "vm/regexp_assembler.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 18 matching lines...) Expand all Loading... |
29 | 29 |
30 #define PRINT(arg) if (FLAG_trace_irregexp) { Print(arg); } | 30 #define PRINT(arg) if (FLAG_trace_irregexp) { Print(arg); } |
31 | 31 |
32 namespace dart { | 32 namespace dart { |
33 | 33 |
34 DEFINE_FLAG(bool, trace_irregexp, false, "Trace irregexps"); | 34 DEFINE_FLAG(bool, trace_irregexp, false, "Trace irregexps"); |
35 | 35 |
36 | 36 |
37 static const intptr_t kInvalidTryIndex = CatchClauseNode::kInvalidTryIndex; | 37 static const intptr_t kInvalidTryIndex = CatchClauseNode::kInvalidTryIndex; |
38 static const intptr_t kNoSourcePos = Scanner::kNoSourcePos; | 38 static const intptr_t kNoSourcePos = Scanner::kNoSourcePos; |
| 39 static const intptr_t kMinStackSize = 512; |
39 | 40 |
40 | 41 |
41 void PrintUtf16(uint16_t c) { | 42 void PrintUtf16(uint16_t c) { |
42 const char* format = (0x20 <= c && c <= 0x7F) ? | 43 const char* format = (0x20 <= c && c <= 0x7F) ? |
43 "%c" : (c <= 0xff) ? "\\x%02x" : "\\u%04x"; | 44 "%c" : (c <= 0xff) ? "\\x%02x" : "\\u%04x"; |
44 OS::Print(format, c); | 45 OS::Print(format, c); |
45 } | 46 } |
46 | 47 |
47 | 48 |
48 /* | 49 /* |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
83 intptr_t capture_count, | 84 intptr_t capture_count, |
84 const ParsedFunction* parsed_function, | 85 const ParsedFunction* parsed_function, |
85 const ZoneGrowableArray<const ICData*>& ic_data_array, | 86 const ZoneGrowableArray<const ICData*>& ic_data_array, |
86 Isolate* isolate) | 87 Isolate* isolate) |
87 : RegExpMacroAssembler(isolate), | 88 : RegExpMacroAssembler(isolate), |
88 specialization_cid_(specialization_cid), | 89 specialization_cid_(specialization_cid), |
89 parsed_function_(parsed_function), | 90 parsed_function_(parsed_function), |
90 ic_data_array_(ic_data_array), | 91 ic_data_array_(ic_data_array), |
91 current_instruction_(NULL), | 92 current_instruction_(NULL), |
92 stack_(NULL), | 93 stack_(NULL), |
| 94 stack_pointer_(NULL), |
93 current_character_(NULL), | 95 current_character_(NULL), |
94 current_position_(NULL), | 96 current_position_(NULL), |
95 string_param_(NULL), | 97 string_param_(NULL), |
96 string_param_length_(NULL), | 98 string_param_length_(NULL), |
97 start_index_param_(NULL), | 99 start_index_param_(NULL), |
98 registers_count_(0), | 100 registers_count_(0), |
99 saved_registers_count_((capture_count + 1) * 2), | 101 saved_registers_count_((capture_count + 1) * 2), |
100 stack_array_(GrowableObjectArray::ZoneHandle( | 102 stack_array_cell_(Array::ZoneHandle(isolate, Array::New(1, Heap::kOld))), |
101 isolate, GrowableObjectArray::New(16, Heap::kOld))), | |
102 // The registers array is allocated at a fixed size after assembly. | 103 // The registers array is allocated at a fixed size after assembly. |
103 registers_array_(TypedData::ZoneHandle(isolate, TypedData::null())) { | 104 registers_array_(TypedData::ZoneHandle(isolate, TypedData::null())) { |
104 switch (specialization_cid) { | 105 switch (specialization_cid) { |
105 case kOneByteStringCid: | 106 case kOneByteStringCid: |
106 case kExternalOneByteStringCid: mode_ = ASCII; break; | 107 case kExternalOneByteStringCid: mode_ = ASCII; break; |
107 case kTwoByteStringCid: | 108 case kTwoByteStringCid: |
108 case kExternalTwoByteStringCid: mode_ = UC16; break; | 109 case kExternalTwoByteStringCid: mode_ = UC16; break; |
109 default: UNREACHABLE(); | 110 default: UNREACHABLE(); |
110 } | 111 } |
111 | 112 |
112 InitializeLocals(); | 113 InitializeLocals(); |
113 | 114 |
| 115 // 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 |
| 117 // even in the case where the backing has been enlarged and thus reallocated. |
| 118 stack_array_cell_.SetAt(0, TypedData::Handle(isolate, |
| 119 TypedData::New(kTypedDataInt32ArrayCid, kMinStackSize / 4, Heap::kOld))); |
| 120 |
114 // Create and generate all preset blocks. | 121 // Create and generate all preset blocks. |
115 entry_block_ = | 122 entry_block_ = |
116 new(isolate) GraphEntryInstr( | 123 new(isolate) GraphEntryInstr( |
117 parsed_function_, | 124 parsed_function_, |
118 new(isolate) TargetEntryInstr(block_id_.Alloc(), kInvalidTryIndex), | 125 new(isolate) TargetEntryInstr(block_id_.Alloc(), kInvalidTryIndex), |
119 Isolate::kNoDeoptId); | 126 Isolate::kNoDeoptId); |
120 start_block_ = | 127 start_block_ = |
121 new(isolate) JoinEntryInstr(block_id_.Alloc(), kInvalidTryIndex); | 128 new(isolate) JoinEntryInstr(block_id_.Alloc(), kInvalidTryIndex); |
122 success_block_ = | 129 success_block_ = |
123 new(isolate) JoinEntryInstr(block_id_.Alloc(), kInvalidTryIndex); | 130 new(isolate) JoinEntryInstr(block_id_.Alloc(), kInvalidTryIndex); |
(...skipping 21 matching lines...) Expand all Loading... |
145 IRRegExpMacroAssembler::~IRRegExpMacroAssembler() { } | 152 IRRegExpMacroAssembler::~IRRegExpMacroAssembler() { } |
146 | 153 |
147 | 154 |
148 void IRRegExpMacroAssembler::InitializeLocals() { | 155 void IRRegExpMacroAssembler::InitializeLocals() { |
149 // All generated functions are expected to have a current-context variable. | 156 // All generated functions are expected to have a current-context variable. |
150 // This variable is unused in irregexp functions. | 157 // This variable is unused in irregexp functions. |
151 parsed_function_->current_context_var()->set_index(GetNextLocalIndex()); | 158 parsed_function_->current_context_var()->set_index(GetNextLocalIndex()); |
152 | 159 |
153 // Create local variables and parameters. | 160 // Create local variables and parameters. |
154 stack_ = Local(Symbols::stack()); | 161 stack_ = Local(Symbols::stack()); |
| 162 stack_pointer_ = Local(Symbols::stack_pointer()); |
155 registers_ = Local(Symbols::position_registers()); | 163 registers_ = Local(Symbols::position_registers()); |
156 current_character_ = Local(Symbols::current_character()); | 164 current_character_ = Local(Symbols::current_character()); |
157 current_position_ = Local(Symbols::current_position()); | 165 current_position_ = Local(Symbols::current_position()); |
158 string_param_length_ = Local(Symbols::string_param_length()); | 166 string_param_length_ = Local(Symbols::string_param_length()); |
159 capture_length_ = Local(Symbols::capture_length()); | 167 capture_length_ = Local(Symbols::capture_length()); |
160 match_start_index_ = Local(Symbols::match_start_index()); | 168 match_start_index_ = Local(Symbols::match_start_index()); |
161 capture_start_index_ = Local(Symbols::capture_start_index()); | 169 capture_start_index_ = Local(Symbols::capture_start_index()); |
162 match_end_index_ = Local(Symbols::match_end_index()); | 170 match_end_index_ = Local(Symbols::match_end_index()); |
163 char_in_capture_ = Local(Symbols::char_in_capture()); | 171 char_in_capture_ = Local(Symbols::char_in_capture()); |
164 char_in_match_ = Local(Symbols::char_in_match()); | 172 char_in_match_ = Local(Symbols::char_in_match()); |
(...skipping 25 matching lines...) Expand all Loading... |
190 PushArgumentInstr* length_push = PushLocal(string_param_length_); | 198 PushArgumentInstr* length_push = PushLocal(string_param_length_); |
191 | 199 |
192 StoreLocal(current_position_, Bind(Sub(start_index_push, length_push))); | 200 StoreLocal(current_position_, Bind(Sub(start_index_push, length_push))); |
193 | 201 |
194 // Generate a local list variable to represent "registers" and | 202 // Generate a local list variable to represent "registers" and |
195 // initialize capture registers (others remain garbage). | 203 // initialize capture registers (others remain garbage). |
196 StoreLocal(registers_, Bind(new(I) ConstantInstr(registers_array_))); | 204 StoreLocal(registers_, Bind(new(I) ConstantInstr(registers_array_))); |
197 ClearRegisters(0, saved_registers_count_ - 1); | 205 ClearRegisters(0, saved_registers_count_ - 1); |
198 | 206 |
199 // Generate a local list variable to represent the backtracking stack. | 207 // Generate a local list variable to represent the backtracking stack. |
200 StoreLocal(stack_, Bind(new(I) ConstantInstr(stack_array_))); | 208 PushArgumentInstr* stack_cell_push = |
201 PushArgumentInstr* stack_push = PushLocal(stack_); | 209 PushArgument(Bind(new(I) ConstantInstr(stack_array_cell_))); |
202 PushArgumentInstr* zero_push = PushArgument(Bind(Uint64Constant(0))); | 210 StoreLocal(stack_, Bind(InstanceCall( |
203 Do(InstanceCall(InstanceCallDescriptor( | 211 InstanceCallDescriptor::FromToken(Token::kINDEX), |
204 Library::PrivateCoreLibName(Symbols::_setLength())), | 212 stack_cell_push, |
205 stack_push, | 213 PushArgument(Bind(Uint64Constant(0)))))); |
206 zero_push)); | 214 StoreLocal(stack_pointer_, Bind(Int64Constant(-1))); |
207 | 215 |
208 // Jump to the start block. | 216 // Jump to the start block. |
209 current_instruction_->Goto(start_block_); | 217 current_instruction_->Goto(start_block_); |
210 } | 218 } |
211 | 219 |
212 | 220 |
213 void IRRegExpMacroAssembler::GenerateBacktrackBlock() { | 221 void IRRegExpMacroAssembler::GenerateBacktrackBlock() { |
214 set_current_instruction(backtrack_block_); | 222 set_current_instruction(backtrack_block_); |
215 TAG(); | 223 TAG(); |
216 CheckPreemption(); | 224 CheckPreemption(); |
217 | 225 |
218 const intptr_t entries_count = entry_block_->indirect_entries().length(); | 226 const intptr_t entries_count = entry_block_->indirect_entries().length(); |
219 | 227 |
220 TypedData& offsets = TypedData::ZoneHandle(I, | 228 TypedData& offsets = TypedData::ZoneHandle(I, |
221 TypedData::New(kTypedDataInt32ArrayCid, entries_count, Heap::kOld)); | 229 TypedData::New(kTypedDataInt32ArrayCid, entries_count, Heap::kOld)); |
222 | 230 |
223 PushArgumentInstr* block_offsets_push = | 231 PushArgumentInstr* block_offsets_push = |
224 PushArgument(Bind(new(I) ConstantInstr(offsets))); | 232 PushArgument(Bind(new(I) ConstantInstr(offsets))); |
225 PushArgumentInstr* block_id_push = PushArgument(PopStack()); | 233 PushArgumentInstr* block_id_push = PushArgument(Bind(PopStack())); |
226 | 234 |
227 Value* offset_value = | 235 Value* offset_value = |
228 Bind(InstanceCall(InstanceCallDescriptor::FromToken(Token::kINDEX), | 236 Bind(InstanceCall(InstanceCallDescriptor::FromToken(Token::kINDEX), |
229 block_offsets_push, | 237 block_offsets_push, |
230 block_id_push)); | 238 block_id_push)); |
231 | 239 |
232 backtrack_goto_ = new(I) IndirectGotoInstr(&offsets, offset_value); | 240 backtrack_goto_ = new(I) IndirectGotoInstr(&offsets, offset_value); |
233 CloseBlockWith(backtrack_goto_); | 241 CloseBlockWith(backtrack_goto_); |
234 | 242 |
235 // Add an edge from the "indirect" goto to each of the targets. | 243 // Add an edge from the "indirect" goto to each of the targets. |
(...skipping 654 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
890 Uint64Constant(limit)), | 898 Uint64Constant(limit)), |
891 on_less); | 899 on_less); |
892 } | 900 } |
893 | 901 |
894 | 902 |
895 void IRRegExpMacroAssembler::CheckGreedyLoop(BlockLabel* on_equal) { | 903 void IRRegExpMacroAssembler::CheckGreedyLoop(BlockLabel* on_equal) { |
896 TAG(); | 904 TAG(); |
897 | 905 |
898 BlockLabel fallthrough; | 906 BlockLabel fallthrough; |
899 | 907 |
900 PushArgumentInstr* stack_push = PushLocal(stack_); | 908 Definition* head = PeekStack(); |
901 Definition* stack_tip_def = InstanceCall( | |
902 InstanceCallDescriptor(String::ZoneHandle( | |
903 I, Field::GetterSymbol(Symbols::last()))), | |
904 stack_push); | |
905 Definition* cur_pos_def = LoadLocal(current_position_); | 909 Definition* cur_pos_def = LoadLocal(current_position_); |
906 | 910 BranchOrBacktrack(Comparison(kNE, head, cur_pos_def), |
907 BranchOrBacktrack(Comparison(kNE, stack_tip_def, cur_pos_def), | |
908 &fallthrough); | 911 &fallthrough); |
909 | 912 |
910 // Pop, throwing away the value. | 913 // Pop, throwing away the value. |
911 stack_push = PushLocal(stack_); | 914 Do(PopStack()); |
912 Do(InstanceCall(InstanceCallDescriptor(Symbols::removeLast()), | |
913 stack_push)); | |
914 | 915 |
915 BranchOrBacktrack(NULL, on_equal); | 916 BranchOrBacktrack(NULL, on_equal); |
916 | 917 |
917 BindBlock(&fallthrough); | 918 BindBlock(&fallthrough); |
918 } | 919 } |
919 | 920 |
920 | 921 |
921 void IRRegExpMacroAssembler::CheckNotBackReferenceIgnoreCase( | 922 void IRRegExpMacroAssembler::CheckNotBackReferenceIgnoreCase( |
922 intptr_t start_reg, | 923 intptr_t start_reg, |
923 BlockLabel* on_no_match) { | 924 BlockLabel* on_no_match) { |
(...skipping 596 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1520 ASSERT(cp_offset < (1<<30)); // Be sane! (And ensure negation works) | 1521 ASSERT(cp_offset < (1<<30)); // Be sane! (And ensure negation works) |
1521 if (check_bounds) { | 1522 if (check_bounds) { |
1522 CheckPosition(cp_offset + characters - 1, on_end_of_input); | 1523 CheckPosition(cp_offset + characters - 1, on_end_of_input); |
1523 } | 1524 } |
1524 LoadCurrentCharacterUnchecked(cp_offset, characters); | 1525 LoadCurrentCharacterUnchecked(cp_offset, characters); |
1525 } | 1526 } |
1526 | 1527 |
1527 | 1528 |
1528 void IRRegExpMacroAssembler::PopCurrentPosition() { | 1529 void IRRegExpMacroAssembler::PopCurrentPosition() { |
1529 TAG(); | 1530 TAG(); |
1530 StoreLocal(current_position_, PopStack()); | 1531 StoreLocal(current_position_, Bind(PopStack())); |
1531 } | 1532 } |
1532 | 1533 |
1533 | 1534 |
1534 void IRRegExpMacroAssembler::PopRegister(intptr_t reg) { | 1535 void IRRegExpMacroAssembler::PopRegister(intptr_t reg) { |
1535 TAG(); | 1536 TAG(); |
1536 ASSERT(reg < registers_count_); | 1537 ASSERT(reg < registers_count_); |
1537 PushArgumentInstr* registers_push = PushLocal(registers_); | 1538 PushArgumentInstr* registers_push = PushLocal(registers_); |
1538 PushArgumentInstr* index_push = PushRegisterIndex(reg); | 1539 PushArgumentInstr* index_push = PushRegisterIndex(reg); |
1539 PushArgumentInstr* pop_push = PushArgument(PopStack()); | 1540 PushArgumentInstr* pop_push = PushArgument(Bind(PopStack())); |
1540 StoreRegister(registers_push, index_push, pop_push); | 1541 StoreRegister(registers_push, index_push, pop_push); |
1541 } | 1542 } |
1542 | 1543 |
1543 | 1544 |
1544 void IRRegExpMacroAssembler::PushStack(Definition *definition) { | 1545 void IRRegExpMacroAssembler::PushStack(Definition *definition) { |
1545 PushArgumentInstr* stack_push = PushLocal(stack_); | 1546 PushArgumentInstr* stack_push = PushLocal(stack_); |
| 1547 PushArgumentInstr* stack_pointer_push = PushLocal(stack_pointer_); |
| 1548 StoreLocal(stack_pointer_, |
| 1549 Bind(Add(stack_pointer_push, |
| 1550 PushArgument(Bind(Uint64Constant(1)))))); |
| 1551 stack_pointer_push = PushLocal(stack_pointer_); |
| 1552 // TODO(zerny): bind value and push could break stack discipline. |
1546 PushArgumentInstr* value_push = PushArgument(Bind(definition)); | 1553 PushArgumentInstr* value_push = PushArgument(Bind(definition)); |
1547 Do(InstanceCall(InstanceCallDescriptor(Symbols::add()), | 1554 Do(InstanceCall(InstanceCallDescriptor::FromToken(Token::kASSIGN_INDEX), |
1548 stack_push, | 1555 stack_push, |
| 1556 stack_pointer_push, |
1549 value_push)); | 1557 value_push)); |
1550 } | 1558 } |
1551 | 1559 |
1552 | 1560 |
1553 Value* IRRegExpMacroAssembler::PopStack() { | 1561 Definition* IRRegExpMacroAssembler::PopStack() { |
1554 PushArgumentInstr* stack_push = PushLocal(stack_); | 1562 PushArgumentInstr* stack_push = PushLocal(stack_); |
1555 return Bind(InstanceCall(InstanceCallDescriptor(Symbols::removeLast()), | 1563 PushArgumentInstr* stack_pointer_push1 = PushLocal(stack_pointer_); |
1556 stack_push)); | 1564 PushArgumentInstr* stack_pointer_push2 = PushLocal(stack_pointer_); |
| 1565 StoreLocal(stack_pointer_, |
| 1566 Bind(Sub(stack_pointer_push2, |
| 1567 PushArgument(Bind(Uint64Constant(1)))))); |
| 1568 return InstanceCall(InstanceCallDescriptor::FromToken(Token::kINDEX), |
| 1569 stack_push, |
| 1570 stack_pointer_push1); |
1557 } | 1571 } |
1558 | 1572 |
1559 | 1573 |
| 1574 Definition* IRRegExpMacroAssembler::PeekStack() { |
| 1575 PushArgumentInstr* stack_push = PushLocal(stack_); |
| 1576 PushArgumentInstr* stack_pointer_push = PushLocal(stack_pointer_); |
| 1577 return InstanceCall(InstanceCallDescriptor::FromToken(Token::kINDEX), |
| 1578 stack_push, |
| 1579 stack_pointer_push); |
| 1580 } |
| 1581 |
| 1582 |
1560 // Pushes the location corresponding to label to the backtracking stack. | 1583 // Pushes the location corresponding to label to the backtracking stack. |
1561 void IRRegExpMacroAssembler::PushBacktrack(BlockLabel* label) { | 1584 void IRRegExpMacroAssembler::PushBacktrack(BlockLabel* label) { |
1562 TAG(); | 1585 TAG(); |
1563 | 1586 |
1564 // Ensure that targets of indirect jumps are never accessed through a | 1587 // Ensure that targets of indirect jumps are never accessed through a |
1565 // normal control flow instructions by creating a new block for each backtrack | 1588 // normal control flow instructions by creating a new block for each backtrack |
1566 // target. | 1589 // target. |
1567 IndirectEntryInstr* indirect_target = IndirectWithJoinGoto(label->block()); | 1590 IndirectEntryInstr* indirect_target = IndirectWithJoinGoto(label->block()); |
1568 | 1591 |
1569 // Add a fake edge from the graph entry for data flow analysis. | 1592 // Add a fake edge from the graph entry for data flow analysis. |
1570 entry_block_->AddIndirectEntry(indirect_target); | 1593 entry_block_->AddIndirectEntry(indirect_target); |
1571 | 1594 |
1572 ConstantInstr* offset = Uint64Constant(indirect_target->indirect_id()); | 1595 ConstantInstr* offset = Uint64Constant(indirect_target->indirect_id()); |
1573 PushStack(offset); | 1596 PushStack(offset); |
| 1597 CheckStackLimit(); |
1574 } | 1598 } |
1575 | 1599 |
1576 | 1600 |
1577 void IRRegExpMacroAssembler::PushCurrentPosition() { | 1601 void IRRegExpMacroAssembler::PushCurrentPosition() { |
1578 TAG(); | 1602 TAG(); |
1579 PushStack(LoadLocal(current_position_)); | 1603 PushStack(LoadLocal(current_position_)); |
1580 } | 1604 } |
1581 | 1605 |
1582 | 1606 |
1583 void IRRegExpMacroAssembler::PushRegister(intptr_t reg) { | 1607 void IRRegExpMacroAssembler::PushRegister(intptr_t reg) { |
1584 TAG(); | 1608 TAG(); |
| 1609 // TODO(zerny): Refactor PushStack so it can be reused here. |
1585 PushArgumentInstr* stack_push = PushLocal(stack_); | 1610 PushArgumentInstr* stack_push = PushLocal(stack_); |
| 1611 PushArgumentInstr* stack_pointer_push = PushLocal(stack_pointer_); |
| 1612 StoreLocal(stack_pointer_, |
| 1613 Bind(Add(stack_pointer_push, |
| 1614 PushArgument(Bind(Uint64Constant(1)))))); |
| 1615 stack_pointer_push = PushLocal(stack_pointer_); |
| 1616 // TODO(zerny): bind value and push could break stack discipline. |
1586 PushArgumentInstr* value_push = PushArgument(LoadRegister(reg)); | 1617 PushArgumentInstr* value_push = PushArgument(LoadRegister(reg)); |
1587 Do(InstanceCall(InstanceCallDescriptor(Symbols::add()), | 1618 Do(InstanceCall(InstanceCallDescriptor::FromToken(Token::kASSIGN_INDEX), |
1588 stack_push, | 1619 stack_push, |
| 1620 stack_pointer_push, |
1589 value_push)); | 1621 value_push)); |
| 1622 CheckStackLimit(); |
1590 } | 1623 } |
1591 | 1624 |
1592 | 1625 |
| 1626 // Checks that (stack.capacity - stack_limit_slack) > stack_pointer. |
| 1627 // This ensures that up to stack_limit_slack stack pushes can be |
| 1628 // done without exhausting the stack space. If the check fails the |
| 1629 // stack will be grown. |
| 1630 void IRRegExpMacroAssembler::CheckStackLimit() { |
| 1631 TAG(); |
| 1632 PushArgumentInstr* stack_push = PushLocal(stack_); |
| 1633 PushArgumentInstr* length_push = PushArgument(Bind(InstanceCall( |
| 1634 InstanceCallDescriptor( |
| 1635 String::ZoneHandle(Field::GetterSymbol(Symbols::Length()))), |
| 1636 stack_push))); |
| 1637 PushArgumentInstr* capacity_push = PushArgument(Bind(Sub( |
| 1638 length_push, |
| 1639 PushArgument(Bind(Uint64Constant(stack_limit_slack())))))); |
| 1640 PushArgumentInstr* stack_pointer_push = PushLocal(stack_pointer_); |
| 1641 BranchInstr* branch = new(I) BranchInstr( |
| 1642 Comparison(kGT, capacity_push, stack_pointer_push)); |
| 1643 CloseBlockWith(branch); |
| 1644 |
| 1645 BlockLabel grow_stack; |
| 1646 BlockLabel fallthrough; |
| 1647 *branch->true_successor_address() = |
| 1648 TargetWithJoinGoto(fallthrough.block()); |
| 1649 *branch->false_successor_address() = |
| 1650 TargetWithJoinGoto(grow_stack.block()); |
| 1651 |
| 1652 BindBlock(&grow_stack); |
| 1653 GrowStack(); |
| 1654 |
| 1655 BindBlock(&fallthrough); |
| 1656 } |
| 1657 |
| 1658 |
| 1659 void IRRegExpMacroAssembler::GrowStack() { |
| 1660 TAG(); |
| 1661 Value* cell = Bind(new(I) ConstantInstr(stack_array_cell_)); |
| 1662 StoreLocal(stack_, Bind(new(I) GrowRegExpStackInstr(cell))); |
| 1663 } |
| 1664 |
| 1665 |
1593 void IRRegExpMacroAssembler::ReadCurrentPositionFromRegister(intptr_t reg) { | 1666 void IRRegExpMacroAssembler::ReadCurrentPositionFromRegister(intptr_t reg) { |
1594 TAG(); | 1667 TAG(); |
1595 StoreLocal(current_position_, LoadRegister(reg)); | 1668 StoreLocal(current_position_, LoadRegister(reg)); |
1596 } | 1669 } |
1597 | 1670 |
1598 // Resets the size of the stack to the value stored in reg. | 1671 // Resets the tip of the stack to the value stored in reg. |
1599 void IRRegExpMacroAssembler::ReadStackPointerFromRegister(intptr_t reg) { | 1672 void IRRegExpMacroAssembler::ReadStackPointerFromRegister(intptr_t reg) { |
1600 TAG(); | 1673 TAG(); |
1601 ASSERT(reg < registers_count_); | 1674 ASSERT(reg < registers_count_); |
1602 | 1675 StoreLocal(stack_pointer_, LoadRegister(reg)); |
1603 PushArgumentInstr* stack_push = PushLocal(stack_); | |
1604 PushArgumentInstr* length_push = PushArgument(LoadRegister(reg)); | |
1605 | |
1606 Do(InstanceCall( | |
1607 InstanceCallDescriptor( | |
1608 String::ZoneHandle(I, Field::SetterSymbol(Symbols::Length()))), | |
1609 stack_push, | |
1610 length_push)); | |
1611 } | 1676 } |
1612 | 1677 |
1613 void IRRegExpMacroAssembler::SetCurrentPositionFromEnd(intptr_t by) { | 1678 void IRRegExpMacroAssembler::SetCurrentPositionFromEnd(intptr_t by) { |
1614 TAG(); | 1679 TAG(); |
1615 | 1680 |
1616 BlockLabel after_position; | 1681 BlockLabel after_position; |
1617 | 1682 |
1618 Definition* cur_pos_def = LoadLocal(current_position_); | 1683 Definition* cur_pos_def = LoadLocal(current_position_); |
1619 Definition* by_value_def = Int64Constant(-by); | 1684 Definition* by_value_def = Int64Constant(-by); |
1620 | 1685 |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1682 StoreRegister(registers_push, index_push, value_push); | 1747 StoreRegister(registers_push, index_push, value_push); |
1683 } | 1748 } |
1684 } | 1749 } |
1685 | 1750 |
1686 | 1751 |
1687 void IRRegExpMacroAssembler::WriteStackPointerToRegister(intptr_t reg) { | 1752 void IRRegExpMacroAssembler::WriteStackPointerToRegister(intptr_t reg) { |
1688 TAG(); | 1753 TAG(); |
1689 | 1754 |
1690 PushArgumentInstr* registers_push = PushLocal(registers_); | 1755 PushArgumentInstr* registers_push = PushLocal(registers_); |
1691 PushArgumentInstr* index_push = PushRegisterIndex(reg); | 1756 PushArgumentInstr* index_push = PushRegisterIndex(reg); |
1692 PushArgumentInstr* stack_push = PushLocal(stack_); | 1757 PushArgumentInstr* tip_push = PushLocal(stack_pointer_); |
1693 PushArgumentInstr* length_push = | 1758 StoreRegister(registers_push, index_push, tip_push); |
1694 PushArgument(Bind(InstanceCall(InstanceCallDescriptor( | |
1695 String::ZoneHandle(I, Field::GetterSymbol(Symbols::Length()))), | |
1696 stack_push))); | |
1697 StoreRegister(registers_push, index_push, length_push); | |
1698 } | 1759 } |
1699 | 1760 |
1700 | 1761 |
1701 // Private methods: | 1762 // Private methods: |
1702 | 1763 |
1703 | 1764 |
1704 void IRRegExpMacroAssembler::CheckPosition(intptr_t cp_offset, | 1765 void IRRegExpMacroAssembler::CheckPosition(intptr_t cp_offset, |
1705 BlockLabel* on_outside_input) { | 1766 BlockLabel* on_outside_input) { |
1706 TAG(); | 1767 TAG(); |
1707 Definition* curpos_def = LoadLocal(current_position_); | 1768 Definition* curpos_def = LoadLocal(current_position_); |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1865 index_val, | 1926 index_val, |
1866 characters, | 1927 characters, |
1867 specialization_cid_, | 1928 specialization_cid_, |
1868 Scanner::kNoSourcePos)); | 1929 Scanner::kNoSourcePos)); |
1869 } | 1930 } |
1870 | 1931 |
1871 | 1932 |
1872 #undef __ | 1933 #undef __ |
1873 | 1934 |
1874 } // namespace dart | 1935 } // namespace dart |
OLD | NEW |