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