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 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
57 * - capture array size (may fit multiple sets of matches) | 57 * - capture array size (may fit multiple sets of matches) |
58 * - int* capture_array (int[num_saved_registers_], for output). | 58 * - int* capture_array (int[num_saved_registers_], for output). |
59 * - end of input (address of end of string) | 59 * - end of input (address of end of string) |
60 * - start of input (address of first character in string) | 60 * - start of input (address of first character in string) |
61 * - start index (character index of start) | 61 * - start index (character index of start) |
62 * - String* input_string (input string) | 62 * - String* input_string (input string) |
63 * - return address | 63 * - return address |
64 * - backup of callee save registers (rbx, possibly rsi and rdi). | 64 * - backup of callee save registers (rbx, possibly rsi and rdi). |
65 * - success counter (only useful for global regexp to count matches) | 65 * - success counter (only useful for global regexp to count matches) |
66 * - Offset of location before start of input (effectively character | 66 * - Offset of location before start of input (effectively character |
67 * position -1). Used to initialize capture registers to a non-position. | 67 * string start - 1). Used to initialize capture registers to a |
| 68 * non-position. |
68 * - At start of string (if 1, we are starting at the start of the | 69 * - At start of string (if 1, we are starting at the start of the |
69 * string, otherwise 0) | 70 * string, otherwise 0) |
70 * - register 0 rbp[-n] (Only positions must be stored in the first | 71 * - register 0 rbp[-n] (Only positions must be stored in the first |
71 * - register 1 rbp[-n-8] num_saved_registers_ registers) | 72 * - register 1 rbp[-n-8] num_saved_registers_ registers) |
72 * - ... | 73 * - ... |
73 * | 74 * |
74 * The first num_saved_registers_ registers are initialized to point to | 75 * The first num_saved_registers_ registers are initialized to point to |
75 * "character -1" in the string (i.e., char_size() bytes before the first | 76 * "character -1" in the string (i.e., char_size() bytes before the first |
76 * character of the string). The remaining registers starts out uninitialized. | 77 * character of the string). The remaining registers starts out uninitialized. |
77 * | 78 * |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
164 } | 165 } |
165 | 166 |
166 | 167 |
167 void RegExpMacroAssemblerX64::CheckCharacterGT(uc16 limit, Label* on_greater) { | 168 void RegExpMacroAssemblerX64::CheckCharacterGT(uc16 limit, Label* on_greater) { |
168 __ cmpl(current_character(), Immediate(limit)); | 169 __ cmpl(current_character(), Immediate(limit)); |
169 BranchOrBacktrack(greater, on_greater); | 170 BranchOrBacktrack(greater, on_greater); |
170 } | 171 } |
171 | 172 |
172 | 173 |
173 void RegExpMacroAssemblerX64::CheckAtStart(Label* on_at_start) { | 174 void RegExpMacroAssemblerX64::CheckAtStart(Label* on_at_start) { |
174 Label not_at_start; | 175 __ leap(rax, Operand(rdi, -char_size())); |
175 // Did we start the match at the start of the string at all? | 176 __ cmpp(rax, Operand(rbp, kStringStartMinusOne)); |
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)); | |
180 __ cmpp(rax, Operand(rbp, kInputStart)); | |
181 BranchOrBacktrack(equal, on_at_start); | 177 BranchOrBacktrack(equal, on_at_start); |
182 __ bind(¬_at_start); | |
183 } | 178 } |
184 | 179 |
185 | 180 |
186 void RegExpMacroAssemblerX64::CheckNotAtStart(Label* on_not_at_start) { | 181 void RegExpMacroAssemblerX64::CheckNotAtStart(int cp_offset, |
187 // Did we start the match at the start of the string at all? | 182 Label* on_not_at_start) { |
188 __ cmpl(Operand(rbp, kStartIndex), Immediate(0)); | 183 __ leap(rax, Operand(rdi, -char_size() + cp_offset * char_size())); |
189 BranchOrBacktrack(not_equal, on_not_at_start); | 184 __ cmpp(rax, Operand(rbp, kStringStartMinusOne)); |
190 // If we did, are we still at the start of the input? | |
191 __ leap(rax, Operand(rsi, rdi, times_1, 0)); | |
192 __ cmpp(rax, Operand(rbp, kInputStart)); | |
193 BranchOrBacktrack(not_equal, on_not_at_start); | 185 BranchOrBacktrack(not_equal, on_not_at_start); |
194 } | 186 } |
195 | 187 |
196 | 188 |
197 void RegExpMacroAssemblerX64::CheckCharacterLT(uc16 limit, Label* on_less) { | 189 void RegExpMacroAssemblerX64::CheckCharacterLT(uc16 limit, Label* on_less) { |
198 __ cmpl(current_character(), Immediate(limit)); | 190 __ cmpl(current_character(), Immediate(limit)); |
199 BranchOrBacktrack(less, on_less); | 191 BranchOrBacktrack(less, on_less); |
200 } | 192 } |
201 | 193 |
202 | 194 |
203 void RegExpMacroAssemblerX64::CheckGreedyLoop(Label* on_equal) { | 195 void RegExpMacroAssemblerX64::CheckGreedyLoop(Label* on_equal) { |
204 Label fallthrough; | 196 Label fallthrough; |
205 __ cmpl(rdi, Operand(backtrack_stackpointer(), 0)); | 197 __ cmpl(rdi, Operand(backtrack_stackpointer(), 0)); |
206 __ j(not_equal, &fallthrough); | 198 __ j(not_equal, &fallthrough); |
207 Drop(); | 199 Drop(); |
208 BranchOrBacktrack(no_condition, on_equal); | 200 BranchOrBacktrack(no_condition, on_equal); |
209 __ bind(&fallthrough); | 201 __ bind(&fallthrough); |
210 } | 202 } |
211 | 203 |
212 | 204 |
213 void RegExpMacroAssemblerX64::CheckNotBackReferenceIgnoreCase( | 205 void RegExpMacroAssemblerX64::CheckNotBackReferenceIgnoreCase( |
214 int start_reg, | 206 int start_reg, bool read_backward, Label* on_no_match) { |
215 Label* on_no_match) { | |
216 Label fallthrough; | 207 Label fallthrough; |
217 ReadPositionFromRegister(rdx, start_reg); // Offset of start of capture | 208 ReadPositionFromRegister(rdx, start_reg); // Offset of start of capture |
218 ReadPositionFromRegister(rbx, start_reg + 1); // Offset of end of capture | 209 ReadPositionFromRegister(rbx, start_reg + 1); // Offset of end of capture |
219 __ subp(rbx, rdx); // Length of capture. | 210 __ subp(rbx, rdx); // Length of capture. |
220 | 211 |
221 // ----------------------- | 212 // ----------------------- |
222 // rdx = Start offset of capture. | 213 // rdx = Start offset of capture. |
223 // rbx = Length of capture | 214 // rbx = Length of capture |
224 | 215 |
225 // If length is negative, this code will fail (it's a symptom of a partial or | 216 // At this point, the capture registers are either both set or both cleared. |
226 // illegal capture where start of capture after end of capture). | 217 // If the capture length is zero, then the capture is either empty or cleared. |
227 // This must not happen (no back-reference can reference a capture that wasn't | 218 // Fall through in both cases. |
228 // closed before in the reg-exp, and we must not generate code that can cause | |
229 // this condition). | |
230 | |
231 // If length is zero, either the capture is empty or it is nonparticipating. | |
232 // In either case succeed immediately. | |
233 __ j(equal, &fallthrough); | 219 __ j(equal, &fallthrough); |
234 | 220 |
235 // ----------------------- | 221 // ----------------------- |
236 // rdx - Start of capture | 222 // rdx - Start of capture |
237 // rbx - length of capture | 223 // rbx - length of capture |
238 // Check that there are sufficient characters left in the input. | 224 // Check that there are sufficient characters left in the input. |
239 __ movl(rax, rdi); | 225 if (read_backward) { |
240 __ addl(rax, rbx); | 226 __ movl(rax, Operand(rbp, kStringStartMinusOne)); |
241 BranchOrBacktrack(greater, on_no_match); | 227 __ addl(rax, rbx); |
| 228 __ cmpl(rdi, rax); |
| 229 BranchOrBacktrack(less_equal, on_no_match); |
| 230 } else { |
| 231 __ movl(rax, rdi); |
| 232 __ addl(rax, rbx); |
| 233 BranchOrBacktrack(greater, on_no_match); |
| 234 } |
242 | 235 |
243 if (mode_ == LATIN1) { | 236 if (mode_ == LATIN1) { |
244 Label loop_increment; | 237 Label loop_increment; |
245 if (on_no_match == NULL) { | 238 if (on_no_match == NULL) { |
246 on_no_match = &backtrack_label_; | 239 on_no_match = &backtrack_label_; |
247 } | 240 } |
248 | 241 |
249 __ leap(r9, Operand(rsi, rdx, times_1, 0)); | 242 __ leap(r9, Operand(rsi, rdx, times_1, 0)); |
250 __ leap(r11, Operand(rsi, rdi, times_1, 0)); | 243 __ leap(r11, Operand(rsi, rdi, times_1, 0)); |
| 244 if (read_backward) { |
| 245 __ subp(r11, rbx); // Offset by length when matching backwards. |
| 246 } |
251 __ addp(rbx, r9); // End of capture | 247 __ addp(rbx, r9); // End of capture |
252 // --------------------- | 248 // --------------------- |
253 // r11 - current input character address | 249 // r11 - current input character address |
254 // r9 - current capture character address | 250 // r9 - current capture character address |
255 // rbx - end of capture | 251 // rbx - end of capture |
256 | 252 |
257 Label loop; | 253 Label loop; |
258 __ bind(&loop); | 254 __ bind(&loop); |
259 __ movzxbl(rdx, Operand(r9, 0)); | 255 __ movzxbl(rdx, Operand(r9, 0)); |
260 __ movzxbl(rax, Operand(r11, 0)); | 256 __ movzxbl(rax, Operand(r11, 0)); |
(...skipping 22 matching lines...) Expand all Loading... |
283 // Increment pointers into match and capture strings. | 279 // Increment pointers into match and capture strings. |
284 __ addp(r11, Immediate(1)); | 280 __ addp(r11, Immediate(1)); |
285 __ addp(r9, Immediate(1)); | 281 __ addp(r9, Immediate(1)); |
286 // Compare to end of capture, and loop if not done. | 282 // Compare to end of capture, and loop if not done. |
287 __ cmpp(r9, rbx); | 283 __ cmpp(r9, rbx); |
288 __ j(below, &loop); | 284 __ j(below, &loop); |
289 | 285 |
290 // Compute new value of character position after the matched part. | 286 // Compute new value of character position after the matched part. |
291 __ movp(rdi, r11); | 287 __ movp(rdi, r11); |
292 __ subq(rdi, rsi); | 288 __ subq(rdi, rsi); |
| 289 if (read_backward) { |
| 290 // Subtract match length if we matched backward. |
| 291 __ addq(rdi, register_location(start_reg)); |
| 292 __ subq(rdi, register_location(start_reg + 1)); |
| 293 } |
293 } else { | 294 } else { |
294 DCHECK(mode_ == UC16); | 295 DCHECK(mode_ == UC16); |
295 // Save important/volatile registers before calling C function. | 296 // Save important/volatile registers before calling C function. |
296 #ifndef _WIN64 | 297 #ifndef _WIN64 |
297 // Caller save on Linux and callee save in Windows. | 298 // Caller save on Linux and callee save in Windows. |
298 __ pushq(rsi); | 299 __ pushq(rsi); |
299 __ pushq(rdi); | 300 __ pushq(rdi); |
300 #endif | 301 #endif |
301 __ pushq(backtrack_stackpointer()); | 302 __ pushq(backtrack_stackpointer()); |
302 | 303 |
303 static const int num_arguments = 4; | 304 static const int num_arguments = 4; |
304 __ PrepareCallCFunction(num_arguments); | 305 __ PrepareCallCFunction(num_arguments); |
305 | 306 |
306 // Put arguments into parameter registers. Parameters are | 307 // Put arguments into parameter registers. Parameters are |
307 // Address byte_offset1 - Address captured substring's start. | 308 // Address byte_offset1 - Address captured substring's start. |
308 // Address byte_offset2 - Address of current character position. | 309 // Address byte_offset2 - Address of current character position. |
309 // size_t byte_length - length of capture in bytes(!) | 310 // size_t byte_length - length of capture in bytes(!) |
310 // Isolate* isolate | 311 // Isolate* isolate |
311 #ifdef _WIN64 | 312 #ifdef _WIN64 |
312 // Compute and set byte_offset1 (start of capture). | 313 // Compute and set byte_offset1 (start of capture). |
313 __ leap(rcx, Operand(rsi, rdx, times_1, 0)); | 314 __ leap(rcx, Operand(rsi, rdx, times_1, 0)); |
314 // Set byte_offset2. | 315 // Set byte_offset2. |
315 __ leap(rdx, Operand(rsi, rdi, times_1, 0)); | 316 __ leap(rdx, Operand(rsi, rdi, times_1, 0)); |
| 317 if (read_backward) { |
| 318 __ subq(rdx, rbx); |
| 319 } |
316 // Set byte_length. | 320 // Set byte_length. |
317 __ movp(r8, rbx); | 321 __ movp(r8, rbx); |
318 // Isolate. | 322 // Isolate. |
319 __ LoadAddress(r9, ExternalReference::isolate_address(isolate())); | 323 __ LoadAddress(r9, ExternalReference::isolate_address(isolate())); |
320 #else // AMD64 calling convention | 324 #else // AMD64 calling convention |
321 // Compute byte_offset2 (current position = rsi+rdi). | 325 // Compute byte_offset2 (current position = rsi+rdi). |
322 __ leap(rax, Operand(rsi, rdi, times_1, 0)); | 326 __ leap(rax, Operand(rsi, rdi, times_1, 0)); |
323 // Compute and set byte_offset1 (start of capture). | 327 // Compute and set byte_offset1 (start of capture). |
324 __ leap(rdi, Operand(rsi, rdx, times_1, 0)); | 328 __ leap(rdi, Operand(rsi, rdx, times_1, 0)); |
325 // Set byte_offset2. | 329 // Set byte_offset2. |
326 __ movp(rsi, rax); | 330 __ movp(rsi, rax); |
| 331 if (read_backward) { |
| 332 __ subq(rsi, rbx); |
| 333 } |
327 // Set byte_length. | 334 // Set byte_length. |
328 __ movp(rdx, rbx); | 335 __ movp(rdx, rbx); |
329 // Isolate. | 336 // Isolate. |
330 __ LoadAddress(rcx, ExternalReference::isolate_address(isolate())); | 337 __ LoadAddress(rcx, ExternalReference::isolate_address(isolate())); |
331 #endif | 338 #endif |
332 | 339 |
333 { // NOLINT: Can't find a way to open this scope without confusing the | 340 { // NOLINT: Can't find a way to open this scope without confusing the |
334 // linter. | 341 // linter. |
335 AllowExternalCallThatCantCauseGC scope(&masm_); | 342 AllowExternalCallThatCantCauseGC scope(&masm_); |
336 ExternalReference compare = | 343 ExternalReference compare = |
337 ExternalReference::re_case_insensitive_compare_uc16(isolate()); | 344 ExternalReference::re_case_insensitive_compare_uc16(isolate()); |
338 __ CallCFunction(compare, num_arguments); | 345 __ CallCFunction(compare, num_arguments); |
339 } | 346 } |
340 | 347 |
341 // Restore original values before reacting on result value. | 348 // Restore original values before reacting on result value. |
342 __ Move(code_object_pointer(), masm_.CodeObject()); | 349 __ Move(code_object_pointer(), masm_.CodeObject()); |
343 __ popq(backtrack_stackpointer()); | 350 __ popq(backtrack_stackpointer()); |
344 #ifndef _WIN64 | 351 #ifndef _WIN64 |
345 __ popq(rdi); | 352 __ popq(rdi); |
346 __ popq(rsi); | 353 __ popq(rsi); |
347 #endif | 354 #endif |
348 | 355 |
349 // Check if function returned non-zero for success or zero for failure. | 356 // Check if function returned non-zero for success or zero for failure. |
350 __ testp(rax, rax); | 357 __ testp(rax, rax); |
351 BranchOrBacktrack(zero, on_no_match); | 358 BranchOrBacktrack(zero, on_no_match); |
352 // On success, increment position by length of capture. | 359 // On success, advance position by length of capture. |
353 // Requires that rbx is callee save (true for both Win64 and AMD64 ABIs). | 360 // Requires that rbx is callee save (true for both Win64 and AMD64 ABIs). |
354 __ addq(rdi, rbx); | 361 if (read_backward) { |
| 362 __ subq(rdi, rbx); |
| 363 } else { |
| 364 __ addq(rdi, rbx); |
| 365 } |
355 } | 366 } |
356 __ bind(&fallthrough); | 367 __ bind(&fallthrough); |
357 } | 368 } |
358 | 369 |
359 | 370 |
360 void RegExpMacroAssemblerX64::CheckNotBackReference( | 371 void RegExpMacroAssemblerX64::CheckNotBackReference(int start_reg, |
361 int start_reg, | 372 bool read_backward, |
362 Label* on_no_match) { | 373 Label* on_no_match) { |
363 Label fallthrough; | 374 Label fallthrough; |
364 | 375 |
365 // Find length of back-referenced capture. | 376 // Find length of back-referenced capture. |
366 ReadPositionFromRegister(rdx, start_reg); // Offset of start of capture | 377 ReadPositionFromRegister(rdx, start_reg); // Offset of start of capture |
367 ReadPositionFromRegister(rax, start_reg + 1); // Offset of end of capture | 378 ReadPositionFromRegister(rax, start_reg + 1); // Offset of end of capture |
368 __ subp(rax, rdx); // Length to check. | 379 __ subp(rax, rdx); // Length to check. |
369 | 380 |
370 // Fail on partial or illegal capture (start of capture after end of capture). | 381 // At this point, the capture registers are either both set or both cleared. |
371 // This must not happen (no back-reference can reference a capture that wasn't | 382 // If the capture length is zero, then the capture is either empty or cleared. |
372 // closed before in the reg-exp). | 383 // Fall through in both cases. |
373 __ Check(greater_equal, kInvalidCaptureReferenced); | |
374 | |
375 // Succeed on empty capture (including non-participating capture) | |
376 __ j(equal, &fallthrough); | 384 __ j(equal, &fallthrough); |
377 | 385 |
378 // ----------------------- | 386 // ----------------------- |
379 // rdx - Start of capture | 387 // rdx - Start of capture |
380 // rax - length of capture | 388 // rax - length of capture |
381 | |
382 // Check that there are sufficient characters left in the input. | 389 // Check that there are sufficient characters left in the input. |
383 __ movl(rbx, rdi); | 390 if (read_backward) { |
384 __ addl(rbx, rax); | 391 __ movl(rbx, Operand(rbp, kStringStartMinusOne)); |
385 BranchOrBacktrack(greater, on_no_match); | 392 __ addl(rbx, rax); |
| 393 __ cmpl(rdi, rbx); |
| 394 BranchOrBacktrack(less_equal, on_no_match); |
| 395 } else { |
| 396 __ movl(rbx, rdi); |
| 397 __ addl(rbx, rax); |
| 398 BranchOrBacktrack(greater, on_no_match); |
| 399 } |
386 | 400 |
387 // Compute pointers to match string and capture string | 401 // Compute pointers to match string and capture string |
388 __ leap(rbx, Operand(rsi, rdi, times_1, 0)); // Start of match. | 402 __ leap(rbx, Operand(rsi, rdi, times_1, 0)); // Start of match. |
| 403 if (read_backward) { |
| 404 __ subq(rbx, rax); // Offset by length when matching backwards. |
| 405 } |
389 __ addp(rdx, rsi); // Start of capture. | 406 __ addp(rdx, rsi); // Start of capture. |
390 __ leap(r9, Operand(rdx, rax, times_1, 0)); // End of capture | 407 __ leap(r9, Operand(rdx, rax, times_1, 0)); // End of capture |
391 | 408 |
392 // ----------------------- | 409 // ----------------------- |
393 // rbx - current capture character address. | 410 // rbx - current capture character address. |
394 // rbx - current input character address . | 411 // rbx - current input character address . |
395 // r9 - end of input to match (capture length after rbx). | 412 // r9 - end of input to match (capture length after rbx). |
396 | 413 |
397 Label loop; | 414 Label loop; |
398 __ bind(&loop); | 415 __ bind(&loop); |
(...skipping 10 matching lines...) Expand all Loading... |
409 __ addp(rbx, Immediate(char_size())); | 426 __ addp(rbx, Immediate(char_size())); |
410 __ addp(rdx, Immediate(char_size())); | 427 __ addp(rdx, Immediate(char_size())); |
411 // Check if we have reached end of match area. | 428 // Check if we have reached end of match area. |
412 __ cmpp(rdx, r9); | 429 __ cmpp(rdx, r9); |
413 __ j(below, &loop); | 430 __ j(below, &loop); |
414 | 431 |
415 // Success. | 432 // Success. |
416 // Set current character position to position after match. | 433 // Set current character position to position after match. |
417 __ movp(rdi, rbx); | 434 __ movp(rdi, rbx); |
418 __ subq(rdi, rsi); | 435 __ subq(rdi, rsi); |
| 436 if (read_backward) { |
| 437 // Subtract match length if we matched backward. |
| 438 __ addq(rdi, register_location(start_reg)); |
| 439 __ subq(rdi, register_location(start_reg + 1)); |
| 440 } |
419 | 441 |
420 __ bind(&fallthrough); | 442 __ bind(&fallthrough); |
421 } | 443 } |
422 | 444 |
423 | 445 |
424 void RegExpMacroAssemblerX64::CheckNotCharacter(uint32_t c, | 446 void RegExpMacroAssemblerX64::CheckNotCharacter(uint32_t c, |
425 Label* on_not_equal) { | 447 Label* on_not_equal) { |
426 __ cmpl(current_character(), Immediate(c)); | 448 __ cmpl(current_character(), Immediate(c)); |
427 BranchOrBacktrack(not_equal, on_not_equal); | 449 BranchOrBacktrack(not_equal, on_not_equal); |
428 } | 450 } |
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
675 __ pushq(rsi); | 697 __ pushq(rsi); |
676 __ pushq(rdx); | 698 __ pushq(rdx); |
677 __ pushq(rcx); | 699 __ pushq(rcx); |
678 __ pushq(r8); | 700 __ pushq(r8); |
679 __ pushq(r9); | 701 __ pushq(r9); |
680 | 702 |
681 __ pushq(rbx); // Callee-save | 703 __ pushq(rbx); // Callee-save |
682 #endif | 704 #endif |
683 | 705 |
684 __ Push(Immediate(0)); // Number of successful matches in a global regexp. | 706 __ Push(Immediate(0)); // Number of successful matches in a global regexp. |
685 __ Push(Immediate(0)); // Make room for "input start - 1" constant. | 707 __ Push(Immediate(0)); // Make room for "string start - 1" constant. |
686 | 708 |
687 // Check if we have space on the stack for registers. | 709 // Check if we have space on the stack for registers. |
688 Label stack_limit_hit; | 710 Label stack_limit_hit; |
689 Label stack_ok; | 711 Label stack_ok; |
690 | 712 |
691 ExternalReference stack_limit = | 713 ExternalReference stack_limit = |
692 ExternalReference::address_of_stack_limit(isolate()); | 714 ExternalReference::address_of_stack_limit(isolate()); |
693 __ movp(rcx, rsp); | 715 __ movp(rcx, rsp); |
694 __ Move(kScratchRegister, stack_limit); | 716 __ Move(kScratchRegister, stack_limit); |
695 __ subp(rcx, Operand(kScratchRegister, 0)); | 717 __ subp(rcx, Operand(kScratchRegister, 0)); |
(...skipping 29 matching lines...) Expand all Loading... |
725 // (effectively string position -1). | 747 // (effectively string position -1). |
726 __ movp(rbx, Operand(rbp, kStartIndex)); | 748 __ movp(rbx, Operand(rbp, kStartIndex)); |
727 __ negq(rbx); | 749 __ negq(rbx); |
728 if (mode_ == UC16) { | 750 if (mode_ == UC16) { |
729 __ leap(rax, Operand(rdi, rbx, times_2, -char_size())); | 751 __ leap(rax, Operand(rdi, rbx, times_2, -char_size())); |
730 } else { | 752 } else { |
731 __ leap(rax, Operand(rdi, rbx, times_1, -char_size())); | 753 __ leap(rax, Operand(rdi, rbx, times_1, -char_size())); |
732 } | 754 } |
733 // Store this value in a local variable, for use when clearing | 755 // Store this value in a local variable, for use when clearing |
734 // position registers. | 756 // position registers. |
735 __ movp(Operand(rbp, kInputStartMinusOne), rax); | 757 __ movp(Operand(rbp, kStringStartMinusOne), rax); |
736 | 758 |
737 #if V8_OS_WIN | 759 #if V8_OS_WIN |
738 // Ensure that we have written to each stack page, in order. Skipping a page | 760 // Ensure that we have written to each stack page, in order. Skipping a page |
739 // on Windows can cause segmentation faults. Assuming page size is 4k. | 761 // on Windows can cause segmentation faults. Assuming page size is 4k. |
740 const int kPageSize = 4096; | 762 const int kPageSize = 4096; |
741 const int kRegistersPerPage = kPageSize / kPointerSize; | 763 const int kRegistersPerPage = kPageSize / kPointerSize; |
742 for (int i = num_saved_registers_ + kRegistersPerPage - 1; | 764 for (int i = num_saved_registers_ + kRegistersPerPage - 1; |
743 i < num_registers_; | 765 i < num_registers_; |
744 i += kRegistersPerPage) { | 766 i += kRegistersPerPage) { |
745 __ movp(register_location(i), rax); // One write every page. | 767 __ movp(register_location(i), rax); // One write every page. |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
828 // Check whether we have enough room for another set of capture results. | 850 // Check whether we have enough room for another set of capture results. |
829 __ cmpp(rcx, Immediate(num_saved_registers_)); | 851 __ cmpp(rcx, Immediate(num_saved_registers_)); |
830 __ j(less, &exit_label_); | 852 __ j(less, &exit_label_); |
831 | 853 |
832 __ movp(Operand(rbp, kNumOutputRegisters), rcx); | 854 __ movp(Operand(rbp, kNumOutputRegisters), rcx); |
833 // Advance the location for output. | 855 // Advance the location for output. |
834 __ addp(Operand(rbp, kRegisterOutput), | 856 __ addp(Operand(rbp, kRegisterOutput), |
835 Immediate(num_saved_registers_ * kIntSize)); | 857 Immediate(num_saved_registers_ * kIntSize)); |
836 | 858 |
837 // Prepare rax to initialize registers with its value in the next run. | 859 // Prepare rax to initialize registers with its value in the next run. |
838 __ movp(rax, Operand(rbp, kInputStartMinusOne)); | 860 __ movp(rax, Operand(rbp, kStringStartMinusOne)); |
839 | 861 |
840 if (global_with_zero_length_check()) { | 862 if (global_with_zero_length_check()) { |
841 // Special case for zero-length matches. | 863 // Special case for zero-length matches. |
842 // rdx: capture start index | 864 // rdx: capture start index |
843 __ cmpp(rdi, rdx); | 865 __ cmpp(rdi, rdx); |
844 // Not a zero-length match, restart. | 866 // Not a zero-length match, restart. |
845 __ j(not_equal, &load_char_start_regexp); | 867 __ j(not_equal, &load_char_start_regexp); |
846 // rdi (offset from the end) is zero if we already reached the end. | 868 // rdi (offset from the end) is zero if we already reached the end. |
847 __ testp(rdi, rdi); | 869 __ testp(rdi, rdi); |
848 __ j(zero, &exit_label_, Label::kNear); | 870 __ j(zero, &exit_label_, Label::kNear); |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1011 RegExpMacroAssembler::IrregexpImplementation | 1033 RegExpMacroAssembler::IrregexpImplementation |
1012 RegExpMacroAssemblerX64::Implementation() { | 1034 RegExpMacroAssemblerX64::Implementation() { |
1013 return kX64Implementation; | 1035 return kX64Implementation; |
1014 } | 1036 } |
1015 | 1037 |
1016 | 1038 |
1017 void RegExpMacroAssemblerX64::LoadCurrentCharacter(int cp_offset, | 1039 void RegExpMacroAssemblerX64::LoadCurrentCharacter(int cp_offset, |
1018 Label* on_end_of_input, | 1040 Label* on_end_of_input, |
1019 bool check_bounds, | 1041 bool check_bounds, |
1020 int characters) { | 1042 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) | 1043 DCHECK(cp_offset < (1<<30)); // Be sane! (And ensure negation works) |
1023 if (check_bounds) { | 1044 if (check_bounds) { |
1024 CheckPosition(cp_offset + characters - 1, on_end_of_input); | 1045 if (cp_offset >= 0) { |
| 1046 CheckPosition(cp_offset + characters - 1, on_end_of_input); |
| 1047 } else { |
| 1048 CheckPosition(cp_offset, on_end_of_input); |
| 1049 } |
1025 } | 1050 } |
1026 LoadCurrentCharacterUnchecked(cp_offset, characters); | 1051 LoadCurrentCharacterUnchecked(cp_offset, characters); |
1027 } | 1052 } |
1028 | 1053 |
1029 | 1054 |
1030 void RegExpMacroAssemblerX64::PopCurrentPosition() { | 1055 void RegExpMacroAssemblerX64::PopCurrentPosition() { |
1031 Pop(rdi); | 1056 Pop(rdi); |
1032 } | 1057 } |
1033 | 1058 |
1034 | 1059 |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1117 __ movp(register_location(reg), rdi); | 1142 __ movp(register_location(reg), rdi); |
1118 } else { | 1143 } else { |
1119 __ leap(rax, Operand(rdi, cp_offset * char_size())); | 1144 __ leap(rax, Operand(rdi, cp_offset * char_size())); |
1120 __ movp(register_location(reg), rax); | 1145 __ movp(register_location(reg), rax); |
1121 } | 1146 } |
1122 } | 1147 } |
1123 | 1148 |
1124 | 1149 |
1125 void RegExpMacroAssemblerX64::ClearRegisters(int reg_from, int reg_to) { | 1150 void RegExpMacroAssemblerX64::ClearRegisters(int reg_from, int reg_to) { |
1126 DCHECK(reg_from <= reg_to); | 1151 DCHECK(reg_from <= reg_to); |
1127 __ movp(rax, Operand(rbp, kInputStartMinusOne)); | 1152 __ movp(rax, Operand(rbp, kStringStartMinusOne)); |
1128 for (int reg = reg_from; reg <= reg_to; reg++) { | 1153 for (int reg = reg_from; reg <= reg_to; reg++) { |
1129 __ movp(register_location(reg), rax); | 1154 __ movp(register_location(reg), rax); |
1130 } | 1155 } |
1131 } | 1156 } |
1132 | 1157 |
1133 | 1158 |
1134 void RegExpMacroAssemblerX64::WriteStackPointerToRegister(int reg) { | 1159 void RegExpMacroAssemblerX64::WriteStackPointerToRegister(int reg) { |
1135 __ movp(rax, backtrack_stackpointer()); | 1160 __ movp(rax, backtrack_stackpointer()); |
1136 __ subp(rax, Operand(rbp, kStackHighEnd)); | 1161 __ subp(rax, Operand(rbp, kStackHighEnd)); |
1137 __ movp(register_location(reg), rax); | 1162 __ movp(register_location(reg), rax); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1198 DCHECK(register_index < (1<<30)); | 1223 DCHECK(register_index < (1<<30)); |
1199 if (num_registers_ <= register_index) { | 1224 if (num_registers_ <= register_index) { |
1200 num_registers_ = register_index + 1; | 1225 num_registers_ = register_index + 1; |
1201 } | 1226 } |
1202 return Operand(rbp, kRegisterZero - register_index * kPointerSize); | 1227 return Operand(rbp, kRegisterZero - register_index * kPointerSize); |
1203 } | 1228 } |
1204 | 1229 |
1205 | 1230 |
1206 void RegExpMacroAssemblerX64::CheckPosition(int cp_offset, | 1231 void RegExpMacroAssemblerX64::CheckPosition(int cp_offset, |
1207 Label* on_outside_input) { | 1232 Label* on_outside_input) { |
1208 __ cmpl(rdi, Immediate(-cp_offset * char_size())); | 1233 if (cp_offset >= 0) { |
1209 BranchOrBacktrack(greater_equal, on_outside_input); | 1234 __ cmpl(rdi, Immediate(-cp_offset * char_size())); |
| 1235 BranchOrBacktrack(greater_equal, on_outside_input); |
| 1236 } else { |
| 1237 __ leap(rax, Operand(rdi, cp_offset * char_size())); |
| 1238 __ cmpp(rax, Operand(rbp, kStringStartMinusOne)); |
| 1239 BranchOrBacktrack(less_equal, on_outside_input); |
| 1240 } |
1210 } | 1241 } |
1211 | 1242 |
1212 | 1243 |
1213 void RegExpMacroAssemblerX64::BranchOrBacktrack(Condition condition, | 1244 void RegExpMacroAssemblerX64::BranchOrBacktrack(Condition condition, |
1214 Label* to) { | 1245 Label* to) { |
1215 if (condition < 0) { // No condition | 1246 if (condition < 0) { // No condition |
1216 if (to == NULL) { | 1247 if (to == NULL) { |
1217 Backtrack(); | 1248 Backtrack(); |
1218 return; | 1249 return; |
1219 } | 1250 } |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1352 } | 1383 } |
1353 | 1384 |
1354 #undef __ | 1385 #undef __ |
1355 | 1386 |
1356 #endif // V8_INTERPRETED_REGEXP | 1387 #endif // V8_INTERPRETED_REGEXP |
1357 | 1388 |
1358 } // namespace internal | 1389 } // namespace internal |
1359 } // namespace v8 | 1390 } // namespace v8 |
1360 | 1391 |
1361 #endif // V8_TARGET_ARCH_X64 | 1392 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |