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
3// found in the LICENSE file.
4
5#if V8_TARGET_ARCH_X64
6
7#include "src/regexp/x64/regexp-macro-assembler-x64.h"
8
9#include "src/factory.h"
10#include "src/log.h"
11#include "src/macro-assembler.h"
12#include "src/objects-inl.h"
13#include "src/regexp/regexp-macro-assembler.h"
14#include "src/regexp/regexp-stack.h"
15#include "src/unicode.h"
16
17namespace v8 {
18namespace internal {
19
20#ifndef V8_INTERPRETED_REGEXP
21
22/*
23 * This assembler uses the following register assignment convention
24 * - rdx : Currently loaded character(s) as Latin1 or UC16.  Must be loaded
25 *         using LoadCurrentCharacter before using any of the dispatch methods.
26 *         Temporarily stores the index of capture start after a matching pass
27 *         for a global regexp.
28 * - rdi : Current position in input, as negative offset from end of string.
29 *         Please notice that this is the byte offset, not the character
30 *         offset!  Is always a 32-bit signed (negative) offset, but must be
31 *         maintained sign-extended to 64 bits, since it is used as index.
32 * - rsi : End of input (points to byte after last character in input),
33 *         so that rsi+rdi points to the current character.
34 * - rbp : Frame pointer.  Used to access arguments, local variables and
35 *         RegExp registers.
36 * - rsp : Points to tip of C stack.
37 * - rcx : Points to tip of backtrack stack.  The backtrack stack contains
38 *         only 32-bit values.  Most are offsets from some base (e.g., character
39 *         positions from end of string or code location from Code* pointer).
40 * - r8  : Code object pointer.  Used to convert between absolute and
41 *         code-object-relative addresses.
42 *
43 * The registers rax, rbx, r9 and r11 are free to use for computations.
44 * If changed to use r12+, they should be saved as callee-save registers.
45 * The macro assembler special register r13 (kRootRegister) isn't special
46 * during execution of RegExp code (it doesn't hold the value assumed when
47 * creating JS code), so Root related macro operations can be used.
48 *
49 * Each call to a C++ method should retain these registers.
50 *
51 * The stack will have the following content, in some order, indexable from the
52 * frame pointer (see, e.g., kStackHighEnd):
53 *    - Isolate* isolate     (address of the current isolate)
54 *    - direct_call          (if 1, direct call from JavaScript code, if 0 call
55 *                            through the runtime system)
56 *    - stack_area_base      (high end of the memory area to use as
57 *                            backtracking stack)
58 *    - capture array size   (may fit multiple sets of matches)
59 *    - int* capture_array   (int[num_saved_registers_], for output).
60 *    - end of input         (address of end of string)
61 *    - start of input       (address of first character in string)
62 *    - start index          (character index of start)
63 *    - String* input_string (input string)
64 *    - return address
65 *    - backup of callee save registers (rbx, possibly rsi and rdi).
66 *    - success counter      (only useful for global regexp to count matches)
67 *    - Offset of location before start of input (effectively character
68 *      string start - 1).  Used to initialize capture registers to a
69 *      non-position.
70 *    - At start of string (if 1, we are starting at the start of the
71 *      string, otherwise 0)
72 *    - register 0  rbp[-n]   (Only positions must be stored in the first
73 *    - register 1  rbp[-n-8]  num_saved_registers_ registers)
74 *    - ...
75 *
76 * The first num_saved_registers_ registers are initialized to point to
77 * "character -1" in the string (i.e., char_size() bytes before the first
78 * character of the string).  The remaining registers starts out uninitialized.
79 *
80 * The first seven values must be provided by the calling code by
81 * calling the code's entry address cast to a function pointer with the
82 * following signature:
83 * int (*match)(String* input_string,
84 *              int start_index,
85 *              Address start,
86 *              Address end,
87 *              int* capture_output_array,
88 *              bool at_start,
89 *              byte* stack_area_base,
90 *              bool direct_call)
91 */
92
93#define __ ACCESS_MASM((&masm_))
94
95RegExpMacroAssemblerX64::RegExpMacroAssemblerX64(Isolate* isolate, Zone* zone,
96                                                 Mode mode,
97                                                 int registers_to_save)
98    : NativeRegExpMacroAssembler(isolate, zone),
99      masm_(isolate, NULL, kRegExpCodeSize, CodeObjectRequired::kYes),
100      no_root_array_scope_(&masm_),
101      code_relative_fixup_positions_(4, zone),
102      mode_(mode),
103      num_registers_(registers_to_save),
104      num_saved_registers_(registers_to_save),
105      entry_label_(),
106      start_label_(),
107      success_label_(),
108      backtrack_label_(),
109      exit_label_() {
110  DCHECK_EQ(0, registers_to_save % 2);
111  __ jmp(&entry_label_);   // We'll write the entry code when we know more.
112  __ bind(&start_label_);  // And then continue from here.
113}
114
115
116RegExpMacroAssemblerX64::~RegExpMacroAssemblerX64() {
117  // Unuse labels in case we throw away the assembler without calling GetCode.
118  entry_label_.Unuse();
119  start_label_.Unuse();
120  success_label_.Unuse();
121  backtrack_label_.Unuse();
122  exit_label_.Unuse();
123  check_preempt_label_.Unuse();
124  stack_overflow_label_.Unuse();
125}
126
127
128int RegExpMacroAssemblerX64::stack_limit_slack()  {
129  return RegExpStack::kStackLimitSlack;
130}
131
132
133void RegExpMacroAssemblerX64::AdvanceCurrentPosition(int by) {
134  if (by != 0) {
135    __ addq(rdi, Immediate(by * char_size()));
136  }
137}
138
139
140void RegExpMacroAssemblerX64::AdvanceRegister(int reg, int by) {
141  DCHECK(reg >= 0);
142  DCHECK(reg < num_registers_);
143  if (by != 0) {
144    __ addp(register_location(reg), Immediate(by));
145  }
146}
147
148
149void RegExpMacroAssemblerX64::Backtrack() {
150  CheckPreemption();
151  // Pop Code* offset from backtrack stack, add Code* and jump to location.
152  Pop(rbx);
153  __ addp(rbx, code_object_pointer());
154  __ jmp(rbx);
155}
156
157
158void RegExpMacroAssemblerX64::Bind(Label* label) {
159  __ bind(label);
160}
161
162
163void RegExpMacroAssemblerX64::CheckCharacter(uint32_t c, Label* on_equal) {
164  __ cmpl(current_character(), Immediate(c));
165  BranchOrBacktrack(equal, on_equal);
166}
167
168
169void RegExpMacroAssemblerX64::CheckCharacterGT(uc16 limit, Label* on_greater) {
170  __ cmpl(current_character(), Immediate(limit));
171  BranchOrBacktrack(greater, on_greater);
172}
173
174
175void RegExpMacroAssemblerX64::CheckAtStart(Label* on_at_start) {
176  __ leap(rax, Operand(rdi, -char_size()));
177  __ cmpp(rax, Operand(rbp, kStringStartMinusOne));
178  BranchOrBacktrack(equal, on_at_start);
179}
180
181
182void RegExpMacroAssemblerX64::CheckNotAtStart(int cp_offset,
183                                              Label* on_not_at_start) {
184  __ leap(rax, Operand(rdi, -char_size() + cp_offset * char_size()));
185  __ cmpp(rax, Operand(rbp, kStringStartMinusOne));
186  BranchOrBacktrack(not_equal, on_not_at_start);
187}
188
189
190void RegExpMacroAssemblerX64::CheckCharacterLT(uc16 limit, Label* on_less) {
191  __ cmpl(current_character(), Immediate(limit));
192  BranchOrBacktrack(less, on_less);
193}
194
195
196void RegExpMacroAssemblerX64::CheckGreedyLoop(Label* on_equal) {
197  Label fallthrough;
198  __ cmpl(rdi, Operand(backtrack_stackpointer(), 0));
199  __ j(not_equal, &fallthrough);
200  Drop();
201  BranchOrBacktrack(no_condition, on_equal);
202  __ bind(&fallthrough);
203}
204
205
206void RegExpMacroAssemblerX64::CheckNotBackReferenceIgnoreCase(
207    int start_reg, bool read_backward, bool unicode, Label* on_no_match) {
208  Label fallthrough;
209  ReadPositionFromRegister(rdx, start_reg);  // Offset of start of capture
210  ReadPositionFromRegister(rbx, start_reg + 1);  // Offset of end of capture
211  __ subp(rbx, rdx);  // Length of capture.
212
213  // -----------------------
214  // rdx  = Start offset of capture.
215  // rbx = Length of capture
216
217  // At this point, the capture registers are either both set or both cleared.
218  // If the capture length is zero, then the capture is either empty or cleared.
219  // Fall through in both cases.
220  __ j(equal, &fallthrough);
221
222  // -----------------------
223  // rdx - Start of capture
224  // rbx - length of capture
225  // Check that there are sufficient characters left in the input.
226  if (read_backward) {
227    __ movl(rax, Operand(rbp, kStringStartMinusOne));
228    __ addl(rax, rbx);
229    __ cmpl(rdi, rax);
230    BranchOrBacktrack(less_equal, on_no_match);
231  } else {
232    __ movl(rax, rdi);
233    __ addl(rax, rbx);
234    BranchOrBacktrack(greater, on_no_match);
235  }
236
237  if (mode_ == LATIN1) {
238    Label loop_increment;
239    if (on_no_match == NULL) {
240      on_no_match = &backtrack_label_;
241    }
242
243    __ leap(r9, Operand(rsi, rdx, times_1, 0));
244    __ leap(r11, Operand(rsi, rdi, times_1, 0));
245    if (read_backward) {
246      __ subp(r11, rbx);  // Offset by length when matching backwards.
247    }
248    __ addp(rbx, r9);  // End of capture
249    // ---------------------
250    // r11 - current input character address
251    // r9 - current capture character address
252    // rbx - end of capture
253
254    Label loop;
255    __ bind(&loop);
256    __ movzxbl(rdx, Operand(r9, 0));
257    __ movzxbl(rax, Operand(r11, 0));
258    // al - input character
259    // dl - capture character
260    __ cmpb(rax, rdx);
261    __ j(equal, &loop_increment);
262
263    // Mismatch, try case-insensitive match (converting letters to lower-case).
264    // I.e., if or-ing with 0x20 makes values equal and in range 'a'-'z', it's
265    // a match.
266    __ orp(rax, Immediate(0x20));  // Convert match character to lower-case.
267    __ orp(rdx, Immediate(0x20));  // Convert capture character to lower-case.
268    __ cmpb(rax, rdx);
269    __ j(not_equal, on_no_match);  // Definitely not equal.
270    __ subb(rax, Immediate('a'));
271    __ cmpb(rax, Immediate('z' - 'a'));
272    __ j(below_equal, &loop_increment);  // In range 'a'-'z'.
273    // Latin-1: Check for values in range [224,254] but not 247.
274    __ subb(rax, Immediate(224 - 'a'));
275    __ cmpb(rax, Immediate(254 - 224));
276    __ j(above, on_no_match);  // Weren't Latin-1 letters.
277    __ cmpb(rax, Immediate(247 - 224));  // Check for 247.
278    __ j(equal, on_no_match);
279    __ bind(&loop_increment);
280    // Increment pointers into match and capture strings.
281    __ addp(r11, Immediate(1));
282    __ addp(r9, Immediate(1));
283    // Compare to end of capture, and loop if not done.
284    __ cmpp(r9, rbx);
285    __ j(below, &loop);
286
287    // Compute new value of character position after the matched part.
288    __ movp(rdi, r11);
289    __ subq(rdi, rsi);
290    if (read_backward) {
291      // Subtract match length if we matched backward.
292      __ addq(rdi, register_location(start_reg));
293      __ subq(rdi, register_location(start_reg + 1));
294    }
295  } else {
296    DCHECK(mode_ == UC16);
297    // Save important/volatile registers before calling C function.
298#ifndef _WIN64
299    // Caller save on Linux and callee save in Windows.
300    __ pushq(rsi);
301    __ pushq(rdi);
302#endif
303    __ pushq(backtrack_stackpointer());
304
305    static const int num_arguments = 4;
306    __ PrepareCallCFunction(num_arguments);
307
308    // Put arguments into parameter registers. Parameters are
309    //   Address byte_offset1 - Address captured substring's start.
310    //   Address byte_offset2 - Address of current character position.
311    //   size_t byte_length - length of capture in bytes(!)
312//   Isolate* isolate or 0 if unicode flag.
313#ifdef _WIN64
314    DCHECK(rcx.is(arg_reg_1));
315    DCHECK(rdx.is(arg_reg_2));
316    // Compute and set byte_offset1 (start of capture).
317    __ leap(rcx, Operand(rsi, rdx, times_1, 0));
318    // Set byte_offset2.
319    __ leap(rdx, Operand(rsi, rdi, times_1, 0));
320    if (read_backward) {
321      __ subq(rdx, rbx);
322    }
323#else  // AMD64 calling convention
324    DCHECK(rdi.is(arg_reg_1));
325    DCHECK(rsi.is(arg_reg_2));
326    // Compute byte_offset2 (current position = rsi+rdi).
327    __ leap(rax, Operand(rsi, rdi, times_1, 0));
328    // Compute and set byte_offset1 (start of capture).
329    __ leap(rdi, Operand(rsi, rdx, times_1, 0));
330    // Set byte_offset2.
331    __ movp(rsi, rax);
332    if (read_backward) {
333      __ subq(rsi, rbx);
334    }
335#endif  // _WIN64
336
337    // Set byte_length.
338    __ movp(arg_reg_3, rbx);
339    // Isolate.
340#ifdef V8_I18N_SUPPORT
341    if (unicode) {
342      __ movp(arg_reg_4, Immediate(0));
343    } else  // NOLINT
344#endif      // V8_I18N_SUPPORT
345    {
346      __ LoadAddress(arg_reg_4, ExternalReference::isolate_address(isolate()));
347    }
348
349    { // NOLINT: Can't find a way to open this scope without confusing the
350      // linter.
351      AllowExternalCallThatCantCauseGC scope(&masm_);
352      ExternalReference compare =
353          ExternalReference::re_case_insensitive_compare_uc16(isolate());
354      __ CallCFunction(compare, num_arguments);
355    }
356
357    // Restore original values before reacting on result value.
358    __ Move(code_object_pointer(), masm_.CodeObject());
359    __ popq(backtrack_stackpointer());
360#ifndef _WIN64
361    __ popq(rdi);
362    __ popq(rsi);
363#endif
364
365    // Check if function returned non-zero for success or zero for failure.
366    __ testp(rax, rax);
367    BranchOrBacktrack(zero, on_no_match);
368    // On success, advance position by length of capture.
369    // Requires that rbx is callee save (true for both Win64 and AMD64 ABIs).
370    if (read_backward) {
371      __ subq(rdi, rbx);
372    } else {
373      __ addq(rdi, rbx);
374    }
375  }
376  __ bind(&fallthrough);
377}
378
379
380void RegExpMacroAssemblerX64::CheckNotBackReference(int start_reg,
381                                                    bool read_backward,
382                                                    Label* on_no_match) {
383  Label fallthrough;
384
385  // Find length of back-referenced capture.
386  ReadPositionFromRegister(rdx, start_reg);  // Offset of start of capture
387  ReadPositionFromRegister(rax, start_reg + 1);  // Offset of end of capture
388  __ subp(rax, rdx);  // Length to check.
389
390  // At this point, the capture registers are either both set or both cleared.
391  // If the capture length is zero, then the capture is either empty or cleared.
392  // Fall through in both cases.
393  __ j(equal, &fallthrough);
394
395  // -----------------------
396  // rdx - Start of capture
397  // rax - length of capture
398  // Check that there are sufficient characters left in the input.
399  if (read_backward) {
400    __ movl(rbx, Operand(rbp, kStringStartMinusOne));
401    __ addl(rbx, rax);
402    __ cmpl(rdi, rbx);
403    BranchOrBacktrack(less_equal, on_no_match);
404  } else {
405    __ movl(rbx, rdi);
406    __ addl(rbx, rax);
407    BranchOrBacktrack(greater, on_no_match);
408  }
409
410  // Compute pointers to match string and capture string
411  __ leap(rbx, Operand(rsi, rdi, times_1, 0));  // Start of match.
412  if (read_backward) {
413    __ subq(rbx, rax);  // Offset by length when matching backwards.
414  }
415  __ addp(rdx, rsi);  // Start of capture.
416  __ leap(r9, Operand(rdx, rax, times_1, 0));  // End of capture
417
418  // -----------------------
419  // rbx - current capture character address.
420  // rbx - current input character address .
421  // r9 - end of input to match (capture length after rbx).
422
423  Label loop;
424  __ bind(&loop);
425  if (mode_ == LATIN1) {
426    __ movzxbl(rax, Operand(rdx, 0));
427    __ cmpb(rax, Operand(rbx, 0));
428  } else {
429    DCHECK(mode_ == UC16);
430    __ movzxwl(rax, Operand(rdx, 0));
431    __ cmpw(rax, Operand(rbx, 0));
432  }
433  BranchOrBacktrack(not_equal, on_no_match);
434  // Increment pointers into capture and match string.
435  __ addp(rbx, Immediate(char_size()));
436  __ addp(rdx, Immediate(char_size()));
437  // Check if we have reached end of match area.
438  __ cmpp(rdx, r9);
439  __ j(below, &loop);
440
441  // Success.
442  // Set current character position to position after match.
443  __ movp(rdi, rbx);
444  __ subq(rdi, rsi);
445  if (read_backward) {
446    // Subtract match length if we matched backward.
447    __ addq(rdi, register_location(start_reg));
448    __ subq(rdi, register_location(start_reg + 1));
449  }
450
451  __ bind(&fallthrough);
452}
453
454
455void RegExpMacroAssemblerX64::CheckNotCharacter(uint32_t c,
456                                                Label* on_not_equal) {
457  __ cmpl(current_character(), Immediate(c));
458  BranchOrBacktrack(not_equal, on_not_equal);
459}
460
461
462void RegExpMacroAssemblerX64::CheckCharacterAfterAnd(uint32_t c,
463                                                     uint32_t mask,
464                                                     Label* on_equal) {
465  if (c == 0) {
466    __ testl(current_character(), Immediate(mask));
467  } else {
468    __ movl(rax, Immediate(mask));
469    __ andp(rax, current_character());
470    __ cmpl(rax, Immediate(c));
471  }
472  BranchOrBacktrack(equal, on_equal);
473}
474
475
476void RegExpMacroAssemblerX64::CheckNotCharacterAfterAnd(uint32_t c,
477                                                        uint32_t mask,
478                                                        Label* on_not_equal) {
479  if (c == 0) {
480    __ testl(current_character(), Immediate(mask));
481  } else {
482    __ movl(rax, Immediate(mask));
483    __ andp(rax, current_character());
484    __ cmpl(rax, Immediate(c));
485  }
486  BranchOrBacktrack(not_equal, on_not_equal);
487}
488
489
490void RegExpMacroAssemblerX64::CheckNotCharacterAfterMinusAnd(
491    uc16 c,
492    uc16 minus,
493    uc16 mask,
494    Label* on_not_equal) {
495  DCHECK(minus < String::kMaxUtf16CodeUnit);
496  __ leap(rax, Operand(current_character(), -minus));
497  __ andp(rax, Immediate(mask));
498  __ cmpl(rax, Immediate(c));
499  BranchOrBacktrack(not_equal, on_not_equal);
500}
501
502
503void RegExpMacroAssemblerX64::CheckCharacterInRange(
504    uc16 from,
505    uc16 to,
506    Label* on_in_range) {
507  __ leal(rax, Operand(current_character(), -from));
508  __ cmpl(rax, Immediate(to - from));
509  BranchOrBacktrack(below_equal, on_in_range);
510}
511
512
513void RegExpMacroAssemblerX64::CheckCharacterNotInRange(
514    uc16 from,
515    uc16 to,
516    Label* on_not_in_range) {
517  __ leal(rax, Operand(current_character(), -from));
518  __ cmpl(rax, Immediate(to - from));
519  BranchOrBacktrack(above, on_not_in_range);
520}
521
522
523void RegExpMacroAssemblerX64::CheckBitInTable(
524    Handle<ByteArray> table,
525    Label* on_bit_set) {
526  __ Move(rax, table);
527  Register index = current_character();
528  if (mode_ != LATIN1 || kTableMask != String::kMaxOneByteCharCode) {
529    __ movp(rbx, current_character());
530    __ andp(rbx, Immediate(kTableMask));
531    index = rbx;
532  }
533  __ cmpb(FieldOperand(rax, index, times_1, ByteArray::kHeaderSize),
534          Immediate(0));
535  BranchOrBacktrack(not_equal, on_bit_set);
536}
537
538
539bool RegExpMacroAssemblerX64::CheckSpecialCharacterClass(uc16 type,
540                                                         Label* on_no_match) {
541  // Range checks (c in min..max) are generally implemented by an unsigned
542  // (c - min) <= (max - min) check, using the sequence:
543  //   leap(rax, Operand(current_character(), -min)) or sub(rax, Immediate(min))
544  //   cmp(rax, Immediate(max - min))
545  switch (type) {
546  case 's':
547    // Match space-characters
548    if (mode_ == LATIN1) {
549      // One byte space characters are '\t'..'\r', ' ' and \u00a0.
550      Label success;
551      __ cmpl(current_character(), Immediate(' '));
552      __ j(equal, &success, Label::kNear);
553      // Check range 0x09..0x0d
554      __ leap(rax, Operand(current_character(), -'\t'));
555      __ cmpl(rax, Immediate('\r' - '\t'));
556      __ j(below_equal, &success, Label::kNear);
557      // \u00a0 (NBSP).
558      __ cmpl(rax, Immediate(0x00a0 - '\t'));
559      BranchOrBacktrack(not_equal, on_no_match);
560      __ bind(&success);
561      return true;
562    }
563    return false;
564  case 'S':
565    // The emitted code for generic character classes is good enough.
566    return false;
567  case 'd':
568    // Match ASCII digits ('0'..'9')
569    __ leap(rax, Operand(current_character(), -'0'));
570    __ cmpl(rax, Immediate('9' - '0'));
571    BranchOrBacktrack(above, on_no_match);
572    return true;
573  case 'D':
574    // Match non ASCII-digits
575    __ leap(rax, Operand(current_character(), -'0'));
576    __ cmpl(rax, Immediate('9' - '0'));
577    BranchOrBacktrack(below_equal, on_no_match);
578    return true;
579  case '.': {
580    // Match non-newlines (not 0x0a('\n'), 0x0d('\r'), 0x2028 and 0x2029)
581    __ movl(rax, current_character());
582    __ xorp(rax, Immediate(0x01));
583    // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c
584    __ subl(rax, Immediate(0x0b));
585    __ cmpl(rax, Immediate(0x0c - 0x0b));
586    BranchOrBacktrack(below_equal, on_no_match);
587    if (mode_ == UC16) {
588      // Compare original value to 0x2028 and 0x2029, using the already
589      // computed (current_char ^ 0x01 - 0x0b). I.e., check for
590      // 0x201d (0x2028 - 0x0b) or 0x201e.
591      __ subl(rax, Immediate(0x2028 - 0x0b));
592      __ cmpl(rax, Immediate(0x2029 - 0x2028));
593      BranchOrBacktrack(below_equal, on_no_match);
594    }
595    return true;
596  }
597  case 'n': {
598    // Match newlines (0x0a('\n'), 0x0d('\r'), 0x2028 and 0x2029)
599    __ movl(rax, current_character());
600    __ xorp(rax, Immediate(0x01));
601    // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c
602    __ subl(rax, Immediate(0x0b));
603    __ cmpl(rax, Immediate(0x0c - 0x0b));
604    if (mode_ == LATIN1) {
605      BranchOrBacktrack(above, on_no_match);
606    } else {
607      Label done;
608      BranchOrBacktrack(below_equal, &done);
609      // Compare original value to 0x2028 and 0x2029, using the already
610      // computed (current_char ^ 0x01 - 0x0b). I.e., check for
611      // 0x201d (0x2028 - 0x0b) or 0x201e.
612      __ subl(rax, Immediate(0x2028 - 0x0b));
613      __ cmpl(rax, Immediate(0x2029 - 0x2028));
614      BranchOrBacktrack(above, on_no_match);
615      __ bind(&done);
616    }
617    return true;
618  }
619  case 'w': {
620    if (mode_ != LATIN1) {
621      // Table is 256 entries, so all Latin1 characters can be tested.
622      __ cmpl(current_character(), Immediate('z'));
623      BranchOrBacktrack(above, on_no_match);
624    }
625    __ Move(rbx, ExternalReference::re_word_character_map());
626    DCHECK_EQ(0, word_character_map[0]);  // Character '\0' is not a word char.
627    __ testb(Operand(rbx, current_character(), times_1, 0),
628             current_character());
629    BranchOrBacktrack(zero, on_no_match);
630    return true;
631  }
632  case 'W': {
633    Label done;
634    if (mode_ != LATIN1) {
635      // Table is 256 entries, so all Latin1 characters can be tested.
636      __ cmpl(current_character(), Immediate('z'));
637      __ j(above, &done);
638    }
639    __ Move(rbx, ExternalReference::re_word_character_map());
640    DCHECK_EQ(0, word_character_map[0]);  // Character '\0' is not a word char.
641    __ testb(Operand(rbx, current_character(), times_1, 0),
642             current_character());
643    BranchOrBacktrack(not_zero, on_no_match);
644    if (mode_ != LATIN1) {
645      __ bind(&done);
646    }
647    return true;
648  }
649
650  case '*':
651    // Match any character.
652    return true;
653  // No custom implementation (yet): s(UC16), S(UC16).
654  default:
655    return false;
656  }
657}
658
659
660void RegExpMacroAssemblerX64::Fail() {
661  STATIC_ASSERT(FAILURE == 0);  // Return value for failure is zero.
662  if (!global()) {
663    __ Set(rax, FAILURE);
664  }
665  __ jmp(&exit_label_);
666}
667
668
669Handle<HeapObject> RegExpMacroAssemblerX64::GetCode(Handle<String> source) {
670  Label return_rax;
671  // Finalize code - write the entry point code now we know how many
672  // registers we need.
673  // Entry code:
674  __ bind(&entry_label_);
675
676  // Tell the system that we have a stack frame.  Because the type is MANUAL, no
677  // is generated.
678  FrameScope scope(&masm_, StackFrame::MANUAL);
679
680  // Actually emit code to start a new stack frame.
681  __ pushq(rbp);
682  __ movp(rbp, rsp);
683  // Save parameters and callee-save registers. Order here should correspond
684  //  to order of kBackup_ebx etc.
685#ifdef _WIN64
686  // MSVC passes arguments in rcx, rdx, r8, r9, with backing stack slots.
687  // Store register parameters in pre-allocated stack slots,
688  __ movq(Operand(rbp, kInputString), rcx);
689  __ movq(Operand(rbp, kStartIndex), rdx);  // Passed as int32 in edx.
690  __ movq(Operand(rbp, kInputStart), r8);
691  __ movq(Operand(rbp, kInputEnd), r9);
692  // Callee-save on Win64.
693  __ pushq(rsi);
694  __ pushq(rdi);
695  __ pushq(rbx);
696#else
697  // GCC passes arguments in rdi, rsi, rdx, rcx, r8, r9 (and then on stack).
698  // Push register parameters on stack for reference.
699  DCHECK_EQ(kInputString, -1 * kRegisterSize);
700  DCHECK_EQ(kStartIndex, -2 * kRegisterSize);
701  DCHECK_EQ(kInputStart, -3 * kRegisterSize);
702  DCHECK_EQ(kInputEnd, -4 * kRegisterSize);
703  DCHECK_EQ(kRegisterOutput, -5 * kRegisterSize);
704  DCHECK_EQ(kNumOutputRegisters, -6 * kRegisterSize);
705  __ pushq(rdi);
706  __ pushq(rsi);
707  __ pushq(rdx);
708  __ pushq(rcx);
709  __ pushq(r8);
710  __ pushq(r9);
711
712  __ pushq(rbx);  // Callee-save
713#endif
714
715  __ Push(Immediate(0));  // Number of successful matches in a global regexp.
716  __ Push(Immediate(0));  // Make room for "string start - 1" constant.
717
718  // Check if we have space on the stack for registers.
719  Label stack_limit_hit;
720  Label stack_ok;
721
722  ExternalReference stack_limit =
723      ExternalReference::address_of_stack_limit(isolate());
724  __ movp(rcx, rsp);
725  __ Move(kScratchRegister, stack_limit);
726  __ subp(rcx, Operand(kScratchRegister, 0));
727  // Handle it if the stack pointer is already below the stack limit.
728  __ j(below_equal, &stack_limit_hit);
729  // Check if there is room for the variable number of registers above
730  // the stack limit.
731  __ cmpp(rcx, Immediate(num_registers_ * kPointerSize));
732  __ j(above_equal, &stack_ok);
733  // Exit with OutOfMemory exception. There is not enough space on the stack
734  // for our working registers.
735  __ Set(rax, EXCEPTION);
736  __ jmp(&return_rax);
737
738  __ bind(&stack_limit_hit);
739  __ Move(code_object_pointer(), masm_.CodeObject());
740  CallCheckStackGuardState();  // Preserves no registers beside rbp and rsp.
741  __ testp(rax, rax);
742  // If returned value is non-zero, we exit with the returned value as result.
743  __ j(not_zero, &return_rax);
744
745  __ bind(&stack_ok);
746
747  // Allocate space on stack for registers.
748  __ subp(rsp, Immediate(num_registers_ * kPointerSize));
749  // Load string length.
750  __ movp(rsi, Operand(rbp, kInputEnd));
751  // Load input position.
752  __ movp(rdi, Operand(rbp, kInputStart));
753  // Set up rdi to be negative offset from string end.
754  __ subq(rdi, rsi);
755  // Set rax to address of char before start of the string
756  // (effectively string position -1).
757  __ movp(rbx, Operand(rbp, kStartIndex));
758  __ negq(rbx);
759  if (mode_ == UC16) {
760    __ leap(rax, Operand(rdi, rbx, times_2, -char_size()));
761  } else {
762    __ leap(rax, Operand(rdi, rbx, times_1, -char_size()));
763  }
764  // Store this value in a local variable, for use when clearing
765  // position registers.
766  __ movp(Operand(rbp, kStringStartMinusOne), rax);
767
768#if V8_OS_WIN
769  // Ensure that we have written to each stack page, in order. Skipping a page
770  // on Windows can cause segmentation faults. Assuming page size is 4k.
771  const int kPageSize = 4096;
772  const int kRegistersPerPage = kPageSize / kPointerSize;
773  for (int i = num_saved_registers_ + kRegistersPerPage - 1;
774      i < num_registers_;
775      i += kRegistersPerPage) {
776    __ movp(register_location(i), rax);  // One write every page.
777  }
778#endif  // V8_OS_WIN
779
780  // Initialize code object pointer.
781  __ Move(code_object_pointer(), masm_.CodeObject());
782
783  Label load_char_start_regexp, start_regexp;
784  // Load newline if index is at start, previous character otherwise.
785  __ cmpl(Operand(rbp, kStartIndex), Immediate(0));
786  __ j(not_equal, &load_char_start_regexp, Label::kNear);
787  __ Set(current_character(), '\n');
788  __ jmp(&start_regexp, Label::kNear);
789
790  // Global regexp restarts matching here.
791  __ bind(&load_char_start_regexp);
792  // Load previous char as initial value of current character register.
793  LoadCurrentCharacterUnchecked(-1, 1);
794  __ bind(&start_regexp);
795
796  // Initialize on-stack registers.
797  if (num_saved_registers_ > 0) {
798    // Fill saved registers with initial value = start offset - 1
799    // Fill in stack push order, to avoid accessing across an unwritten
800    // page (a problem on Windows).
801    if (num_saved_registers_ > 8) {
802      __ Set(rcx, kRegisterZero);
803      Label init_loop;
804      __ bind(&init_loop);
805      __ movp(Operand(rbp, rcx, times_1, 0), rax);
806      __ subq(rcx, Immediate(kPointerSize));
807      __ cmpq(rcx,
808              Immediate(kRegisterZero - num_saved_registers_ * kPointerSize));
809      __ j(greater, &init_loop);
810    } else {  // Unroll the loop.
811      for (int i = 0; i < num_saved_registers_; i++) {
812        __ movp(register_location(i), rax);
813      }
814    }
815  }
816
817  // Initialize backtrack stack pointer.
818  __ movp(backtrack_stackpointer(), Operand(rbp, kStackHighEnd));
819
820  __ jmp(&start_label_);
821
822  // Exit code:
823  if (success_label_.is_linked()) {
824    // Save captures when successful.
825    __ bind(&success_label_);
826    if (num_saved_registers_ > 0) {
827      // copy captures to output
828      __ movp(rdx, Operand(rbp, kStartIndex));
829      __ movp(rbx, Operand(rbp, kRegisterOutput));
830      __ movp(rcx, Operand(rbp, kInputEnd));
831      __ subp(rcx, Operand(rbp, kInputStart));
832      if (mode_ == UC16) {
833        __ leap(rcx, Operand(rcx, rdx, times_2, 0));
834      } else {
835        __ addp(rcx, rdx);
836      }
837      for (int i = 0; i < num_saved_registers_; i++) {
838        __ movp(rax, register_location(i));
839        if (i == 0 && global_with_zero_length_check()) {
840          // Keep capture start in rdx for the zero-length check later.
841          __ movp(rdx, rax);
842        }
843        __ addp(rax, rcx);  // Convert to index from start, not end.
844        if (mode_ == UC16) {
845          __ sarp(rax, Immediate(1));  // Convert byte index to character index.
846        }
847        __ movl(Operand(rbx, i * kIntSize), rax);
848      }
849    }
850
851    if (global()) {
852      // Restart matching if the regular expression is flagged as global.
853      // Increment success counter.
854      __ incp(Operand(rbp, kSuccessfulCaptures));
855      // Capture results have been stored, so the number of remaining global
856      // output registers is reduced by the number of stored captures.
857      __ movsxlq(rcx, Operand(rbp, kNumOutputRegisters));
858      __ subp(rcx, Immediate(num_saved_registers_));
859      // Check whether we have enough room for another set of capture results.
860      __ cmpp(rcx, Immediate(num_saved_registers_));
861      __ j(less, &exit_label_);
862
863      __ movp(Operand(rbp, kNumOutputRegisters), rcx);
864      // Advance the location for output.
865      __ addp(Operand(rbp, kRegisterOutput),
866              Immediate(num_saved_registers_ * kIntSize));
867
868      // Prepare rax to initialize registers with its value in the next run.
869      __ movp(rax, Operand(rbp, kStringStartMinusOne));
870
871      if (global_with_zero_length_check()) {
872        // Special case for zero-length matches.
873        // rdx: capture start index
874        __ cmpp(rdi, rdx);
875        // Not a zero-length match, restart.
876        __ j(not_equal, &load_char_start_regexp);
877        // rdi (offset from the end) is zero if we already reached the end.
878        __ testp(rdi, rdi);
879        __ j(zero, &exit_label_, Label::kNear);
880        // Advance current position after a zero-length match.
881        Label advance;
882        __ bind(&advance);
883        if (mode_ == UC16) {
884          __ addq(rdi, Immediate(2));
885        } else {
886          __ incq(rdi);
887        }
888        if (global_unicode()) CheckNotInSurrogatePair(0, &advance);
889      }
890
891      __ jmp(&load_char_start_regexp);
892    } else {
893      __ movp(rax, Immediate(SUCCESS));
894    }
895  }
896
897  __ bind(&exit_label_);
898  if (global()) {
899    // Return the number of successful captures.
900    __ movp(rax, Operand(rbp, kSuccessfulCaptures));
901  }
902
903  __ bind(&return_rax);
904#ifdef _WIN64
905  // Restore callee save registers.
906  __ leap(rsp, Operand(rbp, kLastCalleeSaveRegister));
907  __ popq(rbx);
908  __ popq(rdi);
909  __ popq(rsi);
910  // Stack now at rbp.
911#else
912  // Restore callee save register.
913  __ movp(rbx, Operand(rbp, kBackup_rbx));
914  // Skip rsp to rbp.
915  __ movp(rsp, rbp);
916#endif
917  // Exit function frame, restore previous one.
918  __ popq(rbp);
919  __ ret(0);
920
921  // Backtrack code (branch target for conditional backtracks).
922  if (backtrack_label_.is_linked()) {
923    __ bind(&backtrack_label_);
924    Backtrack();
925  }
926
927  Label exit_with_exception;
928
929  // Preempt-code
930  if (check_preempt_label_.is_linked()) {
931    SafeCallTarget(&check_preempt_label_);
932
933    __ pushq(backtrack_stackpointer());
934    __ pushq(rdi);
935
936    CallCheckStackGuardState();
937    __ testp(rax, rax);
938    // If returning non-zero, we should end execution with the given
939    // result as return value.
940    __ j(not_zero, &return_rax);
941
942    // Restore registers.
943    __ Move(code_object_pointer(), masm_.CodeObject());
944    __ popq(rdi);
945    __ popq(backtrack_stackpointer());
946    // String might have moved: Reload esi from frame.
947    __ movp(rsi, Operand(rbp, kInputEnd));
948    SafeReturn();
949  }
950
951  // Backtrack stack overflow code.
952  if (stack_overflow_label_.is_linked()) {
953    SafeCallTarget(&stack_overflow_label_);
954    // Reached if the backtrack-stack limit has been hit.
955
956    Label grow_failed;
957    // Save registers before calling C function
958#ifndef _WIN64
959    // Callee-save in Microsoft 64-bit ABI, but not in AMD64 ABI.
960    __ pushq(rsi);
961    __ pushq(rdi);
962#endif
963
964    // Call GrowStack(backtrack_stackpointer())
965    static const int num_arguments = 3;
966    __ PrepareCallCFunction(num_arguments);
967#ifdef _WIN64
968    // Microsoft passes parameters in rcx, rdx, r8.
969    // First argument, backtrack stackpointer, is already in rcx.
970    __ leap(rdx, Operand(rbp, kStackHighEnd));  // Second argument
971    __ LoadAddress(r8, ExternalReference::isolate_address(isolate()));
972#else
973    // AMD64 ABI passes parameters in rdi, rsi, rdx.
974    __ movp(rdi, backtrack_stackpointer());   // First argument.
975    __ leap(rsi, Operand(rbp, kStackHighEnd));  // Second argument.
976    __ LoadAddress(rdx, ExternalReference::isolate_address(isolate()));
977#endif
978    ExternalReference grow_stack =
979        ExternalReference::re_grow_stack(isolate());
980    __ CallCFunction(grow_stack, num_arguments);
981    // If return NULL, we have failed to grow the stack, and
982    // must exit with a stack-overflow exception.
983    __ testp(rax, rax);
984    __ j(equal, &exit_with_exception);
985    // Otherwise use return value as new stack pointer.
986    __ movp(backtrack_stackpointer(), rax);
987    // Restore saved registers and continue.
988    __ Move(code_object_pointer(), masm_.CodeObject());
989#ifndef _WIN64
990    __ popq(rdi);
991    __ popq(rsi);
992#endif
993    SafeReturn();
994  }
995
996  if (exit_with_exception.is_linked()) {
997    // If any of the code above needed to exit with an exception.
998    __ bind(&exit_with_exception);
999    // Exit with Result EXCEPTION(-1) to signal thrown exception.
1000    __ Set(rax, EXCEPTION);
1001    __ jmp(&return_rax);
1002  }
1003
1004  FixupCodeRelativePositions();
1005
1006  CodeDesc code_desc;
1007  masm_.GetCode(&code_desc);
1008  Isolate* isolate = this->isolate();
1009  Handle<Code> code = isolate->factory()->NewCode(
1010      code_desc, Code::ComputeFlags(Code::REGEXP),
1011      masm_.CodeObject());
1012  PROFILE(isolate, RegExpCodeCreateEvent(AbstractCode::cast(*code), *source));
1013  return Handle<HeapObject>::cast(code);
1014}
1015
1016
1017void RegExpMacroAssemblerX64::GoTo(Label* to) {
1018  BranchOrBacktrack(no_condition, to);
1019}
1020
1021
1022void RegExpMacroAssemblerX64::IfRegisterGE(int reg,
1023                                           int comparand,
1024                                           Label* if_ge) {
1025  __ cmpp(register_location(reg), Immediate(comparand));
1026  BranchOrBacktrack(greater_equal, if_ge);
1027}
1028
1029
1030void RegExpMacroAssemblerX64::IfRegisterLT(int reg,
1031                                           int comparand,
1032                                           Label* if_lt) {
1033  __ cmpp(register_location(reg), Immediate(comparand));
1034  BranchOrBacktrack(less, if_lt);
1035}
1036
1037
1038void RegExpMacroAssemblerX64::IfRegisterEqPos(int reg,
1039                                              Label* if_eq) {
1040  __ cmpp(rdi, register_location(reg));
1041  BranchOrBacktrack(equal, if_eq);
1042}
1043
1044
1045RegExpMacroAssembler::IrregexpImplementation
1046    RegExpMacroAssemblerX64::Implementation() {
1047  return kX64Implementation;
1048}
1049
1050
1051void RegExpMacroAssemblerX64::LoadCurrentCharacter(int cp_offset,
1052                                                   Label* on_end_of_input,
1053                                                   bool check_bounds,
1054                                                   int characters) {
1055  DCHECK(cp_offset < (1<<30));  // Be sane! (And ensure negation works)
1056  if (check_bounds) {
1057    if (cp_offset >= 0) {
1058      CheckPosition(cp_offset + characters - 1, on_end_of_input);
1059    } else {
1060      CheckPosition(cp_offset, on_end_of_input);
1061    }
1062  }
1063  LoadCurrentCharacterUnchecked(cp_offset, characters);
1064}
1065
1066
1067void RegExpMacroAssemblerX64::PopCurrentPosition() {
1068  Pop(rdi);
1069}
1070
1071
1072void RegExpMacroAssemblerX64::PopRegister(int register_index) {
1073  Pop(rax);
1074  __ movp(register_location(register_index), rax);
1075}
1076
1077
1078void RegExpMacroAssemblerX64::PushBacktrack(Label* label) {
1079  Push(label);
1080  CheckStackLimit();
1081}
1082
1083
1084void RegExpMacroAssemblerX64::PushCurrentPosition() {
1085  Push(rdi);
1086}
1087
1088
1089void RegExpMacroAssemblerX64::PushRegister(int register_index,
1090                                           StackCheckFlag check_stack_limit) {
1091  __ movp(rax, register_location(register_index));
1092  Push(rax);
1093  if (check_stack_limit) CheckStackLimit();
1094}
1095
1096
1097STATIC_ASSERT(kPointerSize == kInt64Size || kPointerSize == kInt32Size);
1098
1099
1100void RegExpMacroAssemblerX64::ReadCurrentPositionFromRegister(int reg) {
1101  if (kPointerSize == kInt64Size) {
1102    __ movq(rdi, register_location(reg));
1103  } else {
1104    // Need sign extension for x32 as rdi might be used as an index register.
1105    __ movsxlq(rdi, register_location(reg));
1106  }
1107}
1108
1109
1110void RegExpMacroAssemblerX64::ReadPositionFromRegister(Register dst, int reg) {
1111  if (kPointerSize == kInt64Size) {
1112    __ movq(dst, register_location(reg));
1113  } else {
1114    // Need sign extension for x32 as dst might be used as an index register.
1115    __ movsxlq(dst, register_location(reg));
1116  }
1117}
1118
1119
1120void RegExpMacroAssemblerX64::ReadStackPointerFromRegister(int reg) {
1121  __ movp(backtrack_stackpointer(), register_location(reg));
1122  __ addp(backtrack_stackpointer(), Operand(rbp, kStackHighEnd));
1123}
1124
1125
1126void RegExpMacroAssemblerX64::SetCurrentPositionFromEnd(int by) {
1127  Label after_position;
1128  __ cmpp(rdi, Immediate(-by * char_size()));
1129  __ j(greater_equal, &after_position, Label::kNear);
1130  __ movq(rdi, Immediate(-by * char_size()));
1131  // On RegExp code entry (where this operation is used), the character before
1132  // the current position is expected to be already loaded.
1133  // We have advanced the position, so it's safe to read backwards.
1134  LoadCurrentCharacterUnchecked(-1, 1);
1135  __ bind(&after_position);
1136}
1137
1138
1139void RegExpMacroAssemblerX64::SetRegister(int register_index, int to) {
1140  DCHECK(register_index >= num_saved_registers_);  // Reserved for positions!
1141  __ movp(register_location(register_index), Immediate(to));
1142}
1143
1144
1145bool RegExpMacroAssemblerX64::Succeed() {
1146  __ jmp(&success_label_);
1147  return global();
1148}
1149
1150
1151void RegExpMacroAssemblerX64::WriteCurrentPositionToRegister(int reg,
1152                                                             int cp_offset) {
1153  if (cp_offset == 0) {
1154    __ movp(register_location(reg), rdi);
1155  } else {
1156    __ leap(rax, Operand(rdi, cp_offset * char_size()));
1157    __ movp(register_location(reg), rax);
1158  }
1159}
1160
1161
1162void RegExpMacroAssemblerX64::ClearRegisters(int reg_from, int reg_to) {
1163  DCHECK(reg_from <= reg_to);
1164  __ movp(rax, Operand(rbp, kStringStartMinusOne));
1165  for (int reg = reg_from; reg <= reg_to; reg++) {
1166    __ movp(register_location(reg), rax);
1167  }
1168}
1169
1170
1171void RegExpMacroAssemblerX64::WriteStackPointerToRegister(int reg) {
1172  __ movp(rax, backtrack_stackpointer());
1173  __ subp(rax, Operand(rbp, kStackHighEnd));
1174  __ movp(register_location(reg), rax);
1175}
1176
1177
1178// Private methods:
1179
1180void RegExpMacroAssemblerX64::CallCheckStackGuardState() {
1181  // This function call preserves no register values. Caller should
1182  // store anything volatile in a C call or overwritten by this function.
1183  static const int num_arguments = 3;
1184  __ PrepareCallCFunction(num_arguments);
1185#ifdef _WIN64
1186  // Second argument: Code* of self. (Do this before overwriting r8).
1187  __ movp(rdx, code_object_pointer());
1188  // Third argument: RegExp code frame pointer.
1189  __ movp(r8, rbp);
1190  // First argument: Next address on the stack (will be address of
1191  // return address).
1192  __ leap(rcx, Operand(rsp, -kPointerSize));
1193#else
1194  // Third argument: RegExp code frame pointer.
1195  __ movp(rdx, rbp);
1196  // Second argument: Code* of self.
1197  __ movp(rsi, code_object_pointer());
1198  // First argument: Next address on the stack (will be address of
1199  // return address).
1200  __ leap(rdi, Operand(rsp, -kRegisterSize));
1201#endif
1202  ExternalReference stack_check =
1203      ExternalReference::re_check_stack_guard_state(isolate());
1204  __ CallCFunction(stack_check, num_arguments);
1205}
1206
1207
1208// Helper function for reading a value out of a stack frame.
1209template <typename T>
1210static T& frame_entry(Address re_frame, int frame_offset) {
1211  return reinterpret_cast<T&>(Memory::int32_at(re_frame + frame_offset));
1212}
1213
1214
1215template <typename T>
1216static T* frame_entry_address(Address re_frame, int frame_offset) {
1217  return reinterpret_cast<T*>(re_frame + frame_offset);
1218}
1219
1220
1221int RegExpMacroAssemblerX64::CheckStackGuardState(Address* return_address,
1222                                                  Code* re_code,
1223                                                  Address re_frame) {
1224  return NativeRegExpMacroAssembler::CheckStackGuardState(
1225      frame_entry<Isolate*>(re_frame, kIsolate),
1226      frame_entry<int>(re_frame, kStartIndex),
1227      frame_entry<int>(re_frame, kDirectCall) == 1, return_address, re_code,
1228      frame_entry_address<String*>(re_frame, kInputString),
1229      frame_entry_address<const byte*>(re_frame, kInputStart),
1230      frame_entry_address<const byte*>(re_frame, kInputEnd));
1231}
1232
1233
1234Operand RegExpMacroAssemblerX64::register_location(int register_index) {
1235  DCHECK(register_index < (1<<30));
1236  if (num_registers_ <= register_index) {
1237    num_registers_ = register_index + 1;
1238  }
1239  return Operand(rbp, kRegisterZero - register_index * kPointerSize);
1240}
1241
1242
1243void RegExpMacroAssemblerX64::CheckPosition(int cp_offset,
1244                                            Label* on_outside_input) {
1245  if (cp_offset >= 0) {
1246    __ cmpl(rdi, Immediate(-cp_offset * char_size()));
1247    BranchOrBacktrack(greater_equal, on_outside_input);
1248  } else {
1249    __ leap(rax, Operand(rdi, cp_offset * char_size()));
1250    __ cmpp(rax, Operand(rbp, kStringStartMinusOne));
1251    BranchOrBacktrack(less_equal, on_outside_input);
1252  }
1253}
1254
1255
1256void RegExpMacroAssemblerX64::BranchOrBacktrack(Condition condition,
1257                                                Label* to) {
1258  if (condition < 0) {  // No condition
1259    if (to == NULL) {
1260      Backtrack();
1261      return;
1262    }
1263    __ jmp(to);
1264    return;
1265  }
1266  if (to == NULL) {
1267    __ j(condition, &backtrack_label_);
1268    return;
1269  }
1270  __ j(condition, to);
1271}
1272
1273
1274void RegExpMacroAssemblerX64::SafeCall(Label* to) {
1275  __ call(to);
1276}
1277
1278
1279void RegExpMacroAssemblerX64::SafeCallTarget(Label* label) {
1280  __ bind(label);
1281  __ subp(Operand(rsp, 0), code_object_pointer());
1282}
1283
1284
1285void RegExpMacroAssemblerX64::SafeReturn() {
1286  __ addp(Operand(rsp, 0), code_object_pointer());
1287  __ ret(0);
1288}
1289
1290
1291void RegExpMacroAssemblerX64::Push(Register source) {
1292  DCHECK(!source.is(backtrack_stackpointer()));
1293  // Notice: This updates flags, unlike normal Push.
1294  __ subp(backtrack_stackpointer(), Immediate(kIntSize));
1295  __ movl(Operand(backtrack_stackpointer(), 0), source);
1296}
1297
1298
1299void RegExpMacroAssemblerX64::Push(Immediate value) {
1300  // Notice: This updates flags, unlike normal Push.
1301  __ subp(backtrack_stackpointer(), Immediate(kIntSize));
1302  __ movl(Operand(backtrack_stackpointer(), 0), value);
1303}
1304
1305
1306void RegExpMacroAssemblerX64::FixupCodeRelativePositions() {
1307  for (int i = 0, n = code_relative_fixup_positions_.length(); i < n; i++) {
1308    int position = code_relative_fixup_positions_[i];
1309    // The position succeeds a relative label offset from position.
1310    // Patch the relative offset to be relative to the Code object pointer
1311    // instead.
1312    int patch_position = position - kIntSize;
1313    int offset = masm_.long_at(patch_position);
1314    masm_.long_at_put(patch_position,
1315                       offset
1316                       + position
1317                       + Code::kHeaderSize
1318                       - kHeapObjectTag);
1319  }
1320  code_relative_fixup_positions_.Clear();
1321}
1322
1323
1324void RegExpMacroAssemblerX64::Push(Label* backtrack_target) {
1325  __ subp(backtrack_stackpointer(), Immediate(kIntSize));
1326  __ movl(Operand(backtrack_stackpointer(), 0), backtrack_target);
1327  MarkPositionForCodeRelativeFixup();
1328}
1329
1330
1331void RegExpMacroAssemblerX64::Pop(Register target) {
1332  DCHECK(!target.is(backtrack_stackpointer()));
1333  __ movsxlq(target, Operand(backtrack_stackpointer(), 0));
1334  // Notice: This updates flags, unlike normal Pop.
1335  __ addp(backtrack_stackpointer(), Immediate(kIntSize));
1336}
1337
1338
1339void RegExpMacroAssemblerX64::Drop() {
1340  __ addp(backtrack_stackpointer(), Immediate(kIntSize));
1341}
1342
1343
1344void RegExpMacroAssemblerX64::CheckPreemption() {
1345  // Check for preemption.
1346  Label no_preempt;
1347  ExternalReference stack_limit =
1348      ExternalReference::address_of_stack_limit(isolate());
1349  __ load_rax(stack_limit);
1350  __ cmpp(rsp, rax);
1351  __ j(above, &no_preempt);
1352
1353  SafeCall(&check_preempt_label_);
1354
1355  __ bind(&no_preempt);
1356}
1357
1358
1359void RegExpMacroAssemblerX64::CheckStackLimit() {
1360  Label no_stack_overflow;
1361  ExternalReference stack_limit =
1362      ExternalReference::address_of_regexp_stack_limit(isolate());
1363  __ load_rax(stack_limit);
1364  __ cmpp(backtrack_stackpointer(), rax);
1365  __ j(above, &no_stack_overflow);
1366
1367  SafeCall(&stack_overflow_label_);
1368
1369  __ bind(&no_stack_overflow);
1370}
1371
1372
1373void RegExpMacroAssemblerX64::LoadCurrentCharacterUnchecked(int cp_offset,
1374                                                            int characters) {
1375  if (mode_ == LATIN1) {
1376    if (characters == 4) {
1377      __ movl(current_character(), Operand(rsi, rdi, times_1, cp_offset));
1378    } else if (characters == 2) {
1379      __ movzxwl(current_character(), Operand(rsi, rdi, times_1, cp_offset));
1380    } else {
1381      DCHECK(characters == 1);
1382      __ movzxbl(current_character(), Operand(rsi, rdi, times_1, cp_offset));
1383    }
1384  } else {
1385    DCHECK(mode_ == UC16);
1386    if (characters == 2) {
1387      __ movl(current_character(),
1388              Operand(rsi, rdi, times_1, cp_offset * sizeof(uc16)));
1389    } else {
1390      DCHECK(characters == 1);
1391      __ movzxwl(current_character(),
1392                 Operand(rsi, rdi, times_1, cp_offset * sizeof(uc16)));
1393    }
1394  }
1395}
1396
1397#undef __
1398
1399#endif  // V8_INTERPRETED_REGEXP
1400
1401}  // namespace internal
1402}  // namespace v8
1403
1404#endif  // V8_TARGET_ARCH_X64
1405