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