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 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
55 * negative offset from the end of the string (i.e. the | 55 * negative offset from the end of the string (i.e. the |
56 * position corresponding to str[0] is -str.length). | 56 * position corresponding to str[0] is -str.length). |
57 * Note that current_position_ is *not* byte-based, unlike | 57 * Note that current_position_ is *not* byte-based, unlike |
58 * original V8 code. | 58 * original V8 code. |
59 * | 59 * |
60 * Results are returned though an array of capture indices, stored at | 60 * Results are returned though an array of capture indices, stored at |
61 * matches_param_. A null array specifies a failure to match. The match indices | 61 * matches_param_. A null array specifies a failure to match. The match indices |
62 * [start_inclusive, end_exclusive] for capture group i are stored at positions | 62 * [start_inclusive, end_exclusive] for capture group i are stored at positions |
63 * matches_param_[i * 2] and matches_param_[i * 2 + 1], respectively. Match | 63 * matches_param_[i * 2] and matches_param_[i * 2 + 1], respectively. Match |
64 * indices of -1 denote non-matched groups. Note that we store these indices | 64 * indices of -1 denote non-matched groups. Note that we store these indices |
65 * as a negative offset from the end of the string in position_registers_ | 65 * as a negative offset from the end of the string in registers_array_ |
66 * during processing, and convert them to standard indexes when copying them | 66 * during processing, and convert them to standard indexes when copying them |
67 * to matches_param_ on successful match. | 67 * to matches_param_ on successful match. |
68 */ | 68 */ |
69 | 69 |
70 RegExpMacroAssembler::RegExpMacroAssembler(Isolate* isolate) | 70 RegExpMacroAssembler::RegExpMacroAssembler(Isolate* isolate) |
71 : slow_safe_compiler_(false), | 71 : slow_safe_compiler_(false), |
72 global_mode_(NOT_GLOBAL), | 72 global_mode_(NOT_GLOBAL), |
73 isolate_(isolate) { | 73 isolate_(isolate) { |
74 } | 74 } |
75 | 75 |
(...skipping 12 matching lines...) Expand all Loading... |
88 specialization_cid_(specialization_cid), | 88 specialization_cid_(specialization_cid), |
89 parsed_function_(parsed_function), | 89 parsed_function_(parsed_function), |
90 ic_data_array_(ic_data_array), | 90 ic_data_array_(ic_data_array), |
91 current_instruction_(NULL), | 91 current_instruction_(NULL), |
92 stack_(NULL), | 92 stack_(NULL), |
93 current_character_(NULL), | 93 current_character_(NULL), |
94 current_position_(NULL), | 94 current_position_(NULL), |
95 string_param_(NULL), | 95 string_param_(NULL), |
96 string_param_length_(NULL), | 96 string_param_length_(NULL), |
97 start_index_param_(NULL), | 97 start_index_param_(NULL), |
98 position_registers_count_((capture_count + 1) * 2), | 98 registers_count_(0), |
| 99 saved_registers_count_((capture_count + 1) * 2), |
99 stack_array_(GrowableObjectArray::ZoneHandle( | 100 stack_array_(GrowableObjectArray::ZoneHandle( |
100 isolate, GrowableObjectArray::New(16, Heap::kOld))) { | 101 isolate, GrowableObjectArray::New(16, Heap::kOld))), |
| 102 // The registers array is allocated at a fixed size after assembly. |
| 103 registers_array_(TypedData::ZoneHandle(isolate, TypedData::null())) { |
101 switch (specialization_cid) { | 104 switch (specialization_cid) { |
102 case kOneByteStringCid: | 105 case kOneByteStringCid: |
103 case kExternalOneByteStringCid: mode_ = ASCII; break; | 106 case kExternalOneByteStringCid: mode_ = ASCII; break; |
104 case kTwoByteStringCid: | 107 case kTwoByteStringCid: |
105 case kExternalTwoByteStringCid: mode_ = UC16; break; | 108 case kExternalTwoByteStringCid: mode_ = UC16; break; |
106 default: UNREACHABLE(); | 109 default: UNREACHABLE(); |
107 } | 110 } |
108 | 111 |
109 InitializeLocals(); | 112 InitializeLocals(); |
110 | 113 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
142 IRRegExpMacroAssembler::~IRRegExpMacroAssembler() { } | 145 IRRegExpMacroAssembler::~IRRegExpMacroAssembler() { } |
143 | 146 |
144 | 147 |
145 void IRRegExpMacroAssembler::InitializeLocals() { | 148 void IRRegExpMacroAssembler::InitializeLocals() { |
146 // All generated functions are expected to have a current-context variable. | 149 // All generated functions are expected to have a current-context variable. |
147 // This variable is unused in irregexp functions. | 150 // This variable is unused in irregexp functions. |
148 parsed_function_->current_context_var()->set_index(GetNextLocalIndex()); | 151 parsed_function_->current_context_var()->set_index(GetNextLocalIndex()); |
149 | 152 |
150 // Create local variables and parameters. | 153 // Create local variables and parameters. |
151 stack_ = Local(Symbols::stack()); | 154 stack_ = Local(Symbols::stack()); |
| 155 registers_ = Local(Symbols::position_registers()); |
152 current_character_ = Local(Symbols::current_character()); | 156 current_character_ = Local(Symbols::current_character()); |
153 current_position_ = Local(Symbols::current_position()); | 157 current_position_ = Local(Symbols::current_position()); |
154 string_param_length_ = Local(Symbols::string_param_length()); | 158 string_param_length_ = Local(Symbols::string_param_length()); |
155 capture_length_ = Local(Symbols::capture_length()); | 159 capture_length_ = Local(Symbols::capture_length()); |
156 match_start_index_ = Local(Symbols::match_start_index()); | 160 match_start_index_ = Local(Symbols::match_start_index()); |
157 capture_start_index_ = Local(Symbols::capture_start_index()); | 161 capture_start_index_ = Local(Symbols::capture_start_index()); |
158 match_end_index_ = Local(Symbols::match_end_index()); | 162 match_end_index_ = Local(Symbols::match_end_index()); |
159 char_in_capture_ = Local(Symbols::char_in_capture()); | 163 char_in_capture_ = Local(Symbols::char_in_capture()); |
160 char_in_match_ = Local(Symbols::char_in_match()); | 164 char_in_match_ = Local(Symbols::char_in_match()); |
161 index_temp_ = Local(Symbols::index_temp()); | 165 index_temp_ = Local(Symbols::index_temp()); |
162 result_ = Local(Symbols::result()); | 166 result_ = Local(Symbols::result()); |
163 | 167 |
164 string_param_ = Parameter(Symbols::string_param(), 0); | 168 string_param_ = Parameter(Symbols::string_param(), 0); |
165 start_index_param_ = Parameter(Symbols::start_index_param(), 1); | 169 start_index_param_ = Parameter(Symbols::start_index_param(), 1); |
166 | |
167 // Reserve space for all captured group positions. Note that more might | |
168 // be created on the fly for internal use. | |
169 for (intptr_t i = 0; i < position_registers_count_; i++) { | |
170 position_register(i); | |
171 } | |
172 } | 170 } |
173 | 171 |
174 | 172 |
175 void IRRegExpMacroAssembler::GenerateEntryBlock() { | 173 void IRRegExpMacroAssembler::GenerateEntryBlock() { |
176 set_current_instruction(entry_block_->normal_entry()); | 174 set_current_instruction(entry_block_->normal_entry()); |
177 TAG(); | 175 TAG(); |
178 | 176 |
179 // Generate a local list variable which we will use as a backtracking stack. | |
180 | |
181 StoreLocal(stack_, Bind(new(I) ConstantInstr(stack_array_))); | |
182 Do(InstanceCall(InstanceCallDescriptor(Symbols::clear()), PushLocal(stack_))); | |
183 | |
184 // Store string.length. | 177 // Store string.length. |
185 PushArgumentInstr* string_push = PushLocal(string_param_); | 178 PushArgumentInstr* string_push = PushLocal(string_param_); |
186 | 179 |
187 StoreLocal( | 180 StoreLocal( |
188 string_param_length_, | 181 string_param_length_, |
189 Bind(InstanceCall( | 182 Bind(InstanceCall( |
190 InstanceCallDescriptor( | 183 InstanceCallDescriptor( |
191 String::ZoneHandle(Field::GetterSymbol(Symbols::Length()))), | 184 String::ZoneHandle(Field::GetterSymbol(Symbols::Length()))), |
192 string_push))); | 185 string_push))); |
193 | 186 |
194 // Initialize all capture registers. | |
195 ClearRegisters(0, position_registers_count_ - 1); | |
196 | |
197 // Store (start_index - string.length) as the current position (since it's a | 187 // Store (start_index - string.length) as the current position (since it's a |
198 // negative offset from the end of the string). | 188 // negative offset from the end of the string). |
199 PushArgumentInstr* start_index_push = PushLocal(start_index_param_); | 189 PushArgumentInstr* start_index_push = PushLocal(start_index_param_); |
200 PushArgumentInstr* length_push = PushLocal(string_param_length_); | 190 PushArgumentInstr* length_push = PushLocal(string_param_length_); |
201 | 191 |
202 StoreLocal(current_position_, Bind(Sub(start_index_push, length_push))); | 192 StoreLocal(current_position_, Bind(Sub(start_index_push, length_push))); |
203 | 193 |
| 194 // Generate a local list variable to represent "registers" and |
| 195 // initialize capture registers (others remain garbage). |
| 196 StoreLocal(registers_, Bind(new(I) ConstantInstr(registers_array_))); |
| 197 ClearRegisters(0, saved_registers_count_ - 1); |
| 198 |
| 199 // Generate a local list variable to represent the backtracking stack. |
| 200 StoreLocal(stack_, Bind(new(I) ConstantInstr(stack_array_))); |
| 201 PushArgumentInstr* stack_push = PushLocal(stack_); |
| 202 Do(InstanceCall(InstanceCallDescriptor(Symbols::clear()), stack_push)); |
| 203 |
204 // Jump to the start block. | 204 // Jump to the start block. |
205 current_instruction_->Goto(start_block_); | 205 current_instruction_->Goto(start_block_); |
206 } | 206 } |
207 | 207 |
208 | 208 |
209 void IRRegExpMacroAssembler::GenerateBacktrackBlock() { | 209 void IRRegExpMacroAssembler::GenerateBacktrackBlock() { |
210 set_current_instruction(backtrack_block_); | 210 set_current_instruction(backtrack_block_); |
211 TAG(); | 211 TAG(); |
212 CheckPreemption(); | 212 CheckPreemption(); |
213 | 213 |
(...skipping 19 matching lines...) Expand all Loading... |
233 backtrack_goto_->AddSuccessor( | 233 backtrack_goto_->AddSuccessor( |
234 TargetWithJoinGoto(entry_block_->indirect_entries().At(j))); | 234 TargetWithJoinGoto(entry_block_->indirect_entries().At(j))); |
235 } | 235 } |
236 } | 236 } |
237 | 237 |
238 | 238 |
239 void IRRegExpMacroAssembler::GenerateSuccessBlock() { | 239 void IRRegExpMacroAssembler::GenerateSuccessBlock() { |
240 set_current_instruction(success_block_); | 240 set_current_instruction(success_block_); |
241 TAG(); | 241 TAG(); |
242 | 242 |
243 Definition* type_args_null_def = new(I) ConstantInstr( | 243 Value* type = Bind(new(I) ConstantInstr( |
244 TypeArguments::ZoneHandle(I, TypeArguments::null())); | 244 TypeArguments::ZoneHandle(I, TypeArguments::null()))); |
245 PushArgumentInstr* type_arg_push = PushArgument(Bind(type_args_null_def)); | 245 Value* length = Bind(Uint64Constant(saved_registers_count_)); |
246 PushArgumentInstr* length_push = | 246 Value* array = Bind(new(I) CreateArrayInstr(kNoSourcePos, type, length)); |
247 PushArgument(Bind(Uint64Constant(position_registers_count_))); | 247 StoreLocal(result_, array); |
248 | |
249 const Library& lib = Library::Handle(Library::CoreLibrary()); | |
250 const Class& list_class = Class::Handle( | |
251 lib.LookupCoreClass(Symbols::List())); | |
252 const Function& list_ctor = | |
253 Function::ZoneHandle(I, list_class.LookupFactory(Symbols::ListFactory())); | |
254 | |
255 // TODO(zerny): Use CreateArrayInstr and StoreIndexed instead. | |
256 StoreLocal(result_, Bind(StaticCall(list_ctor, type_arg_push, length_push))); | |
257 | 248 |
258 // Store captured offsets in the `matches` parameter. | 249 // Store captured offsets in the `matches` parameter. |
259 // TODO(zerny): Eliminate position_register locals and access `matches` | 250 for (intptr_t i = 0; i < saved_registers_count_; i++) { |
260 // directly. | |
261 for (intptr_t i = 0; i < position_registers_count_; i++) { | |
262 PushArgumentInstr* matches_push = PushLocal(result_); | 251 PushArgumentInstr* matches_push = PushLocal(result_); |
263 PushArgumentInstr* index_push = PushArgument(Bind(Uint64Constant(i))); | 252 PushArgumentInstr* index_push = PushArgument(Bind(Uint64Constant(i))); |
264 | 253 |
265 // Convert negative offsets from the end of the string to string indices. | 254 // Convert negative offsets from the end of the string to string indices. |
266 PushArgumentInstr* offset_push = PushLocal(position_register(i)); | 255 // TODO(zerny): use positive offsets from the get-go. |
| 256 PushArgumentInstr* offset_push = PushArgument(LoadRegister(i)); |
267 PushArgumentInstr* len_push = PushLocal(string_param_length_); | 257 PushArgumentInstr* len_push = PushLocal(string_param_length_); |
268 PushArgumentInstr* value_push = | 258 PushArgumentInstr* value_push = |
269 PushArgument(Bind(Add(offset_push, len_push))); | 259 PushArgument(Bind(Add(offset_push, len_push))); |
270 | 260 |
271 Do(InstanceCall(InstanceCallDescriptor::FromToken(Token::kASSIGN_INDEX), | 261 Do(InstanceCall(InstanceCallDescriptor::FromToken(Token::kASSIGN_INDEX), |
272 matches_push, | 262 matches_push, |
273 index_push, | 263 index_push, |
274 value_push)); | 264 value_push)); |
275 } | 265 } |
276 | 266 |
277 // Print the result if tracing. | 267 // Print the result if tracing. |
278 PRINT(PushLocal(result_)); | 268 PRINT(PushLocal(result_)); |
279 | 269 |
280 // Return true on success. | 270 // Return true on success. |
281 AppendInstruction(new(I) ReturnInstr(kNoSourcePos, Bind(LoadLocal(result_)))); | 271 AppendInstruction(new(I) ReturnInstr(kNoSourcePos, Bind(LoadLocal(result_)))); |
282 } | 272 } |
283 | 273 |
284 | 274 |
285 void IRRegExpMacroAssembler::GenerateExitBlock() { | 275 void IRRegExpMacroAssembler::GenerateExitBlock() { |
286 set_current_instruction(exit_block_); | 276 set_current_instruction(exit_block_); |
287 TAG(); | 277 TAG(); |
288 | 278 |
289 // Return false on failure. | 279 // Return false on failure. |
290 AppendInstruction(new(I) ReturnInstr(kNoSourcePos, Bind(LoadLocal(result_)))); | 280 AppendInstruction(new(I) ReturnInstr(kNoSourcePos, Bind(LoadLocal(result_)))); |
291 } | 281 } |
292 | 282 |
293 | 283 |
| 284 void IRRegExpMacroAssembler::FinalizeRegistersArray() { |
| 285 ASSERT(registers_count_ >= saved_registers_count_); |
| 286 registers_array_ = |
| 287 TypedData::New(kTypedDataInt32ArrayCid, registers_count_, Heap::kOld); |
| 288 } |
| 289 |
| 290 |
294 #if defined(TARGET_ARCH_ARM64) || \ | 291 #if defined(TARGET_ARCH_ARM64) || \ |
295 defined(TARGET_ARCH_ARM) || \ | 292 defined(TARGET_ARCH_ARM) || \ |
296 defined(TARGET_ARCH_MIPS) | 293 defined(TARGET_ARCH_MIPS) |
297 // Disabling unaligned accesses forces the regexp engine to load characters one | 294 // Disabling unaligned accesses forces the regexp engine to load characters one |
298 // by one instead of up to 4 at once, along with the associated performance hit. | 295 // by one instead of up to 4 at once, along with the associated performance hit. |
299 // TODO(zerny): Be less conservative about disabling unaligned accesses. | 296 // TODO(zerny): Be less conservative about disabling unaligned accesses. |
300 // For instance, ARMv6 supports unaligned accesses. Once it is enabled here, | 297 // For instance, ARMv6 supports unaligned accesses. Once it is enabled here, |
301 // update LoadCodeUnitsInstr methods for the appropriate architectures. | 298 // update LoadCodeUnitsInstr methods for the appropriate architectures. |
302 static const bool kEnableUnalignedAccesses = false; | 299 static const bool kEnableUnalignedAccesses = false; |
303 #else | 300 #else |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
429 word_character_field.EvaluateInitializer(); | 426 word_character_field.EvaluateInitializer(); |
430 } | 427 } |
431 ASSERT(!word_character_field.IsUninitialized()); | 428 ASSERT(!word_character_field.IsUninitialized()); |
432 | 429 |
433 return new(I) ConstantInstr( | 430 return new(I) ConstantInstr( |
434 Instance::ZoneHandle(I, word_character_field.value())); | 431 Instance::ZoneHandle(I, word_character_field.value())); |
435 } | 432 } |
436 | 433 |
437 | 434 |
438 ComparisonInstr* IRRegExpMacroAssembler::Comparison( | 435 ComparisonInstr* IRRegExpMacroAssembler::Comparison( |
439 ComparisonKind kind, Definition* lhs, Definition* rhs) { | 436 ComparisonKind kind, PushArgumentInstr* lhs, PushArgumentInstr* rhs) { |
440 Token::Kind strict_comparison = Token::kEQ_STRICT; | 437 Token::Kind strict_comparison = Token::kEQ_STRICT; |
441 Token::Kind intermediate_operator = Token::kILLEGAL; | 438 Token::Kind intermediate_operator = Token::kILLEGAL; |
442 switch (kind) { | 439 switch (kind) { |
443 case kEQ: | 440 case kEQ: |
444 intermediate_operator = Token::kEQ; | 441 intermediate_operator = Token::kEQ; |
445 break; | 442 break; |
446 case kNE: | 443 case kNE: |
447 intermediate_operator = Token::kEQ; | 444 intermediate_operator = Token::kEQ; |
448 strict_comparison = Token::kNE_STRICT; | 445 strict_comparison = Token::kNE_STRICT; |
449 break; | 446 break; |
450 case kLT: | 447 case kLT: |
451 intermediate_operator = Token::kLT; | 448 intermediate_operator = Token::kLT; |
452 break; | 449 break; |
453 case kGT: | 450 case kGT: |
454 intermediate_operator = Token::kGT; | 451 intermediate_operator = Token::kGT; |
455 break; | 452 break; |
456 case kLTE: | 453 case kLTE: |
457 intermediate_operator = Token::kLTE; | 454 intermediate_operator = Token::kLTE; |
458 break; | 455 break; |
459 case kGTE: | 456 case kGTE: |
460 intermediate_operator = Token::kGTE; | 457 intermediate_operator = Token::kGTE; |
461 break; | 458 break; |
462 default: | 459 default: |
463 UNREACHABLE(); | 460 UNREACHABLE(); |
464 } | 461 } |
465 | 462 |
466 ASSERT(intermediate_operator != Token::kILLEGAL); | 463 ASSERT(intermediate_operator != Token::kILLEGAL); |
467 | 464 |
468 PushArgumentInstr* lhs_push = PushArgument(Bind(lhs)); | |
469 PushArgumentInstr* rhs_push = PushArgument(Bind(rhs)); | |
470 | |
471 Value* lhs_value = | 465 Value* lhs_value = |
472 Bind(InstanceCall( | 466 Bind(InstanceCall( |
473 InstanceCallDescriptor::FromToken(intermediate_operator), | 467 InstanceCallDescriptor::FromToken(intermediate_operator), |
474 lhs_push, | 468 lhs, |
475 rhs_push)); | 469 rhs)); |
476 Value* rhs_value = Bind(BoolConstant(true)); | 470 Value* rhs_value = Bind(BoolConstant(true)); |
477 | 471 |
478 return new(I) StrictCompareInstr( | 472 return new(I) StrictCompareInstr( |
479 kNoSourcePos, strict_comparison, lhs_value, rhs_value, true); | 473 kNoSourcePos, strict_comparison, lhs_value, rhs_value, true); |
480 } | 474 } |
481 | 475 |
| 476 ComparisonInstr* IRRegExpMacroAssembler::Comparison( |
| 477 ComparisonKind kind, Definition* lhs, Definition* rhs) { |
| 478 PushArgumentInstr* lhs_push = PushArgument(Bind(lhs)); |
| 479 PushArgumentInstr* rhs_push = PushArgument(Bind(rhs)); |
| 480 return Comparison(kind, lhs_push, rhs_push); |
| 481 } |
| 482 |
482 | 483 |
483 StaticCallInstr* IRRegExpMacroAssembler::StaticCall( | 484 StaticCallInstr* IRRegExpMacroAssembler::StaticCall( |
484 const Function& function) const { | 485 const Function& function) const { |
485 ZoneGrowableArray<PushArgumentInstr*>* arguments = | 486 ZoneGrowableArray<PushArgumentInstr*>* arguments = |
486 new(I) ZoneGrowableArray<PushArgumentInstr*>(0); | 487 new(I) ZoneGrowableArray<PushArgumentInstr*>(0); |
487 return StaticCall(function, arguments); | 488 return StaticCall(function, arguments); |
488 } | 489 } |
489 | 490 |
490 | 491 |
491 StaticCallInstr* IRRegExpMacroAssembler::StaticCall( | 492 StaticCallInstr* IRRegExpMacroAssembler::StaticCall( |
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
728 | 729 |
729 Value* new_pos_value = Bind(Add(cur_pos_push, by_push)); | 730 Value* new_pos_value = Bind(Add(cur_pos_push, by_push)); |
730 StoreLocal(current_position_, new_pos_value); | 731 StoreLocal(current_position_, new_pos_value); |
731 } | 732 } |
732 } | 733 } |
733 | 734 |
734 | 735 |
735 void IRRegExpMacroAssembler::AdvanceRegister(intptr_t reg, intptr_t by) { | 736 void IRRegExpMacroAssembler::AdvanceRegister(intptr_t reg, intptr_t by) { |
736 TAG(); | 737 TAG(); |
737 ASSERT(reg >= 0); | 738 ASSERT(reg >= 0); |
738 ASSERT(reg < position_registers_.length()); | 739 ASSERT(reg < registers_count_); |
739 | 740 |
740 if (by != 0) { | 741 if (by != 0) { |
741 PushArgumentInstr* reg_push = PushLocal(position_register(reg)); | 742 PushArgumentInstr* registers_push = PushLocal(registers_); |
| 743 PushArgumentInstr* index_push = PushRegisterIndex(reg); |
| 744 PushArgumentInstr* reg_push = PushArgument(LoadRegister(reg)); |
742 PushArgumentInstr* by_push = PushArgument(Bind(Int64Constant(by))); | 745 PushArgumentInstr* by_push = PushArgument(Bind(Int64Constant(by))); |
743 StoreLocal(position_register(reg), Bind(Add(reg_push, by_push))); | 746 PushArgumentInstr* value_push = PushArgument(Bind(Add(reg_push, by_push))); |
| 747 StoreRegister(registers_push, index_push, value_push); |
744 } | 748 } |
745 } | 749 } |
746 | 750 |
747 | 751 |
748 void IRRegExpMacroAssembler::Backtrack() { | 752 void IRRegExpMacroAssembler::Backtrack() { |
749 TAG(); | 753 TAG(); |
750 GoTo(backtrack_block_); | 754 GoTo(backtrack_block_); |
751 } | 755 } |
752 | 756 |
753 | 757 |
(...skipping 16 matching lines...) Expand all Loading... |
770 PRINT(PushArgument(Bind(Uint64Constant(label->block()->block_id())))); | 774 PRINT(PushArgument(Bind(Uint64Constant(label->block()->block_id())))); |
771 } | 775 } |
772 | 776 |
773 | 777 |
774 intptr_t IRRegExpMacroAssembler::GetNextLocalIndex() { | 778 intptr_t IRRegExpMacroAssembler::GetNextLocalIndex() { |
775 intptr_t id = local_id_.Alloc(); | 779 intptr_t id = local_id_.Alloc(); |
776 return kFirstLocalSlotFromFp - id; | 780 return kFirstLocalSlotFromFp - id; |
777 } | 781 } |
778 | 782 |
779 | 783 |
780 LocalVariable* IRRegExpMacroAssembler::position_register(intptr_t index) { | 784 Value* IRRegExpMacroAssembler::LoadRegister(intptr_t index) { |
781 // Create position registers as needed. | 785 PushArgumentInstr* registers_push = PushLocal(registers_); |
782 for (intptr_t i = position_registers_.length(); i < index + 1; i++) { | 786 PushArgumentInstr* index_push = PushRegisterIndex(index); |
783 position_registers_.Add(Local(Symbols::position_registers())); | 787 return Bind(InstanceCall(InstanceCallDescriptor::FromToken(Token::kINDEX), |
784 } | 788 registers_push, |
| 789 index_push)); |
| 790 } |
785 | 791 |
786 return position_registers_[index]; | 792 void IRRegExpMacroAssembler::StoreRegister(intptr_t index, intptr_t value) { |
| 793 PushArgumentInstr* registers_push = PushLocal(registers_); |
| 794 PushArgumentInstr* index_push = PushRegisterIndex(index); |
| 795 PushArgumentInstr* value_push = PushArgument(Bind(Uint64Constant(value))); |
| 796 StoreRegister(registers_push, index_push, value_push); |
787 } | 797 } |
788 | 798 |
789 | 799 |
| 800 void IRRegExpMacroAssembler::StoreRegister(PushArgumentInstr* registers, |
| 801 PushArgumentInstr* index, |
| 802 PushArgumentInstr* value) { |
| 803 TAG(); |
| 804 Do(InstanceCall(InstanceCallDescriptor::FromToken(Token::kASSIGN_INDEX), |
| 805 registers, |
| 806 index, |
| 807 value)); |
| 808 } |
| 809 |
| 810 PushArgumentInstr* IRRegExpMacroAssembler::PushRegisterIndex(intptr_t index) { |
| 811 if (registers_count_ <= index) { |
| 812 registers_count_ = index + 1; |
| 813 } |
| 814 return PushArgument(Bind(Uint64Constant(index))); |
| 815 } |
| 816 |
| 817 |
790 void IRRegExpMacroAssembler::CheckCharacter(uint32_t c, BlockLabel* on_equal) { | 818 void IRRegExpMacroAssembler::CheckCharacter(uint32_t c, BlockLabel* on_equal) { |
791 TAG(); | 819 TAG(); |
792 Definition* cur_char_def = LoadLocal(current_character_); | 820 Definition* cur_char_def = LoadLocal(current_character_); |
793 Definition* char_def = Uint64Constant(c); | 821 Definition* char_def = Uint64Constant(c); |
794 | 822 |
795 BranchOrBacktrack(Comparison(kEQ, cur_char_def, char_def), on_equal); | 823 BranchOrBacktrack(Comparison(kEQ, cur_char_def, char_def), on_equal); |
796 } | 824 } |
797 | 825 |
798 | 826 |
799 void IRRegExpMacroAssembler::CheckCharacterGT(uint16_t limit, | 827 void IRRegExpMacroAssembler::CheckCharacterGT(uint16_t limit, |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
883 BranchOrBacktrack(NULL, on_equal); | 911 BranchOrBacktrack(NULL, on_equal); |
884 | 912 |
885 BindBlock(&fallthrough); | 913 BindBlock(&fallthrough); |
886 } | 914 } |
887 | 915 |
888 | 916 |
889 void IRRegExpMacroAssembler::CheckNotBackReferenceIgnoreCase( | 917 void IRRegExpMacroAssembler::CheckNotBackReferenceIgnoreCase( |
890 intptr_t start_reg, | 918 intptr_t start_reg, |
891 BlockLabel* on_no_match) { | 919 BlockLabel* on_no_match) { |
892 TAG(); | 920 TAG(); |
893 ASSERT(start_reg + 1 <= position_registers_.length()); | 921 ASSERT(start_reg + 1 <= registers_count_); |
894 | 922 |
895 BlockLabel fallthrough; | 923 BlockLabel fallthrough; |
896 | 924 |
897 PushArgumentInstr* end_push = PushLocal(position_register(start_reg + 1)); | 925 PushArgumentInstr* end_push = PushArgument(LoadRegister(start_reg + 1)); |
898 PushArgumentInstr* start_push = PushLocal(position_register(start_reg)); | 926 PushArgumentInstr* start_push = PushArgument(LoadRegister(start_reg)); |
899 StoreLocal(capture_length_, Bind(Sub(end_push, start_push))); | 927 StoreLocal(capture_length_, Bind(Sub(end_push, start_push))); |
900 | 928 |
901 // The length of a capture should not be negative. This can only happen | 929 // The length of a capture should not be negative. This can only happen |
902 // if the end of the capture is unrecorded, or at a point earlier than | 930 // if the end of the capture is unrecorded, or at a point earlier than |
903 // the start of the capture. | 931 // the start of the capture. |
904 // BranchOrBacktrack(less, on_no_match); | 932 // BranchOrBacktrack(less, on_no_match); |
905 | 933 |
906 BranchOrBacktrack(Comparison(kLT, | 934 BranchOrBacktrack(Comparison(kLT, |
907 LoadLocal(capture_length_), | 935 LoadLocal(capture_length_), |
908 Uint64Constant(0)), | 936 Uint64Constant(0)), |
(...skipping 15 matching lines...) Expand all Loading... |
924 InstanceCall(InstanceCallDescriptor::FromToken(Token::kADD), | 952 InstanceCall(InstanceCallDescriptor::FromToken(Token::kADD), |
925 pos_push, | 953 pos_push, |
926 len_push), | 954 len_push), |
927 Uint64Constant(0)), | 955 Uint64Constant(0)), |
928 on_no_match); | 956 on_no_match); |
929 | 957 |
930 pos_push = PushLocal(current_position_); | 958 pos_push = PushLocal(current_position_); |
931 len_push = PushLocal(string_param_length_); | 959 len_push = PushLocal(string_param_length_); |
932 StoreLocal(match_start_index_, Bind(Add(pos_push, len_push))); | 960 StoreLocal(match_start_index_, Bind(Add(pos_push, len_push))); |
933 | 961 |
934 pos_push = PushLocal(position_register(start_reg)); | 962 pos_push = PushArgument(LoadRegister(start_reg)); |
935 len_push = PushLocal(string_param_length_); | 963 len_push = PushLocal(string_param_length_); |
936 StoreLocal(capture_start_index_, Bind(Add(pos_push, len_push))); | 964 StoreLocal(capture_start_index_, Bind(Add(pos_push, len_push))); |
937 | 965 |
938 pos_push = PushLocal(match_start_index_); | 966 pos_push = PushLocal(match_start_index_); |
939 len_push = PushLocal(capture_length_); | 967 len_push = PushLocal(capture_length_); |
940 StoreLocal(match_end_index_, Bind(Add(pos_push, len_push))); | 968 StoreLocal(match_end_index_, Bind(Add(pos_push, len_push))); |
941 | 969 |
942 BlockLabel success; | 970 BlockLabel success; |
943 if (mode_ == ASCII) { | 971 if (mode_ == ASCII) { |
944 BlockLabel loop_increment; | 972 BlockLabel loop_increment; |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1050 StoreLocal(current_position_, Bind(Sub(match_end_push, len_push))); | 1078 StoreLocal(current_position_, Bind(Sub(match_end_push, len_push))); |
1051 | 1079 |
1052 BindBlock(&fallthrough); | 1080 BindBlock(&fallthrough); |
1053 } | 1081 } |
1054 | 1082 |
1055 | 1083 |
1056 void IRRegExpMacroAssembler::CheckNotBackReference( | 1084 void IRRegExpMacroAssembler::CheckNotBackReference( |
1057 intptr_t start_reg, | 1085 intptr_t start_reg, |
1058 BlockLabel* on_no_match) { | 1086 BlockLabel* on_no_match) { |
1059 TAG(); | 1087 TAG(); |
1060 ASSERT(start_reg + 1 <= position_registers_.length()); | 1088 ASSERT(start_reg + 1 <= registers_count_); |
1061 | 1089 |
1062 BlockLabel fallthrough; | 1090 BlockLabel fallthrough; |
1063 BlockLabel success; | 1091 BlockLabel success; |
1064 | 1092 |
1065 // Find length of back-referenced capture. | 1093 // Find length of back-referenced capture. |
1066 PushArgumentInstr* end_push = PushLocal(position_register(start_reg + 1)); | 1094 PushArgumentInstr* end_push = PushArgument(LoadRegister(start_reg + 1)); |
1067 PushArgumentInstr* start_push = PushLocal(position_register(start_reg)); | 1095 PushArgumentInstr* start_push = PushArgument(LoadRegister(start_reg)); |
1068 StoreLocal(capture_length_, Bind(Sub(end_push, start_push))); | 1096 StoreLocal(capture_length_, Bind(Sub(end_push, start_push))); |
1069 | 1097 |
1070 // Fail on partial or illegal capture (start of capture after end of capture). | 1098 // Fail on partial or illegal capture (start of capture after end of capture). |
1071 BranchOrBacktrack(Comparison(kLT, | 1099 BranchOrBacktrack(Comparison(kLT, |
1072 LoadLocal(capture_length_), | 1100 LoadLocal(capture_length_), |
1073 Uint64Constant(0)), | 1101 Uint64Constant(0)), |
1074 on_no_match); | 1102 on_no_match); |
1075 | 1103 |
1076 // Succeed on empty capture (including no capture) | 1104 // Succeed on empty capture (including no capture) |
1077 BranchOrBacktrack(Comparison(kEQ, | 1105 BranchOrBacktrack(Comparison(kEQ, |
(...skipping 10 matching lines...) Expand all Loading... |
1088 pos_push, | 1116 pos_push, |
1089 len_push), | 1117 len_push), |
1090 Uint64Constant(0)), | 1118 Uint64Constant(0)), |
1091 on_no_match); | 1119 on_no_match); |
1092 | 1120 |
1093 // Compute pointers to match string and capture string. | 1121 // Compute pointers to match string and capture string. |
1094 pos_push = PushLocal(current_position_); | 1122 pos_push = PushLocal(current_position_); |
1095 len_push = PushLocal(string_param_length_); | 1123 len_push = PushLocal(string_param_length_); |
1096 StoreLocal(match_start_index_, Bind(Add(pos_push, len_push))); | 1124 StoreLocal(match_start_index_, Bind(Add(pos_push, len_push))); |
1097 | 1125 |
1098 pos_push = PushLocal(position_register(start_reg)); | 1126 pos_push = PushArgument(LoadRegister(start_reg)); |
1099 len_push = PushLocal(string_param_length_); | 1127 len_push = PushLocal(string_param_length_); |
1100 StoreLocal(capture_start_index_, Bind(Add(pos_push, len_push))); | 1128 StoreLocal(capture_start_index_, Bind(Add(pos_push, len_push))); |
1101 | 1129 |
1102 pos_push = PushLocal(match_start_index_); | 1130 pos_push = PushLocal(match_start_index_); |
1103 len_push = PushLocal(capture_length_); | 1131 len_push = PushLocal(capture_length_); |
1104 StoreLocal(match_end_index_, Bind(Add(pos_push, len_push))); | 1132 StoreLocal(match_end_index_, Bind(Add(pos_push, len_push))); |
1105 | 1133 |
1106 BlockLabel loop; | 1134 BlockLabel loop; |
1107 BindBlock(&loop); | 1135 BindBlock(&loop); |
1108 | 1136 |
(...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1441 UNREACHABLE(); // Dart regexps are always global. | 1469 UNREACHABLE(); // Dart regexps are always global. |
1442 } | 1470 } |
1443 GoTo(exit_block_); | 1471 GoTo(exit_block_); |
1444 } | 1472 } |
1445 | 1473 |
1446 | 1474 |
1447 void IRRegExpMacroAssembler::IfRegisterGE(intptr_t reg, | 1475 void IRRegExpMacroAssembler::IfRegisterGE(intptr_t reg, |
1448 intptr_t comparand, | 1476 intptr_t comparand, |
1449 BlockLabel* if_ge) { | 1477 BlockLabel* if_ge) { |
1450 TAG(); | 1478 TAG(); |
1451 BranchOrBacktrack(Comparison(kGTE, | 1479 PushArgumentInstr* reg_push = PushArgument(LoadRegister(reg)); |
1452 LoadLocal(position_register(reg)), | 1480 PushArgumentInstr* pos = PushArgument(Bind(Int64Constant(comparand))); |
1453 Int64Constant(comparand)), | 1481 BranchOrBacktrack(Comparison(kGTE, reg_push, pos), if_ge); |
1454 if_ge); | |
1455 } | 1482 } |
1456 | 1483 |
1457 | 1484 |
1458 void IRRegExpMacroAssembler::IfRegisterLT(intptr_t reg, | 1485 void IRRegExpMacroAssembler::IfRegisterLT(intptr_t reg, |
1459 intptr_t comparand, | 1486 intptr_t comparand, |
1460 BlockLabel* if_lt) { | 1487 BlockLabel* if_lt) { |
1461 TAG(); | 1488 TAG(); |
1462 BranchOrBacktrack(Comparison(kLT, | 1489 PushArgumentInstr* reg_push = PushArgument(LoadRegister(reg)); |
1463 LoadLocal(position_register(reg)), | 1490 PushArgumentInstr* pos = PushArgument(Bind(Int64Constant(comparand))); |
1464 Int64Constant(comparand)), | 1491 BranchOrBacktrack(Comparison(kLT, reg_push, pos), if_lt); |
1465 if_lt); | |
1466 } | 1492 } |
1467 | 1493 |
1468 | 1494 |
1469 void IRRegExpMacroAssembler::IfRegisterEqPos(intptr_t reg, | 1495 void IRRegExpMacroAssembler::IfRegisterEqPos(intptr_t reg, |
1470 BlockLabel* if_eq) { | 1496 BlockLabel* if_eq) { |
1471 TAG(); | 1497 TAG(); |
1472 BranchOrBacktrack(Comparison(kEQ, | 1498 PushArgumentInstr* reg_push = PushArgument(LoadRegister(reg)); |
1473 LoadLocal(position_register(reg)), | 1499 PushArgumentInstr* pos = PushArgument(Bind(LoadLocal(current_position_))); |
1474 LoadLocal(current_position_)), | 1500 BranchOrBacktrack(Comparison(kEQ, reg_push, pos), if_eq); |
1475 if_eq); | |
1476 } | 1501 } |
1477 | 1502 |
1478 | 1503 |
1479 RegExpMacroAssembler::IrregexpImplementation | 1504 RegExpMacroAssembler::IrregexpImplementation |
1480 IRRegExpMacroAssembler::Implementation() { | 1505 IRRegExpMacroAssembler::Implementation() { |
1481 return kIRImplementation; | 1506 return kIRImplementation; |
1482 } | 1507 } |
1483 | 1508 |
1484 | 1509 |
1485 void IRRegExpMacroAssembler::LoadCurrentCharacter(intptr_t cp_offset, | 1510 void IRRegExpMacroAssembler::LoadCurrentCharacter(intptr_t cp_offset, |
1486 BlockLabel* on_end_of_input, | 1511 BlockLabel* on_end_of_input, |
1487 bool check_bounds, | 1512 bool check_bounds, |
1488 intptr_t characters) { | 1513 intptr_t characters) { |
1489 TAG(); | 1514 TAG(); |
1490 ASSERT(cp_offset >= -1); // ^ and \b can look behind one character. | 1515 ASSERT(cp_offset >= -1); // ^ and \b can look behind one character. |
1491 ASSERT(cp_offset < (1<<30)); // Be sane! (And ensure negation works) | 1516 ASSERT(cp_offset < (1<<30)); // Be sane! (And ensure negation works) |
1492 if (check_bounds) { | 1517 if (check_bounds) { |
1493 CheckPosition(cp_offset + characters - 1, on_end_of_input); | 1518 CheckPosition(cp_offset + characters - 1, on_end_of_input); |
1494 } | 1519 } |
1495 LoadCurrentCharacterUnchecked(cp_offset, characters); | 1520 LoadCurrentCharacterUnchecked(cp_offset, characters); |
1496 } | 1521 } |
1497 | 1522 |
1498 | 1523 |
1499 void IRRegExpMacroAssembler::PopCurrentPosition() { | 1524 void IRRegExpMacroAssembler::PopCurrentPosition() { |
1500 TAG(); | 1525 TAG(); |
1501 StoreLocal(current_position_, PopStack()); | 1526 StoreLocal(current_position_, PopStack()); |
1502 } | 1527 } |
1503 | 1528 |
1504 | 1529 |
1505 void IRRegExpMacroAssembler::PopRegister(intptr_t register_index) { | 1530 void IRRegExpMacroAssembler::PopRegister(intptr_t reg) { |
1506 TAG(); | 1531 TAG(); |
1507 ASSERT(register_index < position_registers_.length()); | 1532 ASSERT(reg < registers_count_); |
1508 StoreLocal(position_register(register_index), PopStack()); | 1533 PushArgumentInstr* registers_push = PushLocal(registers_); |
| 1534 PushArgumentInstr* index_push = PushRegisterIndex(reg); |
| 1535 PushArgumentInstr* pop_push = PushArgument(PopStack()); |
| 1536 StoreRegister(registers_push, index_push, pop_push); |
1509 } | 1537 } |
1510 | 1538 |
1511 | 1539 |
1512 void IRRegExpMacroAssembler::PushStack(Definition *definition) { | 1540 void IRRegExpMacroAssembler::PushStack(Definition *definition) { |
1513 PushArgumentInstr* stack_push = PushLocal(stack_); | 1541 PushArgumentInstr* stack_push = PushLocal(stack_); |
1514 PushArgumentInstr* value_push = PushArgument(Bind(definition)); | 1542 PushArgumentInstr* value_push = PushArgument(Bind(definition)); |
1515 Do(InstanceCall(InstanceCallDescriptor(Symbols::add()), | 1543 Do(InstanceCall(InstanceCallDescriptor(Symbols::add()), |
1516 stack_push, | 1544 stack_push, |
1517 value_push)); | 1545 value_push)); |
1518 } | 1546 } |
(...skipping 22 matching lines...) Expand all Loading... |
1541 PushStack(offset); | 1569 PushStack(offset); |
1542 } | 1570 } |
1543 | 1571 |
1544 | 1572 |
1545 void IRRegExpMacroAssembler::PushCurrentPosition() { | 1573 void IRRegExpMacroAssembler::PushCurrentPosition() { |
1546 TAG(); | 1574 TAG(); |
1547 PushStack(LoadLocal(current_position_)); | 1575 PushStack(LoadLocal(current_position_)); |
1548 } | 1576 } |
1549 | 1577 |
1550 | 1578 |
1551 void IRRegExpMacroAssembler::PushRegister(intptr_t register_index) { | 1579 void IRRegExpMacroAssembler::PushRegister(intptr_t reg) { |
1552 TAG(); | 1580 TAG(); |
1553 PushStack(LoadLocal(position_register(register_index))); | 1581 PushArgumentInstr* stack_push = PushLocal(stack_); |
| 1582 PushArgumentInstr* value_push = PushArgument(LoadRegister(reg)); |
| 1583 Do(InstanceCall(InstanceCallDescriptor(Symbols::add()), |
| 1584 stack_push, |
| 1585 value_push)); |
1554 } | 1586 } |
1555 | 1587 |
1556 | 1588 |
1557 void IRRegExpMacroAssembler::ReadCurrentPositionFromRegister(intptr_t reg) { | 1589 void IRRegExpMacroAssembler::ReadCurrentPositionFromRegister(intptr_t reg) { |
1558 TAG(); | 1590 TAG(); |
1559 StoreLocal(current_position_, Bind(LoadLocal(position_register(reg)))); | 1591 StoreLocal(current_position_, LoadRegister(reg)); |
1560 } | 1592 } |
1561 | 1593 |
1562 // Resets the size of the stack to the value stored in reg. | 1594 // Resets the size of the stack to the value stored in reg. |
1563 void IRRegExpMacroAssembler::ReadStackPointerFromRegister(intptr_t reg) { | 1595 void IRRegExpMacroAssembler::ReadStackPointerFromRegister(intptr_t reg) { |
1564 TAG(); | 1596 TAG(); |
1565 ASSERT(reg < position_registers_.length()); | 1597 ASSERT(reg < registers_count_); |
1566 | 1598 |
1567 PushArgumentInstr* stack_push = PushLocal(stack_); | 1599 PushArgumentInstr* stack_push = PushLocal(stack_); |
1568 PushArgumentInstr* length_push = PushLocal(position_register(reg)); | 1600 PushArgumentInstr* length_push = PushArgument(LoadRegister(reg)); |
1569 | 1601 |
1570 Do(InstanceCall( | 1602 Do(InstanceCall( |
1571 InstanceCallDescriptor( | 1603 InstanceCallDescriptor( |
1572 String::ZoneHandle(I, Field::SetterSymbol(Symbols::Length()))), | 1604 String::ZoneHandle(I, Field::SetterSymbol(Symbols::Length()))), |
1573 stack_push, | 1605 stack_push, |
1574 length_push)); | 1606 length_push)); |
1575 } | 1607 } |
1576 | 1608 |
1577 void IRRegExpMacroAssembler::SetCurrentPositionFromEnd(intptr_t by) { | 1609 void IRRegExpMacroAssembler::SetCurrentPositionFromEnd(intptr_t by) { |
1578 TAG(); | 1610 TAG(); |
(...skipping 10 matching lines...) Expand all Loading... |
1589 | 1621 |
1590 // On RegExp code entry (where this operation is used), the character before | 1622 // On RegExp code entry (where this operation is used), the character before |
1591 // the current position is expected to be already loaded. | 1623 // the current position is expected to be already loaded. |
1592 // We have advanced the position, so it's safe to read backwards. | 1624 // We have advanced the position, so it's safe to read backwards. |
1593 LoadCurrentCharacterUnchecked(-1, 1); | 1625 LoadCurrentCharacterUnchecked(-1, 1); |
1594 | 1626 |
1595 BindBlock(&after_position); | 1627 BindBlock(&after_position); |
1596 } | 1628 } |
1597 | 1629 |
1598 | 1630 |
1599 void IRRegExpMacroAssembler::SetRegister(intptr_t register_index, intptr_t to) { | 1631 void IRRegExpMacroAssembler::SetRegister(intptr_t reg, intptr_t to) { |
1600 TAG(); | 1632 TAG(); |
1601 // Reserved for positions! | 1633 // Reserved for positions! |
1602 ASSERT(register_index >= position_registers_count_); | 1634 ASSERT(reg >= saved_registers_count_); |
1603 StoreLocal(position_register(register_index), Bind(Int64Constant(to))); | 1635 StoreRegister(reg, to); |
1604 } | 1636 } |
1605 | 1637 |
1606 | 1638 |
1607 bool IRRegExpMacroAssembler::Succeed() { | 1639 bool IRRegExpMacroAssembler::Succeed() { |
1608 TAG(); | 1640 TAG(); |
1609 GoTo(success_block_); | 1641 GoTo(success_block_); |
1610 return global(); | 1642 return global(); |
1611 } | 1643 } |
1612 | 1644 |
1613 | 1645 |
1614 void IRRegExpMacroAssembler::WriteCurrentPositionToRegister( | 1646 void IRRegExpMacroAssembler::WriteCurrentPositionToRegister( |
1615 intptr_t reg, intptr_t cp_offset) { | 1647 intptr_t reg, intptr_t cp_offset) { |
1616 TAG(); | 1648 TAG(); |
1617 | 1649 |
| 1650 PushArgumentInstr* registers_push = PushLocal(registers_); |
| 1651 PushArgumentInstr* index_push = PushRegisterIndex(reg); |
1618 PushArgumentInstr* pos_push = PushLocal(current_position_); | 1652 PushArgumentInstr* pos_push = PushLocal(current_position_); |
1619 PushArgumentInstr* off_push = | 1653 PushArgumentInstr* off_push = PushArgument(Bind(Int64Constant(cp_offset))); |
1620 PushArgument(Bind(Int64Constant(cp_offset))); | 1654 PushArgumentInstr* neg_off_push = PushArgument(Bind(Add(pos_push, off_push))); |
1621 | |
1622 // Push the negative offset; these are converted to positive string positions | 1655 // Push the negative offset; these are converted to positive string positions |
1623 // within the success block. | 1656 // within the success block. |
1624 StoreLocal(position_register(reg), Bind(Add(pos_push, off_push))); | 1657 StoreRegister(registers_push, index_push, neg_off_push); |
1625 } | 1658 } |
1626 | 1659 |
1627 | 1660 |
1628 void IRRegExpMacroAssembler::ClearRegisters( | 1661 void IRRegExpMacroAssembler::ClearRegisters( |
1629 intptr_t reg_from, intptr_t reg_to) { | 1662 intptr_t reg_from, intptr_t reg_to) { |
1630 TAG(); | 1663 TAG(); |
1631 | 1664 |
1632 ASSERT(reg_from <= reg_to); | 1665 ASSERT(reg_from <= reg_to); |
1633 ASSERT(reg_to < position_registers_.length()); | |
1634 | 1666 |
1635 // In order to clear registers to a final result value of -1, set them to | 1667 // In order to clear registers to a final result value of -1, set them to |
1636 // (-1 - string length), the offset of -1 from the end of the string. | 1668 // (-1 - string length), the offset of -1 from the end of the string. |
1637 | 1669 |
1638 for (intptr_t reg = reg_from; reg <= reg_to; reg++) { | 1670 for (intptr_t reg = reg_from; reg <= reg_to; reg++) { |
| 1671 PushArgumentInstr* registers_push = PushLocal(registers_); |
| 1672 PushArgumentInstr* index_push = PushRegisterIndex(reg); |
1639 PushArgumentInstr* minus_one_push = | 1673 PushArgumentInstr* minus_one_push = |
1640 PushArgument(Bind(Int64Constant(-1))); | 1674 PushArgument(Bind(Int64Constant(-1))); |
1641 PushArgumentInstr* length_push = PushLocal(string_param_length_); | 1675 PushArgumentInstr* length_push = PushLocal(string_param_length_); |
1642 | 1676 PushArgumentInstr* value_push = |
1643 StoreLocal(position_register(reg), Bind(Sub(minus_one_push, length_push))); | 1677 PushArgument(Bind(Sub(minus_one_push, length_push))); |
| 1678 StoreRegister(registers_push, index_push, value_push); |
1644 } | 1679 } |
1645 } | 1680 } |
1646 | 1681 |
1647 | 1682 |
1648 void IRRegExpMacroAssembler::WriteStackPointerToRegister(intptr_t reg) { | 1683 void IRRegExpMacroAssembler::WriteStackPointerToRegister(intptr_t reg) { |
1649 TAG(); | 1684 TAG(); |
1650 | 1685 |
| 1686 PushArgumentInstr* registers_push = PushLocal(registers_); |
| 1687 PushArgumentInstr* index_push = PushRegisterIndex(reg); |
1651 PushArgumentInstr* stack_push = PushLocal(stack_); | 1688 PushArgumentInstr* stack_push = PushLocal(stack_); |
1652 Value* length_value = | 1689 PushArgumentInstr* length_push = |
1653 Bind(InstanceCall(InstanceCallDescriptor( | 1690 PushArgument(Bind(InstanceCall(InstanceCallDescriptor( |
1654 String::ZoneHandle( | 1691 String::ZoneHandle(I, Field::GetterSymbol(Symbols::Length()))), |
1655 I, Field::GetterSymbol(Symbols::Length()))), | 1692 stack_push))); |
1656 stack_push)); | 1693 StoreRegister(registers_push, index_push, length_push); |
1657 | |
1658 StoreLocal(position_register(reg), length_value); | |
1659 } | 1694 } |
1660 | 1695 |
1661 | 1696 |
1662 // Private methods: | 1697 // Private methods: |
1663 | 1698 |
1664 | 1699 |
1665 void IRRegExpMacroAssembler::CheckPosition(intptr_t cp_offset, | 1700 void IRRegExpMacroAssembler::CheckPosition(intptr_t cp_offset, |
1666 BlockLabel* on_outside_input) { | 1701 BlockLabel* on_outside_input) { |
1667 TAG(); | 1702 TAG(); |
1668 Definition* curpos_def = LoadLocal(current_position_); | 1703 Definition* curpos_def = LoadLocal(current_position_); |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1826 index_val, | 1861 index_val, |
1827 characters, | 1862 characters, |
1828 specialization_cid_, | 1863 specialization_cid_, |
1829 Scanner::kNoSourcePos)); | 1864 Scanner::kNoSourcePos)); |
1830 } | 1865 } |
1831 | 1866 |
1832 | 1867 |
1833 #undef __ | 1868 #undef __ |
1834 | 1869 |
1835 } // namespace dart | 1870 } // namespace dart |
OLD | NEW |