OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 #if V8_TARGET_ARCH_MIPS | 5 #if V8_TARGET_ARCH_MIPS |
6 | 6 |
7 #include "src/regexp/mips/regexp-macro-assembler-mips.h" | 7 #include "src/regexp/mips/regexp-macro-assembler-mips.h" |
8 | 8 |
9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
10 #include "src/log.h" | 10 #include "src/log.h" |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
174 BranchOrBacktrack(on_equal, eq, current_character(), Operand(c)); | 174 BranchOrBacktrack(on_equal, eq, current_character(), Operand(c)); |
175 } | 175 } |
176 | 176 |
177 | 177 |
178 void RegExpMacroAssemblerMIPS::CheckCharacterGT(uc16 limit, Label* on_greater) { | 178 void RegExpMacroAssemblerMIPS::CheckCharacterGT(uc16 limit, Label* on_greater) { |
179 BranchOrBacktrack(on_greater, gt, current_character(), Operand(limit)); | 179 BranchOrBacktrack(on_greater, gt, current_character(), Operand(limit)); |
180 } | 180 } |
181 | 181 |
182 | 182 |
183 void RegExpMacroAssemblerMIPS::CheckAtStart(Label* on_at_start) { | 183 void RegExpMacroAssemblerMIPS::CheckAtStart(Label* on_at_start) { |
184 Label not_at_start; | 184 __ lw(a1, MemOperand(frame_pointer(), kStringStartMinusOne)); |
185 // Did we start the match at the start of the string at all? | 185 __ Addu(a0, current_input_offset(), Operand(-char_size())); |
186 __ lw(a0, MemOperand(frame_pointer(), kStartIndex)); | |
187 BranchOrBacktrack(¬_at_start, ne, a0, Operand(zero_reg)); | |
188 | |
189 // If we did, are we still at the start of the input? | |
190 __ lw(a1, MemOperand(frame_pointer(), kInputStart)); | |
191 __ Addu(a0, end_of_input_address(), Operand(current_input_offset())); | |
192 BranchOrBacktrack(on_at_start, eq, a0, Operand(a1)); | 186 BranchOrBacktrack(on_at_start, eq, a0, Operand(a1)); |
193 __ bind(¬_at_start); | |
194 } | 187 } |
195 | 188 |
196 | 189 |
197 void RegExpMacroAssemblerMIPS::CheckNotAtStart(Label* on_not_at_start) { | 190 void RegExpMacroAssemblerMIPS::CheckNotAtStart(int cp_offset, |
198 // Did we start the match at the start of the string at all? | 191 Label* on_not_at_start) { |
199 __ lw(a0, MemOperand(frame_pointer(), kStartIndex)); | 192 __ lw(a1, MemOperand(frame_pointer(), kStringStartMinusOne)); |
200 BranchOrBacktrack(on_not_at_start, ne, a0, Operand(zero_reg)); | 193 __ Addu(a0, current_input_offset(), |
201 // If we did, are we still at the start of the input? | 194 Operand(-char_size() + cp_offset * char_size())); |
202 __ lw(a1, MemOperand(frame_pointer(), kInputStart)); | |
203 __ Addu(a0, end_of_input_address(), Operand(current_input_offset())); | |
204 BranchOrBacktrack(on_not_at_start, ne, a0, Operand(a1)); | 195 BranchOrBacktrack(on_not_at_start, ne, a0, Operand(a1)); |
205 } | 196 } |
206 | 197 |
207 | 198 |
208 void RegExpMacroAssemblerMIPS::CheckCharacterLT(uc16 limit, Label* on_less) { | 199 void RegExpMacroAssemblerMIPS::CheckCharacterLT(uc16 limit, Label* on_less) { |
209 BranchOrBacktrack(on_less, lt, current_character(), Operand(limit)); | 200 BranchOrBacktrack(on_less, lt, current_character(), Operand(limit)); |
210 } | 201 } |
211 | 202 |
212 | 203 |
213 void RegExpMacroAssemblerMIPS::CheckGreedyLoop(Label* on_equal) { | 204 void RegExpMacroAssemblerMIPS::CheckGreedyLoop(Label* on_equal) { |
214 Label backtrack_non_equal; | 205 Label backtrack_non_equal; |
215 __ lw(a0, MemOperand(backtrack_stackpointer(), 0)); | 206 __ lw(a0, MemOperand(backtrack_stackpointer(), 0)); |
216 __ Branch(&backtrack_non_equal, ne, current_input_offset(), Operand(a0)); | 207 __ Branch(&backtrack_non_equal, ne, current_input_offset(), Operand(a0)); |
217 __ Addu(backtrack_stackpointer(), | 208 __ Addu(backtrack_stackpointer(), |
218 backtrack_stackpointer(), | 209 backtrack_stackpointer(), |
219 Operand(kPointerSize)); | 210 Operand(kPointerSize)); |
220 __ bind(&backtrack_non_equal); | 211 __ bind(&backtrack_non_equal); |
221 BranchOrBacktrack(on_equal, eq, current_input_offset(), Operand(a0)); | 212 BranchOrBacktrack(on_equal, eq, current_input_offset(), Operand(a0)); |
222 } | 213 } |
223 | 214 |
224 | 215 |
225 void RegExpMacroAssemblerMIPS::CheckNotBackReferenceIgnoreCase( | 216 void RegExpMacroAssemblerMIPS::CheckNotBackReferenceIgnoreCase( |
226 int start_reg, | 217 int start_reg, bool read_backward, Label* on_no_match) { |
227 Label* on_no_match) { | |
228 Label fallthrough; | 218 Label fallthrough; |
229 __ lw(a0, register_location(start_reg)); // Index of start of capture. | 219 __ lw(a0, register_location(start_reg)); // Index of start of capture. |
230 __ lw(a1, register_location(start_reg + 1)); // Index of end of capture. | 220 __ lw(a1, register_location(start_reg + 1)); // Index of end of capture. |
231 __ Subu(a1, a1, a0); // Length of capture. | 221 __ Subu(a1, a1, a0); // Length of capture. |
232 | 222 |
233 // If length is zero, either the capture is empty or it is not participating. | 223 // At this point, the capture registers are either both set or both cleared. |
234 // In either case succeed immediately. | 224 // If the capture length is zero, then the capture is either empty or cleared. |
| 225 // Fall through in both cases. |
235 __ Branch(&fallthrough, eq, a1, Operand(zero_reg)); | 226 __ Branch(&fallthrough, eq, a1, Operand(zero_reg)); |
236 | 227 |
237 __ Addu(t5, a1, current_input_offset()); | 228 if (read_backward) { |
238 // Check that there are enough characters left in the input. | 229 __ lw(t0, MemOperand(frame_pointer(), kStringStartMinusOne)); |
239 BranchOrBacktrack(on_no_match, gt, t5, Operand(zero_reg)); | 230 __ Addu(t0, t0, a1); |
| 231 BranchOrBacktrack(on_no_match, le, current_input_offset(), Operand(t0)); |
| 232 } else { |
| 233 __ Addu(t5, a1, current_input_offset()); |
| 234 // Check that there are enough characters left in the input. |
| 235 BranchOrBacktrack(on_no_match, gt, t5, Operand(zero_reg)); |
| 236 } |
240 | 237 |
241 if (mode_ == LATIN1) { | 238 if (mode_ == LATIN1) { |
242 Label success; | 239 Label success; |
243 Label fail; | 240 Label fail; |
244 Label loop_check; | 241 Label loop_check; |
245 | 242 |
246 // a0 - offset of start of capture. | 243 // a0 - offset of start of capture. |
247 // a1 - length of capture. | 244 // a1 - length of capture. |
248 __ Addu(a0, a0, Operand(end_of_input_address())); | 245 __ Addu(a0, a0, Operand(end_of_input_address())); |
249 __ Addu(a2, end_of_input_address(), Operand(current_input_offset())); | 246 __ Addu(a2, end_of_input_address(), Operand(current_input_offset())); |
| 247 if (read_backward) { |
| 248 __ Subu(a2, a2, Operand(a1)); |
| 249 } |
250 __ Addu(a1, a0, Operand(a1)); | 250 __ Addu(a1, a0, Operand(a1)); |
251 | 251 |
252 // a0 - Address of start of capture. | 252 // a0 - Address of start of capture. |
253 // a1 - Address of end of capture. | 253 // a1 - Address of end of capture. |
254 // a2 - Address of current input position. | 254 // a2 - Address of current input position. |
255 | 255 |
256 Label loop; | 256 Label loop; |
257 __ bind(&loop); | 257 __ bind(&loop); |
258 __ lbu(a3, MemOperand(a0, 0)); | 258 __ lbu(a3, MemOperand(a0, 0)); |
259 __ addiu(a0, a0, char_size()); | 259 __ addiu(a0, a0, char_size()); |
(...skipping 18 matching lines...) Expand all Loading... |
278 __ bind(&loop_check); | 278 __ bind(&loop_check); |
279 __ Branch(&loop, lt, a0, Operand(a1)); | 279 __ Branch(&loop, lt, a0, Operand(a1)); |
280 __ jmp(&success); | 280 __ jmp(&success); |
281 | 281 |
282 __ bind(&fail); | 282 __ bind(&fail); |
283 GoTo(on_no_match); | 283 GoTo(on_no_match); |
284 | 284 |
285 __ bind(&success); | 285 __ bind(&success); |
286 // Compute new value of character position after the matched part. | 286 // Compute new value of character position after the matched part. |
287 __ Subu(current_input_offset(), a2, end_of_input_address()); | 287 __ Subu(current_input_offset(), a2, end_of_input_address()); |
| 288 if (read_backward) { |
| 289 __ lw(t0, register_location(start_reg)); // Index of start of capture. |
| 290 __ lw(t5, register_location(start_reg + 1)); // Index of end of capture. |
| 291 __ Addu(current_input_offset(), current_input_offset(), Operand(t0)); |
| 292 __ Subu(current_input_offset(), current_input_offset(), Operand(t5)); |
| 293 } |
288 } else { | 294 } else { |
289 DCHECK(mode_ == UC16); | 295 DCHECK(mode_ == UC16); |
290 // Put regexp engine registers on stack. | 296 // Put regexp engine registers on stack. |
291 RegList regexp_registers_to_retain = current_input_offset().bit() | | 297 RegList regexp_registers_to_retain = current_input_offset().bit() | |
292 current_character().bit() | backtrack_stackpointer().bit(); | 298 current_character().bit() | backtrack_stackpointer().bit(); |
293 __ MultiPush(regexp_registers_to_retain); | 299 __ MultiPush(regexp_registers_to_retain); |
294 | 300 |
295 int argument_count = 4; | 301 int argument_count = 4; |
296 __ PrepareCallCFunction(argument_count, a2); | 302 __ PrepareCallCFunction(argument_count, a2); |
297 | 303 |
298 // a0 - offset of start of capture. | 304 // a0 - offset of start of capture. |
299 // a1 - length of capture. | 305 // a1 - length of capture. |
300 | 306 |
301 // Put arguments into arguments registers. | 307 // Put arguments into arguments registers. |
302 // Parameters are | 308 // Parameters are |
303 // a0: Address byte_offset1 - Address captured substring's start. | 309 // a0: Address byte_offset1 - Address captured substring's start. |
304 // a1: Address byte_offset2 - Address of current character position. | 310 // a1: Address byte_offset2 - Address of current character position. |
305 // a2: size_t byte_length - length of capture in bytes(!). | 311 // a2: size_t byte_length - length of capture in bytes(!). |
306 // a3: Isolate* isolate. | 312 // a3: Isolate* isolate. |
307 | 313 |
308 // Address of start of capture. | 314 // Address of start of capture. |
309 __ Addu(a0, a0, Operand(end_of_input_address())); | 315 __ Addu(a0, a0, Operand(end_of_input_address())); |
310 // Length of capture. | 316 // Length of capture. |
311 __ mov(a2, a1); | 317 __ mov(a2, a1); |
312 // Save length in callee-save register for use on return. | 318 // Save length in callee-save register for use on return. |
313 __ mov(s3, a1); | 319 __ mov(s3, a1); |
314 // Address of current input position. | 320 // Address of current input position. |
315 __ Addu(a1, current_input_offset(), Operand(end_of_input_address())); | 321 __ Addu(a1, current_input_offset(), Operand(end_of_input_address())); |
| 322 if (read_backward) { |
| 323 __ Subu(a1, a1, Operand(s3)); |
| 324 } |
316 // Isolate. | 325 // Isolate. |
317 __ li(a3, Operand(ExternalReference::isolate_address(masm_->isolate()))); | 326 __ li(a3, Operand(ExternalReference::isolate_address(masm_->isolate()))); |
318 | 327 |
319 { | 328 { |
320 AllowExternalCallThatCantCauseGC scope(masm_); | 329 AllowExternalCallThatCantCauseGC scope(masm_); |
321 ExternalReference function = | 330 ExternalReference function = |
322 ExternalReference::re_case_insensitive_compare_uc16(masm_->isolate()); | 331 ExternalReference::re_case_insensitive_compare_uc16(masm_->isolate()); |
323 __ CallCFunction(function, argument_count); | 332 __ CallCFunction(function, argument_count); |
324 } | 333 } |
325 | 334 |
326 // Restore regexp engine registers. | 335 // Restore regexp engine registers. |
327 __ MultiPop(regexp_registers_to_retain); | 336 __ MultiPop(regexp_registers_to_retain); |
328 __ li(code_pointer(), Operand(masm_->CodeObject()), CONSTANT_SIZE); | 337 __ li(code_pointer(), Operand(masm_->CodeObject()), CONSTANT_SIZE); |
329 __ lw(end_of_input_address(), MemOperand(frame_pointer(), kInputEnd)); | 338 __ lw(end_of_input_address(), MemOperand(frame_pointer(), kInputEnd)); |
330 | 339 |
331 // Check if function returned non-zero for success or zero for failure. | 340 // Check if function returned non-zero for success or zero for failure. |
332 BranchOrBacktrack(on_no_match, eq, v0, Operand(zero_reg)); | 341 BranchOrBacktrack(on_no_match, eq, v0, Operand(zero_reg)); |
333 // On success, increment position by length of capture. | 342 // On success, advance position by length of capture. |
334 __ Addu(current_input_offset(), current_input_offset(), Operand(s3)); | 343 if (read_backward) { |
| 344 __ Subu(current_input_offset(), current_input_offset(), Operand(s3)); |
| 345 } else { |
| 346 __ Addu(current_input_offset(), current_input_offset(), Operand(s3)); |
| 347 } |
335 } | 348 } |
336 | 349 |
337 __ bind(&fallthrough); | 350 __ bind(&fallthrough); |
338 } | 351 } |
339 | 352 |
340 | 353 |
341 void RegExpMacroAssemblerMIPS::CheckNotBackReference( | 354 void RegExpMacroAssemblerMIPS::CheckNotBackReference(int start_reg, |
342 int start_reg, | 355 bool read_backward, |
343 Label* on_no_match) { | 356 Label* on_no_match) { |
344 Label fallthrough; | 357 Label fallthrough; |
345 Label success; | 358 Label success; |
346 | 359 |
347 // Find length of back-referenced capture. | 360 // Find length of back-referenced capture. |
348 __ lw(a0, register_location(start_reg)); | 361 __ lw(a0, register_location(start_reg)); |
349 __ lw(a1, register_location(start_reg + 1)); | 362 __ lw(a1, register_location(start_reg + 1)); |
350 __ Subu(a1, a1, a0); // Length to check. | 363 __ Subu(a1, a1, a0); // Length to check. |
351 // Succeed on empty capture (including no capture). | |
352 __ Branch(&fallthrough, eq, a1, Operand(zero_reg)); | |
353 | 364 |
354 __ Addu(t5, a1, current_input_offset()); | 365 // At this point, the capture registers are either both set or both cleared. |
355 // Check that there are enough characters left in the input. | 366 // If the capture length is zero, then the capture is either empty or cleared. |
356 BranchOrBacktrack(on_no_match, gt, t5, Operand(zero_reg)); | 367 // Fall through in both cases. |
| 368 __ Branch(&fallthrough, le, a1, Operand(zero_reg)); |
357 | 369 |
358 // Compute pointers to match string and capture string. | 370 if (read_backward) { |
| 371 __ lw(t0, MemOperand(frame_pointer(), kStringStartMinusOne)); |
| 372 __ Addu(t0, t0, a1); |
| 373 BranchOrBacktrack(on_no_match, le, current_input_offset(), Operand(t0)); |
| 374 } else { |
| 375 __ Addu(t5, a1, current_input_offset()); |
| 376 // Check that there are enough characters left in the input. |
| 377 BranchOrBacktrack(on_no_match, gt, t5, Operand(zero_reg)); |
| 378 } |
| 379 |
| 380 // a0 - offset of start of capture. |
| 381 // a1 - length of capture. |
359 __ Addu(a0, a0, Operand(end_of_input_address())); | 382 __ Addu(a0, a0, Operand(end_of_input_address())); |
360 __ Addu(a2, end_of_input_address(), Operand(current_input_offset())); | 383 __ Addu(a2, end_of_input_address(), Operand(current_input_offset())); |
361 __ Addu(a1, a1, Operand(a0)); | 384 if (read_backward) { |
| 385 __ Subu(a2, a2, Operand(a1)); |
| 386 } |
| 387 __ Addu(a1, a0, Operand(a1)); |
| 388 |
| 389 // a0 - Address of start of capture. |
| 390 // a1 - Address of end of capture. |
| 391 // a2 - Address of current input position. |
| 392 |
362 | 393 |
363 Label loop; | 394 Label loop; |
364 __ bind(&loop); | 395 __ bind(&loop); |
365 if (mode_ == LATIN1) { | 396 if (mode_ == LATIN1) { |
366 __ lbu(a3, MemOperand(a0, 0)); | 397 __ lbu(a3, MemOperand(a0, 0)); |
367 __ addiu(a0, a0, char_size()); | 398 __ addiu(a0, a0, char_size()); |
368 __ lbu(t0, MemOperand(a2, 0)); | 399 __ lbu(t0, MemOperand(a2, 0)); |
369 __ addiu(a2, a2, char_size()); | 400 __ addiu(a2, a2, char_size()); |
370 } else { | 401 } else { |
371 DCHECK(mode_ == UC16); | 402 DCHECK(mode_ == UC16); |
372 __ lhu(a3, MemOperand(a0, 0)); | 403 __ lhu(a3, MemOperand(a0, 0)); |
373 __ addiu(a0, a0, char_size()); | 404 __ addiu(a0, a0, char_size()); |
374 __ lhu(t0, MemOperand(a2, 0)); | 405 __ lhu(t0, MemOperand(a2, 0)); |
375 __ addiu(a2, a2, char_size()); | 406 __ addiu(a2, a2, char_size()); |
376 } | 407 } |
377 BranchOrBacktrack(on_no_match, ne, a3, Operand(t0)); | 408 BranchOrBacktrack(on_no_match, ne, a3, Operand(t0)); |
378 __ Branch(&loop, lt, a0, Operand(a1)); | 409 __ Branch(&loop, lt, a0, Operand(a1)); |
379 | 410 |
380 // Move current character position to position after match. | 411 // Move current character position to position after match. |
381 __ Subu(current_input_offset(), a2, end_of_input_address()); | 412 __ Subu(current_input_offset(), a2, end_of_input_address()); |
| 413 if (read_backward) { |
| 414 __ lw(t0, register_location(start_reg)); // Index of start of capture. |
| 415 __ lw(t5, register_location(start_reg + 1)); // Index of end of capture. |
| 416 __ Addu(current_input_offset(), current_input_offset(), Operand(t0)); |
| 417 __ Subu(current_input_offset(), current_input_offset(), Operand(t5)); |
| 418 } |
382 __ bind(&fallthrough); | 419 __ bind(&fallthrough); |
383 } | 420 } |
384 | 421 |
385 | 422 |
386 void RegExpMacroAssemblerMIPS::CheckNotCharacter(uint32_t c, | 423 void RegExpMacroAssemblerMIPS::CheckNotCharacter(uint32_t c, |
387 Label* on_not_equal) { | 424 Label* on_not_equal) { |
388 BranchOrBacktrack(on_not_equal, ne, current_character(), Operand(c)); | 425 BranchOrBacktrack(on_not_equal, ne, current_character(), Operand(c)); |
389 } | 426 } |
390 | 427 |
391 | 428 |
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
592 // Order here should correspond to order of offset constants in header file. | 629 // Order here should correspond to order of offset constants in header file. |
593 RegList registers_to_retain = s0.bit() | s1.bit() | s2.bit() | | 630 RegList registers_to_retain = s0.bit() | s1.bit() | s2.bit() | |
594 s3.bit() | s4.bit() | s5.bit() | s6.bit() | s7.bit() | fp.bit(); | 631 s3.bit() | s4.bit() | s5.bit() | s6.bit() | s7.bit() | fp.bit(); |
595 RegList argument_registers = a0.bit() | a1.bit() | a2.bit() | a3.bit(); | 632 RegList argument_registers = a0.bit() | a1.bit() | a2.bit() | a3.bit(); |
596 __ MultiPush(argument_registers | registers_to_retain | ra.bit()); | 633 __ MultiPush(argument_registers | registers_to_retain | ra.bit()); |
597 // Set frame pointer in space for it if this is not a direct call | 634 // Set frame pointer in space for it if this is not a direct call |
598 // from generated code. | 635 // from generated code. |
599 __ Addu(frame_pointer(), sp, Operand(4 * kPointerSize)); | 636 __ Addu(frame_pointer(), sp, Operand(4 * kPointerSize)); |
600 __ mov(a0, zero_reg); | 637 __ mov(a0, zero_reg); |
601 __ push(a0); // Make room for success counter and initialize it to 0. | 638 __ push(a0); // Make room for success counter and initialize it to 0. |
602 __ push(a0); // Make room for "position - 1" constant (value irrelevant). | 639 __ push(a0); // Make room for "string start - 1" constant. |
603 | 640 |
604 // Check if we have space on the stack for registers. | 641 // Check if we have space on the stack for registers. |
605 Label stack_limit_hit; | 642 Label stack_limit_hit; |
606 Label stack_ok; | 643 Label stack_ok; |
607 | 644 |
608 ExternalReference stack_limit = | 645 ExternalReference stack_limit = |
609 ExternalReference::address_of_stack_limit(masm_->isolate()); | 646 ExternalReference::address_of_stack_limit(masm_->isolate()); |
610 __ li(a0, Operand(stack_limit)); | 647 __ li(a0, Operand(stack_limit)); |
611 __ lw(a0, MemOperand(a0)); | 648 __ lw(a0, MemOperand(a0)); |
612 __ Subu(a0, sp, a0); | 649 __ Subu(a0, sp, a0); |
(...skipping 22 matching lines...) Expand all Loading... |
635 // Find negative length (offset of start relative to end). | 672 // Find negative length (offset of start relative to end). |
636 __ Subu(current_input_offset(), a0, end_of_input_address()); | 673 __ Subu(current_input_offset(), a0, end_of_input_address()); |
637 // Set a0 to address of char before start of the input string | 674 // Set a0 to address of char before start of the input string |
638 // (effectively string position -1). | 675 // (effectively string position -1). |
639 __ lw(a1, MemOperand(frame_pointer(), kStartIndex)); | 676 __ lw(a1, MemOperand(frame_pointer(), kStartIndex)); |
640 __ Subu(a0, current_input_offset(), Operand(char_size())); | 677 __ Subu(a0, current_input_offset(), Operand(char_size())); |
641 __ sll(t5, a1, (mode_ == UC16) ? 1 : 0); | 678 __ sll(t5, a1, (mode_ == UC16) ? 1 : 0); |
642 __ Subu(a0, a0, t5); | 679 __ Subu(a0, a0, t5); |
643 // Store this value in a local variable, for use when clearing | 680 // Store this value in a local variable, for use when clearing |
644 // position registers. | 681 // position registers. |
645 __ sw(a0, MemOperand(frame_pointer(), kInputStartMinusOne)); | 682 __ sw(a0, MemOperand(frame_pointer(), kStringStartMinusOne)); |
646 | 683 |
647 // Initialize code pointer register | 684 // Initialize code pointer register |
648 __ li(code_pointer(), Operand(masm_->CodeObject()), CONSTANT_SIZE); | 685 __ li(code_pointer(), Operand(masm_->CodeObject()), CONSTANT_SIZE); |
649 | 686 |
650 Label load_char_start_regexp, start_regexp; | 687 Label load_char_start_regexp, start_regexp; |
651 // Load newline if index is at start, previous character otherwise. | 688 // Load newline if index is at start, previous character otherwise. |
652 __ Branch(&load_char_start_regexp, ne, a1, Operand(zero_reg)); | 689 __ Branch(&load_char_start_regexp, ne, a1, Operand(zero_reg)); |
653 __ li(current_character(), Operand('\n')); | 690 __ li(current_character(), Operand('\n')); |
654 __ jmp(&start_regexp); | 691 __ jmp(&start_regexp); |
655 | 692 |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
744 // Check whether we have enough room for another set of capture results. | 781 // Check whether we have enough room for another set of capture results. |
745 __ mov(v0, a0); | 782 __ mov(v0, a0); |
746 __ Branch(&return_v0, lt, a1, Operand(num_saved_registers_)); | 783 __ Branch(&return_v0, lt, a1, Operand(num_saved_registers_)); |
747 | 784 |
748 __ sw(a1, MemOperand(frame_pointer(), kNumOutputRegisters)); | 785 __ sw(a1, MemOperand(frame_pointer(), kNumOutputRegisters)); |
749 // Advance the location for output. | 786 // Advance the location for output. |
750 __ Addu(a2, a2, num_saved_registers_ * kPointerSize); | 787 __ Addu(a2, a2, num_saved_registers_ * kPointerSize); |
751 __ sw(a2, MemOperand(frame_pointer(), kRegisterOutput)); | 788 __ sw(a2, MemOperand(frame_pointer(), kRegisterOutput)); |
752 | 789 |
753 // Prepare a0 to initialize registers with its value in the next run. | 790 // Prepare a0 to initialize registers with its value in the next run. |
754 __ lw(a0, MemOperand(frame_pointer(), kInputStartMinusOne)); | 791 __ lw(a0, MemOperand(frame_pointer(), kStringStartMinusOne)); |
755 | 792 |
756 if (global_with_zero_length_check()) { | 793 if (global_with_zero_length_check()) { |
757 // Special case for zero-length matches. | 794 // Special case for zero-length matches. |
758 // t7: capture start index | 795 // t7: capture start index |
759 // Not a zero-length match, restart. | 796 // Not a zero-length match, restart. |
760 __ Branch( | 797 __ Branch( |
761 &load_char_start_regexp, ne, current_input_offset(), Operand(t7)); | 798 &load_char_start_regexp, ne, current_input_offset(), Operand(t7)); |
762 // Offset from the end is zero if we already reached the end. | 799 // Offset from the end is zero if we already reached the end. |
763 __ Branch(&exit_label_, eq, current_input_offset(), | 800 __ Branch(&exit_label_, eq, current_input_offset(), |
764 Operand(zero_reg)); | 801 Operand(zero_reg)); |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
898 RegExpMacroAssembler::IrregexpImplementation | 935 RegExpMacroAssembler::IrregexpImplementation |
899 RegExpMacroAssemblerMIPS::Implementation() { | 936 RegExpMacroAssemblerMIPS::Implementation() { |
900 return kMIPSImplementation; | 937 return kMIPSImplementation; |
901 } | 938 } |
902 | 939 |
903 | 940 |
904 void RegExpMacroAssemblerMIPS::LoadCurrentCharacter(int cp_offset, | 941 void RegExpMacroAssemblerMIPS::LoadCurrentCharacter(int cp_offset, |
905 Label* on_end_of_input, | 942 Label* on_end_of_input, |
906 bool check_bounds, | 943 bool check_bounds, |
907 int characters) { | 944 int characters) { |
908 DCHECK(cp_offset >= -1); // ^ and \b can look behind one character. | |
909 DCHECK(cp_offset < (1<<30)); // Be sane! (And ensure negation works). | 945 DCHECK(cp_offset < (1<<30)); // Be sane! (And ensure negation works). |
910 if (check_bounds) { | 946 if (check_bounds) { |
911 CheckPosition(cp_offset + characters - 1, on_end_of_input); | 947 if (cp_offset >= 0) { |
| 948 CheckPosition(cp_offset + characters - 1, on_end_of_input); |
| 949 } else { |
| 950 CheckPosition(cp_offset, on_end_of_input); |
| 951 } |
912 } | 952 } |
913 LoadCurrentCharacterUnchecked(cp_offset, characters); | 953 LoadCurrentCharacterUnchecked(cp_offset, characters); |
914 } | 954 } |
915 | 955 |
916 | 956 |
917 void RegExpMacroAssemblerMIPS::PopCurrentPosition() { | 957 void RegExpMacroAssemblerMIPS::PopCurrentPosition() { |
918 Pop(current_input_offset()); | 958 Pop(current_input_offset()); |
919 } | 959 } |
920 | 960 |
921 | 961 |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1009 __ sw(current_input_offset(), register_location(reg)); | 1049 __ sw(current_input_offset(), register_location(reg)); |
1010 } else { | 1050 } else { |
1011 __ Addu(a0, current_input_offset(), Operand(cp_offset * char_size())); | 1051 __ Addu(a0, current_input_offset(), Operand(cp_offset * char_size())); |
1012 __ sw(a0, register_location(reg)); | 1052 __ sw(a0, register_location(reg)); |
1013 } | 1053 } |
1014 } | 1054 } |
1015 | 1055 |
1016 | 1056 |
1017 void RegExpMacroAssemblerMIPS::ClearRegisters(int reg_from, int reg_to) { | 1057 void RegExpMacroAssemblerMIPS::ClearRegisters(int reg_from, int reg_to) { |
1018 DCHECK(reg_from <= reg_to); | 1058 DCHECK(reg_from <= reg_to); |
1019 __ lw(a0, MemOperand(frame_pointer(), kInputStartMinusOne)); | 1059 __ lw(a0, MemOperand(frame_pointer(), kStringStartMinusOne)); |
1020 for (int reg = reg_from; reg <= reg_to; reg++) { | 1060 for (int reg = reg_from; reg <= reg_to; reg++) { |
1021 __ sw(a0, register_location(reg)); | 1061 __ sw(a0, register_location(reg)); |
1022 } | 1062 } |
1023 } | 1063 } |
1024 | 1064 |
1025 | 1065 |
1026 void RegExpMacroAssemblerMIPS::WriteStackPointerToRegister(int reg) { | 1066 void RegExpMacroAssemblerMIPS::WriteStackPointerToRegister(int reg) { |
1027 __ lw(a1, MemOperand(frame_pointer(), kStackHighEnd)); | 1067 __ lw(a1, MemOperand(frame_pointer(), kStackHighEnd)); |
1028 __ Subu(a0, backtrack_stackpointer(), a1); | 1068 __ Subu(a0, backtrack_stackpointer(), a1); |
1029 __ sw(a0, register_location(reg)); | 1069 __ sw(a0, register_location(reg)); |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1122 if (num_registers_ <= register_index) { | 1162 if (num_registers_ <= register_index) { |
1123 num_registers_ = register_index + 1; | 1163 num_registers_ = register_index + 1; |
1124 } | 1164 } |
1125 return MemOperand(frame_pointer(), | 1165 return MemOperand(frame_pointer(), |
1126 kRegisterZero - register_index * kPointerSize); | 1166 kRegisterZero - register_index * kPointerSize); |
1127 } | 1167 } |
1128 | 1168 |
1129 | 1169 |
1130 void RegExpMacroAssemblerMIPS::CheckPosition(int cp_offset, | 1170 void RegExpMacroAssemblerMIPS::CheckPosition(int cp_offset, |
1131 Label* on_outside_input) { | 1171 Label* on_outside_input) { |
1132 BranchOrBacktrack(on_outside_input, | 1172 if (cp_offset >= 0) { |
1133 ge, | 1173 BranchOrBacktrack(on_outside_input, ge, current_input_offset(), |
1134 current_input_offset(), | 1174 Operand(-cp_offset * char_size())); |
1135 Operand(-cp_offset * char_size())); | 1175 } else { |
| 1176 __ lw(a1, MemOperand(frame_pointer(), kStringStartMinusOne)); |
| 1177 __ Addu(a0, current_input_offset(), Operand(cp_offset * char_size())); |
| 1178 BranchOrBacktrack(on_outside_input, le, a0, Operand(a1)); |
| 1179 } |
1136 } | 1180 } |
1137 | 1181 |
1138 | 1182 |
1139 void RegExpMacroAssemblerMIPS::BranchOrBacktrack(Label* to, | 1183 void RegExpMacroAssemblerMIPS::BranchOrBacktrack(Label* to, |
1140 Condition condition, | 1184 Condition condition, |
1141 Register rs, | 1185 Register rs, |
1142 const Operand& rt) { | 1186 const Operand& rt) { |
1143 if (condition == al) { // Unconditional. | 1187 if (condition == al) { // Unconditional. |
1144 if (to == NULL) { | 1188 if (to == NULL) { |
1145 Backtrack(); | 1189 Backtrack(); |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1236 | 1280 |
1237 | 1281 |
1238 #undef __ | 1282 #undef __ |
1239 | 1283 |
1240 #endif // V8_INTERPRETED_REGEXP | 1284 #endif // V8_INTERPRETED_REGEXP |
1241 | 1285 |
1242 } // namespace internal | 1286 } // namespace internal |
1243 } // namespace v8 | 1287 } // namespace v8 |
1244 | 1288 |
1245 #endif // V8_TARGET_ARCH_MIPS | 1289 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |