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