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_X64 | 5 #if V8_TARGET_ARCH_X64 |
6 | 6 |
7 #include "src/regexp/x64/regexp-macro-assembler-x64.h" | 7 #include "src/regexp/x64/regexp-macro-assembler-x64.h" |
8 | 8 |
9 #include "src/log.h" | 9 #include "src/log.h" |
10 #include "src/macro-assembler.h" | 10 #include "src/macro-assembler.h" |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
164 } | 164 } |
165 | 165 |
166 | 166 |
167 void RegExpMacroAssemblerX64::CheckCharacterGT(uc16 limit, Label* on_greater) { | 167 void RegExpMacroAssemblerX64::CheckCharacterGT(uc16 limit, Label* on_greater) { |
168 __ cmpl(current_character(), Immediate(limit)); | 168 __ cmpl(current_character(), Immediate(limit)); |
169 BranchOrBacktrack(greater, on_greater); | 169 BranchOrBacktrack(greater, on_greater); |
170 } | 170 } |
171 | 171 |
172 | 172 |
173 void RegExpMacroAssemblerX64::CheckAtStart(Label* on_at_start) { | 173 void RegExpMacroAssemblerX64::CheckAtStart(Label* on_at_start) { |
174 Label not_at_start; | |
175 // Did we start the match at the start of the string at all? | |
176 __ cmpl(Operand(rbp, kStartIndex), Immediate(0)); | |
177 BranchOrBacktrack(not_equal, ¬_at_start); | |
178 // If we did, are we still at the start of the input? | |
179 __ leap(rax, Operand(rsi, rdi, times_1, 0)); | 174 __ leap(rax, Operand(rsi, rdi, times_1, 0)); |
| 175 for (int i = 0; i < char_size(); i++) { |
| 176 __ addp(rax, Operand(rbp, kStartIndex)); |
| 177 } |
180 __ cmpp(rax, Operand(rbp, kInputStart)); | 178 __ cmpp(rax, Operand(rbp, kInputStart)); |
181 BranchOrBacktrack(equal, on_at_start); | 179 BranchOrBacktrack(equal, on_at_start); |
182 __ bind(¬_at_start); | |
183 } | 180 } |
184 | 181 |
185 | 182 |
186 void RegExpMacroAssemblerX64::CheckNotAtStart(Label* on_not_at_start) { | 183 void RegExpMacroAssemblerX64::CheckNotAtStart(int cp_offset, |
187 // Did we start the match at the start of the string at all? | 184 Label* on_not_at_start) { |
188 __ cmpl(Operand(rbp, kStartIndex), Immediate(0)); | 185 __ leap(rax, Operand(rsi, rdi, times_1, cp_offset * char_size())); |
189 BranchOrBacktrack(not_equal, on_not_at_start); | 186 for (int i = 0; i < char_size(); i++) { |
190 // If we did, are we still at the start of the input? | 187 __ addp(rax, Operand(rbp, kStartIndex)); |
191 __ leap(rax, Operand(rsi, rdi, times_1, 0)); | 188 } |
192 __ cmpp(rax, Operand(rbp, kInputStart)); | 189 __ cmpp(rax, Operand(rbp, kInputStart)); |
193 BranchOrBacktrack(not_equal, on_not_at_start); | 190 BranchOrBacktrack(not_equal, on_not_at_start); |
194 } | 191 } |
195 | 192 |
196 | 193 |
197 void RegExpMacroAssemblerX64::CheckCharacterLT(uc16 limit, Label* on_less) { | 194 void RegExpMacroAssemblerX64::CheckCharacterLT(uc16 limit, Label* on_less) { |
198 __ cmpl(current_character(), Immediate(limit)); | 195 __ cmpl(current_character(), Immediate(limit)); |
199 BranchOrBacktrack(less, on_less); | 196 BranchOrBacktrack(less, on_less); |
200 } | 197 } |
201 | 198 |
202 | 199 |
203 void RegExpMacroAssemblerX64::CheckGreedyLoop(Label* on_equal) { | 200 void RegExpMacroAssemblerX64::CheckGreedyLoop(Label* on_equal) { |
204 Label fallthrough; | 201 Label fallthrough; |
205 __ cmpl(rdi, Operand(backtrack_stackpointer(), 0)); | 202 __ cmpl(rdi, Operand(backtrack_stackpointer(), 0)); |
206 __ j(not_equal, &fallthrough); | 203 __ j(not_equal, &fallthrough); |
207 Drop(); | 204 Drop(); |
208 BranchOrBacktrack(no_condition, on_equal); | 205 BranchOrBacktrack(no_condition, on_equal); |
209 __ bind(&fallthrough); | 206 __ bind(&fallthrough); |
210 } | 207 } |
211 | 208 |
212 | 209 |
213 void RegExpMacroAssemblerX64::CheckNotBackReferenceIgnoreCase( | 210 void RegExpMacroAssemblerX64::CheckNotBackReferenceIgnoreCase( |
214 int start_reg, | 211 int start_reg, bool read_backward, Label* on_no_match) { |
215 Label* on_no_match) { | |
216 Label fallthrough; | 212 Label fallthrough; |
217 ReadPositionFromRegister(rdx, start_reg); // Offset of start of capture | 213 ReadPositionFromRegister(rdx, start_reg); // Offset of start of capture |
218 ReadPositionFromRegister(rbx, start_reg + 1); // Offset of end of capture | 214 ReadPositionFromRegister(rbx, start_reg + 1); // Offset of end of capture |
219 __ subp(rbx, rdx); // Length of capture. | 215 __ subp(rbx, rdx); // Length of capture. |
220 | 216 |
221 // ----------------------- | 217 // ----------------------- |
222 // rdx = Start offset of capture. | 218 // rdx = Start offset of capture. |
223 // rbx = Length of capture | 219 // rbx = Length of capture |
224 | 220 |
225 // If length is negative, this code will fail (it's a symptom of a partial or | 221 // The length of the capture can only be negative if the end of the |
226 // illegal capture where start of capture after end of capture). | 222 // capture is not yet recorded. If the length is zero, the capture is |
227 // This must not happen (no back-reference can reference a capture that wasn't | 223 // either empty or uncaptured. In either of those cases, succeed. |
228 // closed before in the reg-exp, and we must not generate code that can cause | 224 __ j(less_equal, &fallthrough); |
229 // this condition). | |
230 | 225 |
231 // If length is zero, either the capture is empty or it is nonparticipating. | |
232 // In either case succeed immediately. | |
233 __ j(equal, &fallthrough); | |
234 | 226 |
235 // ----------------------- | 227 // ----------------------- |
236 // rdx - Start of capture | 228 // rdx - Start of capture |
237 // rbx - length of capture | 229 // rbx - length of capture |
238 // Check that there are sufficient characters left in the input. | 230 // Check that there are sufficient characters left in the input. |
239 __ movl(rax, rdi); | 231 if (read_backward) { |
240 __ addl(rax, rbx); | 232 __ leap(rax, Operand(rsi, rdi, times_1, 0)); |
241 BranchOrBacktrack(greater, on_no_match); | 233 __ subp(rax, rbx); |
| 234 for (int i = 0; i < char_size(); i++) { |
| 235 __ addp(rax, Operand(rbp, kStartIndex)); |
| 236 } |
| 237 __ cmpp(rax, Operand(rbp, kInputStart)); |
| 238 BranchOrBacktrack(less, on_no_match); |
| 239 } else { |
| 240 __ movl(rax, rdi); |
| 241 __ addl(rax, rbx); |
| 242 BranchOrBacktrack(greater, on_no_match); |
| 243 } |
242 | 244 |
243 if (mode_ == LATIN1) { | 245 if (mode_ == LATIN1) { |
244 Label loop_increment; | 246 Label loop_increment; |
245 if (on_no_match == NULL) { | 247 if (on_no_match == NULL) { |
246 on_no_match = &backtrack_label_; | 248 on_no_match = &backtrack_label_; |
247 } | 249 } |
248 | 250 |
249 __ leap(r9, Operand(rsi, rdx, times_1, 0)); | 251 __ leap(r9, Operand(rsi, rdx, times_1, 0)); |
250 __ leap(r11, Operand(rsi, rdi, times_1, 0)); | 252 __ leap(r11, Operand(rsi, rdi, times_1, 0)); |
| 253 if (read_backward) { |
| 254 __ subp(r11, rbx); // Offset by length when matching backwards. |
| 255 } |
251 __ addp(rbx, r9); // End of capture | 256 __ addp(rbx, r9); // End of capture |
252 // --------------------- | 257 // --------------------- |
253 // r11 - current input character address | 258 // r11 - current input character address |
254 // r9 - current capture character address | 259 // r9 - current capture character address |
255 // rbx - end of capture | 260 // rbx - end of capture |
256 | 261 |
257 Label loop; | 262 Label loop; |
258 __ bind(&loop); | 263 __ bind(&loop); |
259 __ movzxbl(rdx, Operand(r9, 0)); | 264 __ movzxbl(rdx, Operand(r9, 0)); |
260 __ movzxbl(rax, Operand(r11, 0)); | 265 __ movzxbl(rax, Operand(r11, 0)); |
(...skipping 22 matching lines...) Expand all Loading... |
283 // Increment pointers into match and capture strings. | 288 // Increment pointers into match and capture strings. |
284 __ addp(r11, Immediate(1)); | 289 __ addp(r11, Immediate(1)); |
285 __ addp(r9, Immediate(1)); | 290 __ addp(r9, Immediate(1)); |
286 // Compare to end of capture, and loop if not done. | 291 // Compare to end of capture, and loop if not done. |
287 __ cmpp(r9, rbx); | 292 __ cmpp(r9, rbx); |
288 __ j(below, &loop); | 293 __ j(below, &loop); |
289 | 294 |
290 // Compute new value of character position after the matched part. | 295 // Compute new value of character position after the matched part. |
291 __ movp(rdi, r11); | 296 __ movp(rdi, r11); |
292 __ subq(rdi, rsi); | 297 __ subq(rdi, rsi); |
| 298 if (read_backward) { |
| 299 // Subtract match length if we matched backward. |
| 300 __ addq(rdi, register_location(start_reg)); |
| 301 __ subq(rdi, register_location(start_reg + 1)); |
| 302 } |
293 } else { | 303 } else { |
294 DCHECK(mode_ == UC16); | 304 DCHECK(mode_ == UC16); |
295 // Save important/volatile registers before calling C function. | 305 // Save important/volatile registers before calling C function. |
296 #ifndef _WIN64 | 306 #ifndef _WIN64 |
297 // Caller save on Linux and callee save in Windows. | 307 // Caller save on Linux and callee save in Windows. |
298 __ pushq(rsi); | 308 __ pushq(rsi); |
299 __ pushq(rdi); | 309 __ pushq(rdi); |
300 #endif | 310 #endif |
301 __ pushq(backtrack_stackpointer()); | 311 __ pushq(backtrack_stackpointer()); |
302 | 312 |
303 static const int num_arguments = 4; | 313 static const int num_arguments = 4; |
304 __ PrepareCallCFunction(num_arguments); | 314 __ PrepareCallCFunction(num_arguments); |
305 | 315 |
306 // Put arguments into parameter registers. Parameters are | 316 // Put arguments into parameter registers. Parameters are |
307 // Address byte_offset1 - Address captured substring's start. | 317 // Address byte_offset1 - Address captured substring's start. |
308 // Address byte_offset2 - Address of current character position. | 318 // Address byte_offset2 - Address of current character position. |
309 // size_t byte_length - length of capture in bytes(!) | 319 // size_t byte_length - length of capture in bytes(!) |
310 // Isolate* isolate | 320 // Isolate* isolate |
311 #ifdef _WIN64 | 321 #ifdef _WIN64 |
312 // Compute and set byte_offset1 (start of capture). | 322 // Compute and set byte_offset1 (start of capture). |
313 __ leap(rcx, Operand(rsi, rdx, times_1, 0)); | 323 __ leap(rcx, Operand(rsi, rdx, times_1, 0)); |
314 // Set byte_offset2. | 324 // Set byte_offset2. |
315 __ leap(rdx, Operand(rsi, rdi, times_1, 0)); | 325 __ leap(rdx, Operand(rsi, rdi, times_1, 0)); |
| 326 if (read_backward) { |
| 327 __ subq(rdx, rbx); |
| 328 } |
316 // Set byte_length. | 329 // Set byte_length. |
317 __ movp(r8, rbx); | 330 __ movp(r8, rbx); |
318 // Isolate. | 331 // Isolate. |
319 __ LoadAddress(r9, ExternalReference::isolate_address(isolate())); | 332 __ LoadAddress(r9, ExternalReference::isolate_address(isolate())); |
320 #else // AMD64 calling convention | 333 #else // AMD64 calling convention |
321 // Compute byte_offset2 (current position = rsi+rdi). | 334 // Compute byte_offset2 (current position = rsi+rdi). |
322 __ leap(rax, Operand(rsi, rdi, times_1, 0)); | 335 __ leap(rax, Operand(rsi, rdi, times_1, 0)); |
323 // Compute and set byte_offset1 (start of capture). | 336 // Compute and set byte_offset1 (start of capture). |
324 __ leap(rdi, Operand(rsi, rdx, times_1, 0)); | 337 __ leap(rdi, Operand(rsi, rdx, times_1, 0)); |
325 // Set byte_offset2. | 338 // Set byte_offset2. |
326 __ movp(rsi, rax); | 339 __ movp(rsi, rax); |
| 340 if (read_backward) { |
| 341 __ subq(rsi, rbx); |
| 342 } |
327 // Set byte_length. | 343 // Set byte_length. |
328 __ movp(rdx, rbx); | 344 __ movp(rdx, rbx); |
329 // Isolate. | 345 // Isolate. |
330 __ LoadAddress(rcx, ExternalReference::isolate_address(isolate())); | 346 __ LoadAddress(rcx, ExternalReference::isolate_address(isolate())); |
331 #endif | 347 #endif |
332 | 348 |
333 { // NOLINT: Can't find a way to open this scope without confusing the | 349 { // NOLINT: Can't find a way to open this scope without confusing the |
334 // linter. | 350 // linter. |
335 AllowExternalCallThatCantCauseGC scope(&masm_); | 351 AllowExternalCallThatCantCauseGC scope(&masm_); |
336 ExternalReference compare = | 352 ExternalReference compare = |
337 ExternalReference::re_case_insensitive_compare_uc16(isolate()); | 353 ExternalReference::re_case_insensitive_compare_uc16(isolate()); |
338 __ CallCFunction(compare, num_arguments); | 354 __ CallCFunction(compare, num_arguments); |
339 } | 355 } |
340 | 356 |
341 // Restore original values before reacting on result value. | 357 // Restore original values before reacting on result value. |
342 __ Move(code_object_pointer(), masm_.CodeObject()); | 358 __ Move(code_object_pointer(), masm_.CodeObject()); |
343 __ popq(backtrack_stackpointer()); | 359 __ popq(backtrack_stackpointer()); |
344 #ifndef _WIN64 | 360 #ifndef _WIN64 |
345 __ popq(rdi); | 361 __ popq(rdi); |
346 __ popq(rsi); | 362 __ popq(rsi); |
347 #endif | 363 #endif |
348 | 364 |
349 // Check if function returned non-zero for success or zero for failure. | 365 // Check if function returned non-zero for success or zero for failure. |
350 __ testp(rax, rax); | 366 __ testp(rax, rax); |
351 BranchOrBacktrack(zero, on_no_match); | 367 BranchOrBacktrack(zero, on_no_match); |
352 // On success, increment position by length of capture. | 368 // On success, advance position by length of capture. |
353 // Requires that rbx is callee save (true for both Win64 and AMD64 ABIs). | 369 // Requires that rbx is callee save (true for both Win64 and AMD64 ABIs). |
354 __ addq(rdi, rbx); | 370 if (read_backward) { |
| 371 __ subq(rdi, rbx); |
| 372 } else { |
| 373 __ addq(rdi, rbx); |
| 374 } |
355 } | 375 } |
356 __ bind(&fallthrough); | 376 __ bind(&fallthrough); |
357 } | 377 } |
358 | 378 |
359 | 379 |
360 void RegExpMacroAssemblerX64::CheckNotBackReference( | 380 void RegExpMacroAssemblerX64::CheckNotBackReference(int start_reg, |
361 int start_reg, | 381 bool read_backward, |
362 Label* on_no_match) { | 382 Label* on_no_match) { |
363 Label fallthrough; | 383 Label fallthrough; |
364 | 384 |
365 // Find length of back-referenced capture. | 385 // Find length of back-referenced capture. |
366 ReadPositionFromRegister(rdx, start_reg); // Offset of start of capture | 386 ReadPositionFromRegister(rdx, start_reg); // Offset of start of capture |
367 ReadPositionFromRegister(rax, start_reg + 1); // Offset of end of capture | 387 ReadPositionFromRegister(rax, start_reg + 1); // Offset of end of capture |
368 __ subp(rax, rdx); // Length to check. | 388 __ subp(rax, rdx); // Length to check. |
369 | 389 // The length of the capture can only be negative if the end of the |
370 // Fail on partial or illegal capture (start of capture after end of capture). | 390 // capture is not yet recorded. If the length is zero, the capture is |
371 // This must not happen (no back-reference can reference a capture that wasn't | 391 // either empty or uncaptured. In either of those cases, succeed. |
372 // closed before in the reg-exp). | 392 __ j(less_equal, &fallthrough); |
373 __ Check(greater_equal, kInvalidCaptureReferenced); | |
374 | |
375 // Succeed on empty capture (including non-participating capture) | |
376 __ j(equal, &fallthrough); | |
377 | 393 |
378 // ----------------------- | 394 // ----------------------- |
379 // rdx - Start of capture | 395 // rdx - Start of capture |
380 // rax - length of capture | 396 // rax - length of capture |
381 | |
382 // Check that there are sufficient characters left in the input. | 397 // Check that there are sufficient characters left in the input. |
383 __ movl(rbx, rdi); | 398 if (read_backward) { |
384 __ addl(rbx, rax); | 399 __ leap(rbx, Operand(rsi, rdi, times_1, 0)); |
385 BranchOrBacktrack(greater, on_no_match); | 400 __ subp(rbx, rax); |
| 401 for (int i = 0; i < char_size(); i++) { |
| 402 __ addp(rbx, Operand(rbp, kStartIndex)); |
| 403 } |
| 404 __ cmpp(rbx, Operand(rbp, kInputStart)); |
| 405 BranchOrBacktrack(less, on_no_match); |
| 406 } else { |
| 407 __ movl(rbx, rdi); |
| 408 __ addl(rbx, rax); |
| 409 BranchOrBacktrack(greater, on_no_match); |
| 410 } |
386 | 411 |
387 // Compute pointers to match string and capture string | 412 // Compute pointers to match string and capture string |
388 __ leap(rbx, Operand(rsi, rdi, times_1, 0)); // Start of match. | 413 __ leap(rbx, Operand(rsi, rdi, times_1, 0)); // Start of match. |
| 414 if (read_backward) { |
| 415 __ subq(rbx, rax); // Offset by length when matching backwards. |
| 416 } |
389 __ addp(rdx, rsi); // Start of capture. | 417 __ addp(rdx, rsi); // Start of capture. |
390 __ leap(r9, Operand(rdx, rax, times_1, 0)); // End of capture | 418 __ leap(r9, Operand(rdx, rax, times_1, 0)); // End of capture |
391 | 419 |
392 // ----------------------- | 420 // ----------------------- |
393 // rbx - current capture character address. | 421 // rbx - current capture character address. |
394 // rbx - current input character address . | 422 // rbx - current input character address . |
395 // r9 - end of input to match (capture length after rbx). | 423 // r9 - end of input to match (capture length after rbx). |
396 | 424 |
397 Label loop; | 425 Label loop; |
398 __ bind(&loop); | 426 __ bind(&loop); |
(...skipping 10 matching lines...) Expand all Loading... |
409 __ addp(rbx, Immediate(char_size())); | 437 __ addp(rbx, Immediate(char_size())); |
410 __ addp(rdx, Immediate(char_size())); | 438 __ addp(rdx, Immediate(char_size())); |
411 // Check if we have reached end of match area. | 439 // Check if we have reached end of match area. |
412 __ cmpp(rdx, r9); | 440 __ cmpp(rdx, r9); |
413 __ j(below, &loop); | 441 __ j(below, &loop); |
414 | 442 |
415 // Success. | 443 // Success. |
416 // Set current character position to position after match. | 444 // Set current character position to position after match. |
417 __ movp(rdi, rbx); | 445 __ movp(rdi, rbx); |
418 __ subq(rdi, rsi); | 446 __ subq(rdi, rsi); |
| 447 if (read_backward) { |
| 448 // Subtract match length if we matched backward. |
| 449 __ addq(rdi, register_location(start_reg)); |
| 450 __ subq(rdi, register_location(start_reg + 1)); |
| 451 } |
419 | 452 |
420 __ bind(&fallthrough); | 453 __ bind(&fallthrough); |
421 } | 454 } |
422 | 455 |
423 | 456 |
424 void RegExpMacroAssemblerX64::CheckNotCharacter(uint32_t c, | 457 void RegExpMacroAssemblerX64::CheckNotCharacter(uint32_t c, |
425 Label* on_not_equal) { | 458 Label* on_not_equal) { |
426 __ cmpl(current_character(), Immediate(c)); | 459 __ cmpl(current_character(), Immediate(c)); |
427 BranchOrBacktrack(not_equal, on_not_equal); | 460 BranchOrBacktrack(not_equal, on_not_equal); |
428 } | 461 } |
(...skipping 582 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1011 RegExpMacroAssembler::IrregexpImplementation | 1044 RegExpMacroAssembler::IrregexpImplementation |
1012 RegExpMacroAssemblerX64::Implementation() { | 1045 RegExpMacroAssemblerX64::Implementation() { |
1013 return kX64Implementation; | 1046 return kX64Implementation; |
1014 } | 1047 } |
1015 | 1048 |
1016 | 1049 |
1017 void RegExpMacroAssemblerX64::LoadCurrentCharacter(int cp_offset, | 1050 void RegExpMacroAssemblerX64::LoadCurrentCharacter(int cp_offset, |
1018 Label* on_end_of_input, | 1051 Label* on_end_of_input, |
1019 bool check_bounds, | 1052 bool check_bounds, |
1020 int characters) { | 1053 int characters) { |
1021 DCHECK(cp_offset >= -1); // ^ and \b can look behind one character. | |
1022 DCHECK(cp_offset < (1<<30)); // Be sane! (And ensure negation works) | 1054 DCHECK(cp_offset < (1<<30)); // Be sane! (And ensure negation works) |
1023 if (check_bounds) { | 1055 if (check_bounds) { |
1024 CheckPosition(cp_offset + characters - 1, on_end_of_input); | 1056 if (cp_offset >= 0) { |
| 1057 CheckPosition(cp_offset + characters - 1, on_end_of_input); |
| 1058 } else { |
| 1059 CheckPosition(cp_offset, on_end_of_input); |
| 1060 } |
1025 } | 1061 } |
1026 LoadCurrentCharacterUnchecked(cp_offset, characters); | 1062 LoadCurrentCharacterUnchecked(cp_offset, characters); |
1027 } | 1063 } |
1028 | 1064 |
1029 | 1065 |
1030 void RegExpMacroAssemblerX64::PopCurrentPosition() { | 1066 void RegExpMacroAssemblerX64::PopCurrentPosition() { |
1031 Pop(rdi); | 1067 Pop(rdi); |
1032 } | 1068 } |
1033 | 1069 |
1034 | 1070 |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1198 DCHECK(register_index < (1<<30)); | 1234 DCHECK(register_index < (1<<30)); |
1199 if (num_registers_ <= register_index) { | 1235 if (num_registers_ <= register_index) { |
1200 num_registers_ = register_index + 1; | 1236 num_registers_ = register_index + 1; |
1201 } | 1237 } |
1202 return Operand(rbp, kRegisterZero - register_index * kPointerSize); | 1238 return Operand(rbp, kRegisterZero - register_index * kPointerSize); |
1203 } | 1239 } |
1204 | 1240 |
1205 | 1241 |
1206 void RegExpMacroAssemblerX64::CheckPosition(int cp_offset, | 1242 void RegExpMacroAssemblerX64::CheckPosition(int cp_offset, |
1207 Label* on_outside_input) { | 1243 Label* on_outside_input) { |
1208 __ cmpl(rdi, Immediate(-cp_offset * char_size())); | 1244 if (cp_offset >= 0) { |
1209 BranchOrBacktrack(greater_equal, on_outside_input); | 1245 __ cmpl(rdi, Immediate(-cp_offset * char_size())); |
| 1246 BranchOrBacktrack(greater_equal, on_outside_input); |
| 1247 } else { |
| 1248 __ leaq(rax, Operand(rsi, rdi, times_1, cp_offset * char_size())); |
| 1249 for (int i = 0; i < char_size(); i++) { |
| 1250 __ addq(rax, Operand(rbp, kStartIndex)); |
| 1251 } |
| 1252 __ cmpq(rax, Operand(rbp, kInputStart)); |
| 1253 BranchOrBacktrack(less, on_outside_input); |
| 1254 } |
1210 } | 1255 } |
1211 | 1256 |
1212 | 1257 |
1213 void RegExpMacroAssemblerX64::BranchOrBacktrack(Condition condition, | 1258 void RegExpMacroAssemblerX64::BranchOrBacktrack(Condition condition, |
1214 Label* to) { | 1259 Label* to) { |
1215 if (condition < 0) { // No condition | 1260 if (condition < 0) { // No condition |
1216 if (to == NULL) { | 1261 if (to == NULL) { |
1217 Backtrack(); | 1262 Backtrack(); |
1218 return; | 1263 return; |
1219 } | 1264 } |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1352 } | 1397 } |
1353 | 1398 |
1354 #undef __ | 1399 #undef __ |
1355 | 1400 |
1356 #endif // V8_INTERPRETED_REGEXP | 1401 #endif // V8_INTERPRETED_REGEXP |
1357 | 1402 |
1358 } // namespace internal | 1403 } // namespace internal |
1359 } // namespace v8 | 1404 } // namespace v8 |
1360 | 1405 |
1361 #endif // V8_TARGET_ARCH_X64 | 1406 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |