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