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_ARM | 5 #if V8_TARGET_ARCH_ARM |
6 | 6 |
7 #include "src/regexp/arm/regexp-macro-assembler-arm.h" | 7 #include "src/regexp/arm/regexp-macro-assembler-arm.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 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
51 * - fp[32] return address (lr). | 51 * - fp[32] return address (lr). |
52 * - fp[28] old frame pointer (r11). | 52 * - fp[28] old frame pointer (r11). |
53 * - fp[0..24] backup of registers r4..r10. | 53 * - fp[0..24] backup of registers r4..r10. |
54 * --- frame pointer ---- | 54 * --- frame pointer ---- |
55 * - fp[-4] end of input (address of end of string). | 55 * - fp[-4] end of input (address of end of string). |
56 * - fp[-8] start of input (address of first character in string). | 56 * - fp[-8] start of input (address of first character in string). |
57 * - fp[-12] start index (character index of start). | 57 * - fp[-12] start index (character index of start). |
58 * - fp[-16] void* input_string (location of a handle containing the string). | 58 * - fp[-16] void* input_string (location of a handle containing the string). |
59 * - fp[-20] success counter (only for global regexps to count matches). | 59 * - fp[-20] success counter (only for global regexps to count matches). |
60 * - fp[-24] Offset of location before start of input (effectively character | 60 * - fp[-24] Offset of location before start of input (effectively character |
61 * position -1). Used to initialize capture registers to a | 61 * string start - 1). Used to initialize capture registers to a |
62 * non-position. | 62 * non-position. |
63 * - fp[-28] At start (if 1, we are starting at the start of the | 63 * - fp[-28] At start (if 1, we are starting at the start of the |
64 * string, otherwise 0) | 64 * string, otherwise 0) |
65 * - fp[-32] register 0 (Only positions must be stored in the first | 65 * - fp[-32] register 0 (Only positions must be stored in the first |
66 * - register 1 num_saved_registers_ registers) | 66 * - register 1 num_saved_registers_ registers) |
67 * - ... | 67 * - ... |
68 * - register num_registers-1 | 68 * - register num_registers-1 |
69 * --- sp --- | 69 * --- sp --- |
70 * | 70 * |
71 * The first num_saved_registers_ registers are initialized to point to | 71 * The first num_saved_registers_ registers are initialized to point to |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
169 } | 169 } |
170 | 170 |
171 | 171 |
172 void RegExpMacroAssemblerARM::CheckCharacterGT(uc16 limit, Label* on_greater) { | 172 void RegExpMacroAssemblerARM::CheckCharacterGT(uc16 limit, Label* on_greater) { |
173 __ cmp(current_character(), Operand(limit)); | 173 __ cmp(current_character(), Operand(limit)); |
174 BranchOrBacktrack(gt, on_greater); | 174 BranchOrBacktrack(gt, on_greater); |
175 } | 175 } |
176 | 176 |
177 | 177 |
178 void RegExpMacroAssemblerARM::CheckAtStart(Label* on_at_start) { | 178 void RegExpMacroAssemblerARM::CheckAtStart(Label* on_at_start) { |
179 Label not_at_start; | 179 __ ldr(r1, MemOperand(frame_pointer(), kStringStartMinusOne)); |
180 // Did we start the match at the start of the string at all? | 180 __ add(r0, current_input_offset(), Operand(-char_size())); |
181 __ ldr(r0, MemOperand(frame_pointer(), kStartIndex)); | |
182 __ cmp(r0, Operand::Zero()); | |
183 BranchOrBacktrack(ne, ¬_at_start); | |
184 | |
185 // If we did, are we still at the start of the input? | |
186 __ ldr(r1, MemOperand(frame_pointer(), kInputStart)); | |
187 __ add(r0, end_of_input_address(), Operand(current_input_offset())); | |
188 __ cmp(r0, r1); | 181 __ cmp(r0, r1); |
189 BranchOrBacktrack(eq, on_at_start); | 182 BranchOrBacktrack(eq, on_at_start); |
190 __ bind(¬_at_start); | |
191 } | 183 } |
192 | 184 |
193 | 185 |
194 void RegExpMacroAssemblerARM::CheckNotAtStart(Label* on_not_at_start) { | 186 void RegExpMacroAssemblerARM::CheckNotAtStart(int cp_offset, |
195 // Did we start the match at the start of the string at all? | 187 Label* on_not_at_start) { |
196 __ ldr(r0, MemOperand(frame_pointer(), kStartIndex)); | 188 __ ldr(r1, MemOperand(frame_pointer(), kStringStartMinusOne)); |
197 __ cmp(r0, Operand::Zero()); | 189 __ add(r0, current_input_offset(), |
198 BranchOrBacktrack(ne, on_not_at_start); | 190 Operand(-char_size() + cp_offset * char_size())); |
199 // If we did, are we still at the start of the input? | |
200 __ ldr(r1, MemOperand(frame_pointer(), kInputStart)); | |
201 __ add(r0, end_of_input_address(), Operand(current_input_offset())); | |
202 __ cmp(r0, r1); | 191 __ cmp(r0, r1); |
203 BranchOrBacktrack(ne, on_not_at_start); | 192 BranchOrBacktrack(ne, on_not_at_start); |
204 } | 193 } |
205 | 194 |
206 | 195 |
207 void RegExpMacroAssemblerARM::CheckCharacterLT(uc16 limit, Label* on_less) { | 196 void RegExpMacroAssemblerARM::CheckCharacterLT(uc16 limit, Label* on_less) { |
208 __ cmp(current_character(), Operand(limit)); | 197 __ cmp(current_character(), Operand(limit)); |
209 BranchOrBacktrack(lt, on_less); | 198 BranchOrBacktrack(lt, on_less); |
210 } | 199 } |
211 | 200 |
212 | 201 |
213 void RegExpMacroAssemblerARM::CheckGreedyLoop(Label* on_equal) { | 202 void RegExpMacroAssemblerARM::CheckGreedyLoop(Label* on_equal) { |
214 __ ldr(r0, MemOperand(backtrack_stackpointer(), 0)); | 203 __ ldr(r0, MemOperand(backtrack_stackpointer(), 0)); |
215 __ cmp(current_input_offset(), r0); | 204 __ cmp(current_input_offset(), r0); |
216 __ add(backtrack_stackpointer(), | 205 __ add(backtrack_stackpointer(), |
217 backtrack_stackpointer(), Operand(kPointerSize), LeaveCC, eq); | 206 backtrack_stackpointer(), Operand(kPointerSize), LeaveCC, eq); |
218 BranchOrBacktrack(eq, on_equal); | 207 BranchOrBacktrack(eq, on_equal); |
219 } | 208 } |
220 | 209 |
221 | 210 |
222 void RegExpMacroAssemblerARM::CheckNotBackReferenceIgnoreCase( | 211 void RegExpMacroAssemblerARM::CheckNotBackReferenceIgnoreCase( |
223 int start_reg, | 212 int start_reg, bool read_backward, Label* on_no_match) { |
224 Label* on_no_match) { | |
225 Label fallthrough; | 213 Label fallthrough; |
226 __ ldr(r0, register_location(start_reg)); // Index of start of capture | 214 __ ldr(r0, register_location(start_reg)); // Index of start of capture |
227 __ ldr(r1, register_location(start_reg + 1)); // Index of end of capture | 215 __ ldr(r1, register_location(start_reg + 1)); // Index of end of capture |
228 __ sub(r1, r1, r0, SetCC); // Length of capture. | 216 __ sub(r1, r1, r0, SetCC); // Length of capture. |
erikcorry
2015/11/16 14:55:39
If it's a capture in a backwards section, I think
Yang
2015/11/17 09:24:28
I checked, and you are right. This can happen. But
| |
229 | 217 |
230 // If length is zero, either the capture is empty or it is not participating. | 218 // The length of the capture can only be negative if the end of the |
231 // In either case succeed immediately. | 219 // capture is not yet recorded. If the length is zero, the capture is |
232 __ b(eq, &fallthrough); | 220 // either empty or uncaptured. In either of those cases, succeed. |
221 __ b(le, &fallthrough); | |
233 | 222 |
234 // Check that there are enough characters left in the input. | 223 // Check that there are enough characters left in the input. |
235 __ cmn(r1, Operand(current_input_offset())); | 224 if (read_backward) { |
236 BranchOrBacktrack(gt, on_no_match); | 225 __ ldr(r3, MemOperand(frame_pointer(), kStringStartMinusOne)); |
226 __ sub(r2, current_input_offset(), r1); | |
erikcorry
2015/11/16 14:55:39
For (?<=\1(.*))
The length can be very big and th
Yang
2015/11/17 09:24:28
Nice catch.
I changed this so that we add the cap
| |
227 __ cmp(r2, r3); | |
228 BranchOrBacktrack(le, on_no_match); | |
229 } else { | |
230 __ cmn(r1, Operand(current_input_offset())); | |
231 BranchOrBacktrack(gt, on_no_match); | |
232 } | |
237 | 233 |
238 if (mode_ == LATIN1) { | 234 if (mode_ == LATIN1) { |
239 Label success; | 235 Label success; |
240 Label fail; | 236 Label fail; |
241 Label loop_check; | 237 Label loop_check; |
242 | 238 |
243 // r0 - offset of start of capture | 239 // r0 - offset of start of capture |
244 // r1 - length of capture | 240 // r1 - length of capture |
245 __ add(r0, r0, Operand(end_of_input_address())); | 241 __ add(r0, r0, end_of_input_address()); |
246 __ add(r2, end_of_input_address(), Operand(current_input_offset())); | 242 __ add(r2, end_of_input_address(), current_input_offset()); |
247 __ add(r1, r0, Operand(r1)); | 243 if (read_backward) { |
244 __ sub(r2, r2, r1); // Offset by length when matching backwards. | |
245 } | |
246 __ add(r1, r0, r1); | |
248 | 247 |
249 // r0 - Address of start of capture. | 248 // r0 - Address of start of capture. |
250 // r1 - Address of end of capture | 249 // r1 - Address of end of capture |
251 // r2 - Address of current input position. | 250 // r2 - Address of current input position. |
252 | 251 |
253 Label loop; | 252 Label loop; |
254 __ bind(&loop); | 253 __ bind(&loop); |
255 __ ldrb(r3, MemOperand(r0, char_size(), PostIndex)); | 254 __ ldrb(r3, MemOperand(r0, char_size(), PostIndex)); |
256 __ ldrb(r4, MemOperand(r2, char_size(), PostIndex)); | 255 __ ldrb(r4, MemOperand(r2, char_size(), PostIndex)); |
257 __ cmp(r4, r3); | 256 __ cmp(r4, r3); |
(...skipping 18 matching lines...) Expand all Loading... | |
276 __ cmp(r0, r1); | 275 __ cmp(r0, r1); |
277 __ b(lt, &loop); | 276 __ b(lt, &loop); |
278 __ jmp(&success); | 277 __ jmp(&success); |
279 | 278 |
280 __ bind(&fail); | 279 __ bind(&fail); |
281 BranchOrBacktrack(al, on_no_match); | 280 BranchOrBacktrack(al, on_no_match); |
282 | 281 |
283 __ bind(&success); | 282 __ bind(&success); |
284 // Compute new value of character position after the matched part. | 283 // Compute new value of character position after the matched part. |
285 __ sub(current_input_offset(), r2, end_of_input_address()); | 284 __ sub(current_input_offset(), r2, end_of_input_address()); |
285 if (read_backward) { | |
286 __ ldr(r0, register_location(start_reg)); // Index of start of capture | |
287 __ ldr(r1, register_location(start_reg + 1)); // Index of end of capture | |
288 __ add(current_input_offset(), current_input_offset(), r0); | |
289 __ sub(current_input_offset(), current_input_offset(), r1); | |
290 } | |
286 } else { | 291 } else { |
287 DCHECK(mode_ == UC16); | 292 DCHECK(mode_ == UC16); |
288 int argument_count = 4; | 293 int argument_count = 4; |
289 __ PrepareCallCFunction(argument_count, r2); | 294 __ PrepareCallCFunction(argument_count, r2); |
290 | 295 |
291 // r0 - offset of start of capture | 296 // r0 - offset of start of capture |
292 // r1 - length of capture | 297 // r1 - length of capture |
293 | 298 |
294 // Put arguments into arguments registers. | 299 // Put arguments into arguments registers. |
295 // Parameters are | 300 // Parameters are |
296 // r0: Address byte_offset1 - Address captured substring's start. | 301 // r0: Address byte_offset1 - Address captured substring's start. |
297 // r1: Address byte_offset2 - Address of current character position. | 302 // r1: Address byte_offset2 - Address of current character position. |
298 // r2: size_t byte_length - length of capture in bytes(!) | 303 // r2: size_t byte_length - length of capture in bytes(!) |
299 // r3: Isolate* isolate | 304 // r3: Isolate* isolate |
300 | 305 |
301 // Address of start of capture. | 306 // Address of start of capture. |
302 __ add(r0, r0, Operand(end_of_input_address())); | 307 __ add(r0, r0, Operand(end_of_input_address())); |
303 // Length of capture. | 308 // Length of capture. |
304 __ mov(r2, Operand(r1)); | 309 __ mov(r2, Operand(r1)); |
305 // Save length in callee-save register for use on return. | 310 // Save length in callee-save register for use on return. |
306 __ mov(r4, Operand(r1)); | 311 __ mov(r4, Operand(r1)); |
307 // Address of current input position. | 312 // Address of current input position. |
308 __ add(r1, current_input_offset(), Operand(end_of_input_address())); | 313 __ add(r1, current_input_offset(), end_of_input_address()); |
314 if (read_backward) { | |
315 __ sub(r1, r1, r4); | |
316 } | |
309 // Isolate. | 317 // Isolate. |
310 __ mov(r3, Operand(ExternalReference::isolate_address(isolate()))); | 318 __ mov(r3, Operand(ExternalReference::isolate_address(isolate()))); |
311 | 319 |
312 { | 320 { |
313 AllowExternalCallThatCantCauseGC scope(masm_); | 321 AllowExternalCallThatCantCauseGC scope(masm_); |
314 ExternalReference function = | 322 ExternalReference function = |
315 ExternalReference::re_case_insensitive_compare_uc16(isolate()); | 323 ExternalReference::re_case_insensitive_compare_uc16(isolate()); |
316 __ CallCFunction(function, argument_count); | 324 __ CallCFunction(function, argument_count); |
317 } | 325 } |
318 | 326 |
319 // Check if function returned non-zero for success or zero for failure. | 327 // Check if function returned non-zero for success or zero for failure. |
320 __ cmp(r0, Operand::Zero()); | 328 __ cmp(r0, Operand::Zero()); |
321 BranchOrBacktrack(eq, on_no_match); | 329 BranchOrBacktrack(eq, on_no_match); |
322 // On success, increment position by length of capture. | 330 |
323 __ add(current_input_offset(), current_input_offset(), Operand(r4)); | 331 // On success, advance position by length of capture. |
332 if (read_backward) { | |
333 __ sub(current_input_offset(), current_input_offset(), r4); | |
334 } else { | |
335 __ add(current_input_offset(), current_input_offset(), r4); | |
336 } | |
324 } | 337 } |
325 | 338 |
326 __ bind(&fallthrough); | 339 __ bind(&fallthrough); |
327 } | 340 } |
328 | 341 |
329 | 342 |
330 void RegExpMacroAssemblerARM::CheckNotBackReference( | 343 void RegExpMacroAssemblerARM::CheckNotBackReference(int start_reg, |
331 int start_reg, | 344 bool read_backward, |
332 Label* on_no_match) { | 345 Label* on_no_match) { |
333 Label fallthrough; | 346 Label fallthrough; |
334 Label success; | 347 Label success; |
335 | 348 |
336 // Find length of back-referenced capture. | 349 // Find length of back-referenced capture. |
337 __ ldr(r0, register_location(start_reg)); | 350 __ ldr(r0, register_location(start_reg)); |
338 __ ldr(r1, register_location(start_reg + 1)); | 351 __ ldr(r1, register_location(start_reg + 1)); |
339 __ sub(r1, r1, r0, SetCC); // Length to check. | 352 __ sub(r1, r1, r0, SetCC); // Length to check. |
340 // Succeed on empty capture (including no capture). | 353 |
341 __ b(eq, &fallthrough); | 354 // The length of the capture can only be negative if the end of the |
355 // capture is not yet recorded. If the length is zero, the capture is | |
356 // either empty or uncaptured. In either of those cases, succeed. | |
357 __ b(le, &fallthrough); | |
342 | 358 |
343 // Check that there are enough characters left in the input. | 359 // Check that there are enough characters left in the input. |
344 __ cmn(r1, Operand(current_input_offset())); | 360 if (read_backward) { |
345 BranchOrBacktrack(gt, on_no_match); | 361 __ ldr(r3, MemOperand(frame_pointer(), kStringStartMinusOne)); |
362 __ sub(r2, current_input_offset(), r1); | |
363 __ cmp(r2, r3); | |
364 BranchOrBacktrack(lt, on_no_match); | |
365 } else { | |
366 __ cmn(r1, Operand(current_input_offset())); | |
367 BranchOrBacktrack(gt, on_no_match); | |
368 } | |
346 | 369 |
347 // Compute pointers to match string and capture string | 370 // r0 - offset of start of capture |
348 __ add(r0, r0, Operand(end_of_input_address())); | 371 // r1 - length of capture |
349 __ add(r2, end_of_input_address(), Operand(current_input_offset())); | 372 __ add(r0, r0, end_of_input_address()); |
350 __ add(r1, r1, Operand(r0)); | 373 __ add(r2, end_of_input_address(), current_input_offset()); |
374 if (read_backward) { | |
375 __ sub(r2, r2, r1); // Offset by length when matching backwards. | |
376 } | |
377 __ add(r1, r0, r1); | |
351 | 378 |
352 Label loop; | 379 Label loop; |
353 __ bind(&loop); | 380 __ bind(&loop); |
354 if (mode_ == LATIN1) { | 381 if (mode_ == LATIN1) { |
355 __ ldrb(r3, MemOperand(r0, char_size(), PostIndex)); | 382 __ ldrb(r3, MemOperand(r0, char_size(), PostIndex)); |
356 __ ldrb(r4, MemOperand(r2, char_size(), PostIndex)); | 383 __ ldrb(r4, MemOperand(r2, char_size(), PostIndex)); |
357 } else { | 384 } else { |
358 DCHECK(mode_ == UC16); | 385 DCHECK(mode_ == UC16); |
359 __ ldrh(r3, MemOperand(r0, char_size(), PostIndex)); | 386 __ ldrh(r3, MemOperand(r0, char_size(), PostIndex)); |
360 __ ldrh(r4, MemOperand(r2, char_size(), PostIndex)); | 387 __ ldrh(r4, MemOperand(r2, char_size(), PostIndex)); |
361 } | 388 } |
362 __ cmp(r3, r4); | 389 __ cmp(r3, r4); |
363 BranchOrBacktrack(ne, on_no_match); | 390 BranchOrBacktrack(ne, on_no_match); |
364 __ cmp(r0, r1); | 391 __ cmp(r0, r1); |
365 __ b(lt, &loop); | 392 __ b(lt, &loop); |
366 | 393 |
367 // Move current character position to position after match. | 394 // Move current character position to position after match. |
368 __ sub(current_input_offset(), r2, end_of_input_address()); | 395 __ sub(current_input_offset(), r2, end_of_input_address()); |
396 if (read_backward) { | |
397 __ ldr(r0, register_location(start_reg)); // Index of start of capture | |
398 __ ldr(r1, register_location(start_reg + 1)); // Index of end of capture | |
399 __ add(current_input_offset(), current_input_offset(), r0); | |
400 __ sub(current_input_offset(), current_input_offset(), r1); | |
401 } | |
402 | |
369 __ bind(&fallthrough); | 403 __ bind(&fallthrough); |
370 } | 404 } |
371 | 405 |
372 | 406 |
373 void RegExpMacroAssemblerARM::CheckNotCharacter(unsigned c, | 407 void RegExpMacroAssemblerARM::CheckNotCharacter(unsigned c, |
374 Label* on_not_equal) { | 408 Label* on_not_equal) { |
375 __ cmp(current_character(), Operand(c)); | 409 __ cmp(current_character(), Operand(c)); |
376 BranchOrBacktrack(ne, on_not_equal); | 410 BranchOrBacktrack(ne, on_not_equal); |
377 } | 411 } |
378 | 412 |
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
596 // Order here should correspond to order of offset constants in header file. | 630 // Order here should correspond to order of offset constants in header file. |
597 RegList registers_to_retain = r4.bit() | r5.bit() | r6.bit() | | 631 RegList registers_to_retain = r4.bit() | r5.bit() | r6.bit() | |
598 r7.bit() | r8.bit() | r9.bit() | r10.bit() | fp.bit(); | 632 r7.bit() | r8.bit() | r9.bit() | r10.bit() | fp.bit(); |
599 RegList argument_registers = r0.bit() | r1.bit() | r2.bit() | r3.bit(); | 633 RegList argument_registers = r0.bit() | r1.bit() | r2.bit() | r3.bit(); |
600 __ stm(db_w, sp, argument_registers | registers_to_retain | lr.bit()); | 634 __ stm(db_w, sp, argument_registers | registers_to_retain | lr.bit()); |
601 // Set frame pointer in space for it if this is not a direct call | 635 // Set frame pointer in space for it if this is not a direct call |
602 // from generated code. | 636 // from generated code. |
603 __ add(frame_pointer(), sp, Operand(4 * kPointerSize)); | 637 __ add(frame_pointer(), sp, Operand(4 * kPointerSize)); |
604 __ mov(r0, Operand::Zero()); | 638 __ mov(r0, Operand::Zero()); |
605 __ push(r0); // Make room for success counter and initialize it to 0. | 639 __ push(r0); // Make room for success counter and initialize it to 0. |
606 __ push(r0); // Make room for "position - 1" constant (value is irrelevant). | 640 __ push(r0); // Make room for "string start - 1" constant. |
607 // Check if we have space on the stack for registers. | 641 // Check if we have space on the stack for registers. |
608 Label stack_limit_hit; | 642 Label stack_limit_hit; |
609 Label stack_ok; | 643 Label stack_ok; |
610 | 644 |
611 ExternalReference stack_limit = | 645 ExternalReference stack_limit = |
612 ExternalReference::address_of_stack_limit(isolate()); | 646 ExternalReference::address_of_stack_limit(isolate()); |
613 __ mov(r0, Operand(stack_limit)); | 647 __ mov(r0, Operand(stack_limit)); |
614 __ ldr(r0, MemOperand(r0)); | 648 __ ldr(r0, MemOperand(r0)); |
615 __ sub(r0, sp, r0, SetCC); | 649 __ sub(r0, sp, r0, SetCC); |
616 // Handle it if the stack pointer is already below the stack limit. | 650 // Handle it if the stack pointer is already below the stack limit. |
(...skipping 23 matching lines...) Expand all Loading... | |
640 __ ldr(r0, MemOperand(frame_pointer(), kInputStart)); | 674 __ ldr(r0, MemOperand(frame_pointer(), kInputStart)); |
641 // Find negative length (offset of start relative to end). | 675 // Find negative length (offset of start relative to end). |
642 __ sub(current_input_offset(), r0, end_of_input_address()); | 676 __ sub(current_input_offset(), r0, end_of_input_address()); |
643 // Set r0 to address of char before start of the input string | 677 // Set r0 to address of char before start of the input string |
644 // (effectively string position -1). | 678 // (effectively string position -1). |
645 __ ldr(r1, MemOperand(frame_pointer(), kStartIndex)); | 679 __ ldr(r1, MemOperand(frame_pointer(), kStartIndex)); |
646 __ sub(r0, current_input_offset(), Operand(char_size())); | 680 __ sub(r0, current_input_offset(), Operand(char_size())); |
647 __ sub(r0, r0, Operand(r1, LSL, (mode_ == UC16) ? 1 : 0)); | 681 __ sub(r0, r0, Operand(r1, LSL, (mode_ == UC16) ? 1 : 0)); |
648 // Store this value in a local variable, for use when clearing | 682 // Store this value in a local variable, for use when clearing |
649 // position registers. | 683 // position registers. |
650 __ str(r0, MemOperand(frame_pointer(), kInputStartMinusOne)); | 684 __ str(r0, MemOperand(frame_pointer(), kStringStartMinusOne)); |
651 | 685 |
652 // Initialize code pointer register | 686 // Initialize code pointer register |
653 __ mov(code_pointer(), Operand(masm_->CodeObject())); | 687 __ mov(code_pointer(), Operand(masm_->CodeObject())); |
654 | 688 |
655 Label load_char_start_regexp, start_regexp; | 689 Label load_char_start_regexp, start_regexp; |
656 // Load newline if index is at start, previous character otherwise. | 690 // Load newline if index is at start, previous character otherwise. |
657 __ cmp(r1, Operand::Zero()); | 691 __ cmp(r1, Operand::Zero()); |
658 __ b(ne, &load_char_start_regexp); | 692 __ b(ne, &load_char_start_regexp); |
659 __ mov(current_character(), Operand('\n'), LeaveCC, eq); | 693 __ mov(current_character(), Operand('\n'), LeaveCC, eq); |
660 __ jmp(&start_regexp); | 694 __ jmp(&start_regexp); |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
744 // Check whether we have enough room for another set of capture results. | 778 // Check whether we have enough room for another set of capture results. |
745 __ cmp(r1, Operand(num_saved_registers_)); | 779 __ cmp(r1, Operand(num_saved_registers_)); |
746 __ b(lt, &return_r0); | 780 __ b(lt, &return_r0); |
747 | 781 |
748 __ str(r1, MemOperand(frame_pointer(), kNumOutputRegisters)); | 782 __ str(r1, MemOperand(frame_pointer(), kNumOutputRegisters)); |
749 // Advance the location for output. | 783 // Advance the location for output. |
750 __ add(r2, r2, Operand(num_saved_registers_ * kPointerSize)); | 784 __ add(r2, r2, Operand(num_saved_registers_ * kPointerSize)); |
751 __ str(r2, MemOperand(frame_pointer(), kRegisterOutput)); | 785 __ str(r2, MemOperand(frame_pointer(), kRegisterOutput)); |
752 | 786 |
753 // Prepare r0 to initialize registers with its value in the next run. | 787 // Prepare r0 to initialize registers with its value in the next run. |
754 __ ldr(r0, MemOperand(frame_pointer(), kInputStartMinusOne)); | 788 __ ldr(r0, MemOperand(frame_pointer(), kStringStartMinusOne)); |
755 | 789 |
756 if (global_with_zero_length_check()) { | 790 if (global_with_zero_length_check()) { |
757 // Special case for zero-length matches. | 791 // Special case for zero-length matches. |
758 // r4: capture start index | 792 // r4: capture start index |
759 __ cmp(current_input_offset(), r4); | 793 __ cmp(current_input_offset(), r4); |
760 // Not a zero-length match, restart. | 794 // Not a zero-length match, restart. |
761 __ b(ne, &load_char_start_regexp); | 795 __ b(ne, &load_char_start_regexp); |
762 // Offset from the end is zero if we already reached the end. | 796 // Offset from the end is zero if we already reached the end. |
763 __ cmp(current_input_offset(), Operand::Zero()); | 797 __ cmp(current_input_offset(), Operand::Zero()); |
764 __ b(eq, &exit_label_); | 798 __ b(eq, &exit_label_); |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
885 RegExpMacroAssembler::IrregexpImplementation | 919 RegExpMacroAssembler::IrregexpImplementation |
886 RegExpMacroAssemblerARM::Implementation() { | 920 RegExpMacroAssemblerARM::Implementation() { |
887 return kARMImplementation; | 921 return kARMImplementation; |
888 } | 922 } |
889 | 923 |
890 | 924 |
891 void RegExpMacroAssemblerARM::LoadCurrentCharacter(int cp_offset, | 925 void RegExpMacroAssemblerARM::LoadCurrentCharacter(int cp_offset, |
892 Label* on_end_of_input, | 926 Label* on_end_of_input, |
893 bool check_bounds, | 927 bool check_bounds, |
894 int characters) { | 928 int characters) { |
895 DCHECK(cp_offset >= -1); // ^ and \b can look behind one character. | |
896 DCHECK(cp_offset < (1<<30)); // Be sane! (And ensure negation works) | 929 DCHECK(cp_offset < (1<<30)); // Be sane! (And ensure negation works) |
897 if (check_bounds) { | 930 if (check_bounds) { |
898 CheckPosition(cp_offset + characters - 1, on_end_of_input); | 931 if (cp_offset >= 0) { |
932 CheckPosition(cp_offset + characters - 1, on_end_of_input); | |
933 } else { | |
934 CheckPosition(cp_offset, on_end_of_input); | |
935 } | |
899 } | 936 } |
900 LoadCurrentCharacterUnchecked(cp_offset, characters); | 937 LoadCurrentCharacterUnchecked(cp_offset, characters); |
901 } | 938 } |
902 | 939 |
903 | 940 |
904 void RegExpMacroAssemblerARM::PopCurrentPosition() { | 941 void RegExpMacroAssemblerARM::PopCurrentPosition() { |
905 Pop(current_input_offset()); | 942 Pop(current_input_offset()); |
906 } | 943 } |
907 | 944 |
908 | 945 |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
976 __ str(current_input_offset(), register_location(reg)); | 1013 __ str(current_input_offset(), register_location(reg)); |
977 } else { | 1014 } else { |
978 __ add(r0, current_input_offset(), Operand(cp_offset * char_size())); | 1015 __ add(r0, current_input_offset(), Operand(cp_offset * char_size())); |
979 __ str(r0, register_location(reg)); | 1016 __ str(r0, register_location(reg)); |
980 } | 1017 } |
981 } | 1018 } |
982 | 1019 |
983 | 1020 |
984 void RegExpMacroAssemblerARM::ClearRegisters(int reg_from, int reg_to) { | 1021 void RegExpMacroAssemblerARM::ClearRegisters(int reg_from, int reg_to) { |
985 DCHECK(reg_from <= reg_to); | 1022 DCHECK(reg_from <= reg_to); |
986 __ ldr(r0, MemOperand(frame_pointer(), kInputStartMinusOne)); | 1023 __ ldr(r0, MemOperand(frame_pointer(), kStringStartMinusOne)); |
987 for (int reg = reg_from; reg <= reg_to; reg++) { | 1024 for (int reg = reg_from; reg <= reg_to; reg++) { |
988 __ str(r0, register_location(reg)); | 1025 __ str(r0, register_location(reg)); |
989 } | 1026 } |
990 } | 1027 } |
991 | 1028 |
992 | 1029 |
993 void RegExpMacroAssemblerARM::WriteStackPointerToRegister(int reg) { | 1030 void RegExpMacroAssemblerARM::WriteStackPointerToRegister(int reg) { |
994 __ ldr(r1, MemOperand(frame_pointer(), kStackHighEnd)); | 1031 __ ldr(r1, MemOperand(frame_pointer(), kStackHighEnd)); |
995 __ sub(r0, backtrack_stackpointer(), r1); | 1032 __ sub(r0, backtrack_stackpointer(), r1); |
996 __ str(r0, register_location(reg)); | 1033 __ str(r0, register_location(reg)); |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1062 if (num_registers_ <= register_index) { | 1099 if (num_registers_ <= register_index) { |
1063 num_registers_ = register_index + 1; | 1100 num_registers_ = register_index + 1; |
1064 } | 1101 } |
1065 return MemOperand(frame_pointer(), | 1102 return MemOperand(frame_pointer(), |
1066 kRegisterZero - register_index * kPointerSize); | 1103 kRegisterZero - register_index * kPointerSize); |
1067 } | 1104 } |
1068 | 1105 |
1069 | 1106 |
1070 void RegExpMacroAssemblerARM::CheckPosition(int cp_offset, | 1107 void RegExpMacroAssemblerARM::CheckPosition(int cp_offset, |
1071 Label* on_outside_input) { | 1108 Label* on_outside_input) { |
1072 __ cmp(current_input_offset(), Operand(-cp_offset * char_size())); | 1109 if (cp_offset >= 0) { |
1073 BranchOrBacktrack(ge, on_outside_input); | 1110 __ cmp(current_input_offset(), Operand(-cp_offset * char_size())); |
1111 BranchOrBacktrack(ge, on_outside_input); | |
1112 } else { | |
1113 __ ldr(r1, MemOperand(frame_pointer(), kStringStartMinusOne)); | |
1114 __ add(r0, current_input_offset(), Operand(cp_offset * char_size())); | |
1115 __ cmp(r0, r1); | |
1116 BranchOrBacktrack(le, on_outside_input); | |
1117 } | |
1074 } | 1118 } |
1075 | 1119 |
1076 | 1120 |
1077 void RegExpMacroAssemblerARM::BranchOrBacktrack(Condition condition, | 1121 void RegExpMacroAssemblerARM::BranchOrBacktrack(Condition condition, |
1078 Label* to) { | 1122 Label* to) { |
1079 if (condition == al) { // Unconditional. | 1123 if (condition == al) { // Unconditional. |
1080 if (to == NULL) { | 1124 if (to == NULL) { |
1081 Backtrack(); | 1125 Backtrack(); |
1082 return; | 1126 return; |
1083 } | 1127 } |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1188 | 1232 |
1189 | 1233 |
1190 #undef __ | 1234 #undef __ |
1191 | 1235 |
1192 #endif // V8_INTERPRETED_REGEXP | 1236 #endif // V8_INTERPRETED_REGEXP |
1193 | 1237 |
1194 } // namespace internal | 1238 } // namespace internal |
1195 } // namespace v8 | 1239 } // namespace v8 |
1196 | 1240 |
1197 #endif // V8_TARGET_ARCH_ARM | 1241 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |