regexp-macro-assembler-x64.cc revision f87a203d89e1bbb6708282e0b64dbd13d59b723d
1a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Copyright 2009 the V8 project authors. All rights reserved. 2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without 3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are 4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met: 5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions of source code must retain the above copyright 7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// notice, this list of conditions and the following disclaimer. 8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Redistributions in binary form must reproduce the above 9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// copyright notice, this list of conditions and the following 10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// disclaimer in the documentation and/or other materials provided 11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// with the distribution. 12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// * Neither the name of Google Inc. nor the names of its 13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// contributors may be used to endorse or promote products derived 14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// from this software without specific prior written permission. 15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// 16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "v8.h" 29f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 30f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#if defined(V8_TARGET_ARCH_X64) 31f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "serialize.h" 33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "unicode.h" 34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "log.h" 35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "regexp-stack.h" 36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "macro-assembler.h" 37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "regexp-macro-assembler.h" 38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "x64/regexp-macro-assembler-x64.h" 39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 { 41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal { 42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#ifndef V8_INTERPRETED_REGEXP 44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block/* 46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * This assembler uses the following register assignment convention 47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - rdx : currently loaded character(s) as ASCII or UC16. Must be loaded using 48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * LoadCurrentCharacter before using any of the dispatch methods. 49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - rdi : current position in input, as negative offset from end of string. 50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * Please notice that this is the byte offset, not the character 51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * offset! Is always a 32-bit signed (negative) offset, but must be 52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * maintained sign-extended to 64 bits, since it is used as index. 53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - rsi : end of input (points to byte after last character in input), 54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * so that rsi+rdi points to the current character. 55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - rbp : frame pointer. Used to access arguments, local variables and 56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * RegExp registers. 57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - rsp : points to tip of C stack. 58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - rcx : points to tip of backtrack stack. The backtrack stack contains 59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * only 32-bit values. Most are offsets from some base (e.g., character 60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * positions from end of string or code location from Code* pointer). 61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - r8 : code object pointer. Used to convert between absolute and 62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * code-object-relative addresses. 63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * 64e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * The registers rax, rbx, r9 and r11 are free to use for computations. 65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * If changed to use r12+, they should be saved as callee-save registers. 66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * 67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * Each call to a C++ method should retain these registers. 68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * 69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * The stack will have the following content, in some order, indexable from the 70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * frame pointer (see, e.g., kStackHighEnd): 71e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * - direct_call (if 1, direct call from JavaScript code, if 0 call 72e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * through the runtime system) 73e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * - stack_area_base (High end of the memory area to use as 74e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * backtracking stack) 75e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * - int* capture_array (int[num_saved_registers_], for output). 76e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * - end of input (Address of end of string) 77e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * - start of input (Address of first character in string) 78e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * - start index (character index of start) 79e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * - String* input_string (input string) 80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - return address 81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - backup of callee save registers (rbx, possibly rsi and rdi). 82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - Offset of location before start of input (effectively character 83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * position -1). Used to initialize capture registers to a non-position. 84d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke * - At start of string (if 1, we are starting at the start of the 85d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke * string, otherwise 0) 86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - register 0 rbp[-n] (Only positions must be stored in the first 87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - register 1 rbp[-n-8] num_saved_registers_ registers) 88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - ... 89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * 90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * The first num_saved_registers_ registers are initialized to point to 91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * "character -1" in the string (i.e., char_size() bytes before the first 92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * character of the string). The remaining registers starts out uninitialized. 93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * 94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * The first seven values must be provided by the calling code by 95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * calling the code's entry address cast to a function pointer with the 96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * following signature: 97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * int (*match)(String* input_string, 98e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * int start_index, 99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * Address start, 100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * Address end, 101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * int* capture_output_array, 102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * bool at_start, 103e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * byte* stack_area_base, 104e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * bool direct_call) 105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block */ 106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define __ ACCESS_MASM(masm_) 108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegExpMacroAssemblerX64::RegExpMacroAssemblerX64( 110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Mode mode, 111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int registers_to_save) 112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block : masm_(new MacroAssembler(NULL, kRegExpCodeSize)), 113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block code_relative_fixup_positions_(4), 114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mode_(mode), 115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block num_registers_(registers_to_save), 116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block num_saved_registers_(registers_to_save), 117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block entry_label_(), 118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block start_label_(), 119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block success_label_(), 120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block backtrack_label_(), 121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block exit_label_() { 122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(0, registers_to_save % 2); 123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&entry_label_); // We'll write the entry code when we know more. 124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&start_label_); // And then continue from here. 125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegExpMacroAssemblerX64::~RegExpMacroAssemblerX64() { 129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block delete masm_; 130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Unuse labels in case we throw away the assembler without calling GetCode. 131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block entry_label_.Unuse(); 132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block start_label_.Unuse(); 133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block success_label_.Unuse(); 134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block backtrack_label_.Unuse(); 135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block exit_label_.Unuse(); 136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block check_preempt_label_.Unuse(); 137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block stack_overflow_label_.Unuse(); 138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint RegExpMacroAssemblerX64::stack_limit_slack() { 142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return RegExpStack::kStackLimitSlack; 143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::AdvanceCurrentPosition(int by) { 147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (by != 0) { 148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ addq(rdi, Immediate(by * char_size())); 149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::AdvanceRegister(int reg, int by) { 154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(reg >= 0); 155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(reg < num_registers_); 156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (by != 0) { 157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ addq(register_location(reg), Immediate(by)); 158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::Backtrack() { 163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CheckPreemption(); 164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Pop Code* offset from backtrack stack, add Code* and jump to location. 165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Pop(rbx); 166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ addq(rbx, code_object_pointer()); 167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(rbx); 168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::Bind(Label* label) { 172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(label); 173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::CheckCharacter(uint32_t c, Label* on_equal) { 177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpl(current_character(), Immediate(c)); 178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(equal, on_equal); 179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::CheckCharacterGT(uc16 limit, Label* on_greater) { 183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpl(current_character(), Immediate(limit)); 184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(greater, on_greater); 185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::CheckAtStart(Label* on_at_start) { 189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label not_at_start; 190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Did we start the match at the start of the string at all? 19125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ cmpb(Operand(rbp, kStartIndex), Immediate(0)); 19225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen BranchOrBacktrack(not_equal, ¬_at_start); 193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If we did, are we still at the start of the input? 194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(rax, Operand(rsi, rdi, times_1, 0)); 195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpq(rax, Operand(rbp, kInputStart)); 196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(equal, on_at_start); 197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(¬_at_start); 198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::CheckNotAtStart(Label* on_not_at_start) { 202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Did we start the match at the start of the string at all? 20325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ cmpb(Operand(rbp, kStartIndex), Immediate(0)); 20425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen BranchOrBacktrack(not_equal, on_not_at_start); 205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If we did, are we still at the start of the input? 206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(rax, Operand(rsi, rdi, times_1, 0)); 207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpq(rax, Operand(rbp, kInputStart)); 208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(not_equal, on_not_at_start); 209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::CheckCharacterLT(uc16 limit, Label* on_less) { 213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpl(current_character(), Immediate(limit)); 214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(less, on_less); 215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::CheckCharacters(Vector<const uc16> str, 219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int cp_offset, 220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_failure, 221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool check_end_of_string) { 22225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen#ifdef DEBUG 22325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // If input is ASCII, don't even bother calling here if the string to 22425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // match contains a non-ascii character. 22525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen if (mode_ == ASCII) { 22625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen for (int i = 0; i < str.length(); i++) { 22725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen ASSERT(str[i] <= String::kMaxAsciiCharCodeU); 22825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } 22925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } 23025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen#endif 231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int byte_length = str.length() * char_size(); 232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int byte_offset = cp_offset * char_size(); 233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (check_end_of_string) { 234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that there are at least str.length() characters left in the input. 235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpl(rdi, Immediate(-(byte_offset + byte_length))); 236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(greater, on_failure); 237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (on_failure == NULL) { 240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Instead of inlining a backtrack, (re)use the global backtrack target. 241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block on_failure = &backtrack_label_; 242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 24425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // Do one character test first to minimize loading for the case that 24525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // we don't match at all (loading more than one character introduces that 24625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // chance of reading unaligned and reading across cache boundaries). 24725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // If the first character matches, expect a larger chance of matching the 24825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // string, and start loading more characters at a time. 24925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen if (mode_ == ASCII) { 25025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ cmpb(Operand(rsi, rdi, times_1, byte_offset), 25125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen Immediate(static_cast<int8_t>(str[0]))); 25225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } else { 25325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // Don't use 16-bit immediate. The size changing prefix throws off 25425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // pre-decoding. 25525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ movzxwl(rax, 25625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen Operand(rsi, rdi, times_1, byte_offset)); 25725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ cmpl(rax, Immediate(static_cast<int32_t>(str[0]))); 25825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } 25925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen BranchOrBacktrack(not_equal, on_failure); 26025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen 26125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ lea(rbx, Operand(rsi, rdi, times_1, 0)); 26225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen for (int i = 1, n = str.length(); i < n; ) { 263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mode_ == ASCII) { 26425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen if (i + 8 <= n) { 26525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen uint64_t combined_chars = 26625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen (static_cast<uint64_t>(str[i + 0]) << 0) || 26725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen (static_cast<uint64_t>(str[i + 1]) << 8) || 26825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen (static_cast<uint64_t>(str[i + 2]) << 16) || 26925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen (static_cast<uint64_t>(str[i + 3]) << 24) || 27025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen (static_cast<uint64_t>(str[i + 4]) << 32) || 27125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen (static_cast<uint64_t>(str[i + 5]) << 40) || 27225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen (static_cast<uint64_t>(str[i + 6]) << 48) || 27325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen (static_cast<uint64_t>(str[i + 7]) << 56); 27425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ movq(rax, combined_chars, RelocInfo::NONE); 27525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ cmpq(rax, Operand(rbx, byte_offset + i)); 27625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen i += 8; 27725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } else if (i + 4 <= n) { 27825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen uint32_t combined_chars = 27925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen (static_cast<uint32_t>(str[i + 0]) << 0) || 28025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen (static_cast<uint32_t>(str[i + 1]) << 8) || 28125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen (static_cast<uint32_t>(str[i + 2]) << 16) || 28225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen (static_cast<uint32_t>(str[i + 3]) << 24); 28325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ cmpl(Operand(rbx, byte_offset + i), Immediate(combined_chars)); 28425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen i += 4; 28525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } else { 28625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ cmpb(Operand(rbx, byte_offset + i), 28725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen Immediate(static_cast<int8_t>(str[i]))); 28825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen i++; 28925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } 290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(mode_ == UC16); 29225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen if (i + 4 <= n) { 29325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen uint64_t combined_chars = *reinterpret_cast<const uint64_t*>(&str[i]); 29425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ movq(rax, combined_chars, RelocInfo::NONE); 29525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ cmpq(rax, 29625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen Operand(rsi, rdi, times_1, byte_offset + i * sizeof(uc16))); 29725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen i += 4; 29825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } else if (i + 2 <= n) { 29925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen uint32_t combined_chars = *reinterpret_cast<const uint32_t*>(&str[i]); 30025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ cmpl(Operand(rsi, rdi, times_1, byte_offset + i * sizeof(uc16)), 30125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen Immediate(combined_chars)); 30225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen i += 2; 30325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } else { 30425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ movzxwl(rax, 30525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen Operand(rsi, rdi, times_1, byte_offset + i * sizeof(uc16))); 30625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ cmpl(rax, Immediate(str[i])); 30725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen i++; 30825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } 309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(not_equal, on_failure); 311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::CheckGreedyLoop(Label* on_equal) { 316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label fallthrough; 317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpl(rdi, Operand(backtrack_stackpointer(), 0)); 318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &fallthrough); 319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Drop(); 320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(no_condition, on_equal); 321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&fallthrough); 322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::CheckNotBackReferenceIgnoreCase( 326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int start_reg, 327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_no_match) { 328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label fallthrough; 329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rdx, register_location(start_reg)); // Offset of start of capture 330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rbx, register_location(start_reg + 1)); // Offset of end of capture 331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ subq(rbx, rdx); // Length of capture. 332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------- 334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // rdx = Start offset of capture. 335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // rbx = Length of capture 336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If length is negative, this code will fail (it's a symptom of a partial or 338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // illegal capture where start of capture after end of capture). 339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // This must not happen (no back-reference can reference a capture that wasn't 340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // closed before in the reg-exp, and we must not generate code that can cause 341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // this condition). 342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If length is zero, either the capture is empty or it is nonparticipating. 344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // In either case succeed immediately. 345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, &fallthrough); 346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mode_ == ASCII) { 348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label loop_increment; 349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (on_no_match == NULL) { 350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block on_no_match = &backtrack_label_; 351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(r9, Operand(rsi, rdx, times_1, 0)); 354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(r11, Operand(rsi, rdi, times_1, 0)); 355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ addq(rbx, r9); // End of capture 356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------- 357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r11 - current input character address 358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r9 - current capture character address 359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // rbx - end of capture 360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label loop; 362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&loop); 363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzxbl(rdx, Operand(r9, 0)); 364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzxbl(rax, Operand(r11, 0)); 365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // al - input character 366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // dl - capture character 367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpb(rax, rdx); 368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, &loop_increment); 369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Mismatch, try case-insensitive match (converting letters to lower-case). 371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // I.e., if or-ing with 0x20 makes values equal and in range 'a'-'z', it's 372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // a match. 373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ or_(rax, Immediate(0x20)); // Convert match character to lower-case. 374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ or_(rdx, Immediate(0x20)); // Convert capture character to lower-case. 375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpb(rax, rdx); 376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, on_no_match); // Definitely not equal. 377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ subb(rax, Immediate('a')); 378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpb(rax, Immediate('z' - 'a')); 379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(above, on_no_match); // Weren't letters anyway. 380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&loop_increment); 382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Increment pointers into match and capture strings. 383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ addq(r11, Immediate(1)); 384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ addq(r9, Immediate(1)); 385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compare to end of capture, and loop if not done. 386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpq(r9, rbx); 387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(below, &loop); 388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compute new value of character position after the matched part. 390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rdi, r11); 391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ subq(rdi, rsi); 392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(mode_ == UC16); 394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Save important/volatile registers before calling C function. 395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifndef _WIN64 3964515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Caller save on Linux and callee save in Windows. 397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(rsi); 398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(rdi); 399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(backtrack_stackpointer()); 401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 4026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block static const int num_arguments = 3; 4034515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ PrepareCallCFunction(num_arguments); 404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Put arguments into parameter registers. Parameters are 406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Address byte_offset1 - Address captured substring's start. 407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Address byte_offset2 - Address of current character position. 408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // size_t byte_length - length of capture in bytes(!) 409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef _WIN64 410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compute and set byte_offset1 (start of capture). 411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(rcx, Operand(rsi, rdx, times_1, 0)); 412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set byte_offset2. 413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(rdx, Operand(rsi, rdi, times_1, 0)); 414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set byte_length. 415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(r8, rbx); 416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#else // AMD64 calling convention 417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compute byte_offset2 (current position = rsi+rdi). 418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(rax, Operand(rsi, rdi, times_1, 0)); 419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compute and set byte_offset1 (start of capture). 420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(rdi, Operand(rsi, rdx, times_1, 0)); 421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set byte_offset2. 422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rsi, rax); 423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set byte_length. 424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rdx, rbx); 425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference compare = 427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference::re_case_insensitive_compare_uc16(); 4284515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ CallCFunction(compare, num_arguments); 429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore original values before reacting on result value. 431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Move(code_object_pointer(), masm_->CodeObject()); 432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(backtrack_stackpointer()); 433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifndef _WIN64 434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(rdi); 435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(rsi); 436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if function returned non-zero for success or zero for failure. 439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ testq(rax, rax); 440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(zero, on_no_match); 441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // On success, increment position by length of capture. 442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Requires that rbx is callee save (true for both Win64 and AMD64 ABIs). 443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ addq(rdi, rbx); 444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&fallthrough); 446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::CheckNotBackReference( 450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int start_reg, 451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_no_match) { 452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label fallthrough; 453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Find length of back-referenced capture. 455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rdx, register_location(start_reg)); 456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rax, register_location(start_reg + 1)); 457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ subq(rax, rdx); // Length to check. 458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fail on partial or illegal capture (start of capture after end of capture). 460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // This must not happen (no back-reference can reference a capture that wasn't 461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // closed before in the reg-exp). 462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Check(greater_equal, "Invalid capture referenced"); 463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Succeed on empty capture (including non-participating capture) 465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, &fallthrough); 466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------- 468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // rdx - Start of capture 469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // rax - length of capture 470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that there are sufficient characters left in the input. 472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movl(rbx, rdi); 473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ addl(rbx, rax); 474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(greater, on_no_match); 475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compute pointers to match string and capture string 477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(rbx, Operand(rsi, rdi, times_1, 0)); // Start of match. 478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ addq(rdx, rsi); // Start of capture. 479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(r9, Operand(rdx, rax, times_1, 0)); // End of capture 480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------- 482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // rbx - current capture character address. 483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // rbx - current input character address . 484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r9 - end of input to match (capture length after rbx). 485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label loop; 487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&loop); 488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mode_ == ASCII) { 489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzxbl(rax, Operand(rdx, 0)); 490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpb(rax, Operand(rbx, 0)); 491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(mode_ == UC16); 493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzxwl(rax, Operand(rdx, 0)); 494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpw(rax, Operand(rbx, 0)); 495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(not_equal, on_no_match); 497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Increment pointers into capture and match string. 498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ addq(rbx, Immediate(char_size())); 499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ addq(rdx, Immediate(char_size())); 500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if we have reached end of match area. 501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpq(rdx, r9); 502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(below, &loop); 503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Success. 505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set current character position to position after match. 506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rdi, rbx); 507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ subq(rdi, rsi); 508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&fallthrough); 510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::CheckNotRegistersEqual(int reg1, 514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int reg2, 515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_not_equal) { 516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rax, register_location(reg1)); 517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpq(rax, register_location(reg2)); 518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(not_equal, on_not_equal); 519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::CheckNotCharacter(uint32_t c, 523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_not_equal) { 524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpl(current_character(), Immediate(c)); 525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(not_equal, on_not_equal); 526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::CheckCharacterAfterAnd(uint32_t c, 530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uint32_t mask, 531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_equal) { 532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movl(rax, current_character()); 533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ and_(rax, Immediate(mask)); 534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpl(rax, Immediate(c)); 535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(equal, on_equal); 536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::CheckNotCharacterAfterAnd(uint32_t c, 540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uint32_t mask, 541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_not_equal) { 542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movl(rax, current_character()); 543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ and_(rax, Immediate(mask)); 544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpl(rax, Immediate(c)); 545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(not_equal, on_not_equal); 546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::CheckNotCharacterAfterMinusAnd( 550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uc16 c, 551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uc16 minus, 552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uc16 mask, 553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_not_equal) { 554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(minus < String::kMaxUC16CharCode); 555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(rax, Operand(current_character(), -minus)); 556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ and_(rax, Immediate(mask)); 557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpl(rax, Immediate(c)); 558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(not_equal, on_not_equal); 559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool RegExpMacroAssemblerX64::CheckSpecialCharacterClass(uc16 type, 563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_no_match) { 564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Range checks (c in min..max) are generally implemented by an unsigned 565e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // (c - min) <= (max - min) check, using the sequence: 566e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // lea(rax, Operand(current_character(), -min)) or sub(rax, Immediate(min)) 567e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // cmp(rax, Immediate(max - min)) 568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (type) { 569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 's': 570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Match space-characters 571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mode_ == ASCII) { 572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ASCII space characters are '\t'..'\r' and ' '. 573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label success; 574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpl(current_character(), Immediate(' ')); 575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, &success); 576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check range 0x09..0x0d 577e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ lea(rax, Operand(current_character(), -'\t')); 578e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmpl(rax, Immediate('\r' - '\t')); 579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(above, on_no_match); 580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&success); 581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return false; 584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 'S': 585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Match non-space characters. 586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mode_ == ASCII) { 587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ASCII space characters are '\t'..'\r' and ' '. 588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpl(current_character(), Immediate(' ')); 589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(equal, on_no_match); 590e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ lea(rax, Operand(current_character(), -'\t')); 591e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmpl(rax, Immediate('\r' - '\t')); 592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(below_equal, on_no_match); 593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return false; 596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 'd': 597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Match ASCII digits ('0'..'9') 598e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ lea(rax, Operand(current_character(), -'0')); 599e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmpl(rax, Immediate('9' - '0')); 600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(above, on_no_match); 601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 'D': 603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Match non ASCII-digits 604e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ lea(rax, Operand(current_character(), -'0')); 605e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmpl(rax, Immediate('9' - '0')); 606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(below_equal, on_no_match); 607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case '.': { 609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Match non-newlines (not 0x0a('\n'), 0x0d('\r'), 0x2028 and 0x2029) 610e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movl(rax, current_character()); 611e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ xor_(rax, Immediate(0x01)); 612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c 613e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ subl(rax, Immediate(0x0b)); 614e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmpl(rax, Immediate(0x0c - 0x0b)); 615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(below_equal, on_no_match); 616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mode_ == UC16) { 617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compare original value to 0x2028 and 0x2029, using the already 618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // computed (current_char ^ 0x01 - 0x0b). I.e., check for 619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 0x201d (0x2028 - 0x0b) or 0x201e. 620e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ subl(rax, Immediate(0x2028 - 0x0b)); 621e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmpl(rax, Immediate(0x2029 - 0x2028)); 622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(below_equal, on_no_match); 623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 626e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case 'n': { 627e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Match newlines (0x0a('\n'), 0x0d('\r'), 0x2028 and 0x2029) 628e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movl(rax, current_character()); 629e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ xor_(rax, Immediate(0x01)); 630e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c 631e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ subl(rax, Immediate(0x0b)); 632e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmpl(rax, Immediate(0x0c - 0x0b)); 633e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (mode_ == ASCII) { 634e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke BranchOrBacktrack(above, on_no_match); 635e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 636e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label done; 637e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke BranchOrBacktrack(below_equal, &done); 638e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Compare original value to 0x2028 and 0x2029, using the already 639e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // computed (current_char ^ 0x01 - 0x0b). I.e., check for 640e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // 0x201d (0x2028 - 0x0b) or 0x201e. 641e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ subl(rax, Immediate(0x2028 - 0x0b)); 642e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmpl(rax, Immediate(0x2029 - 0x2028)); 643e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke BranchOrBacktrack(above, on_no_match); 644e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(&done); 645e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 646e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return true; 647e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 648e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case 'w': { 649e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (mode_ != ASCII) { 650e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Table is 128 entries, so all ASCII characters can be tested. 651e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmpl(current_character(), Immediate('z')); 652e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke BranchOrBacktrack(above, on_no_match); 653e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 654e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(rbx, ExternalReference::re_word_character_map()); 655e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_EQ(0, word_character_map[0]); // Character '\0' is not a word char. 656e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ExternalReference word_map = ExternalReference::re_word_character_map(); 657e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ testb(Operand(rbx, current_character(), times_1, 0), 658e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke current_character()); 659e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke BranchOrBacktrack(zero, on_no_match); 660e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return true; 661e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 662e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case 'W': { 663e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label done; 664e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (mode_ != ASCII) { 665e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Table is 128 entries, so all ASCII characters can be tested. 666e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmpl(current_character(), Immediate('z')); 667e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(above, &done); 668e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 669e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(rbx, ExternalReference::re_word_character_map()); 670e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_EQ(0, word_character_map[0]); // Character '\0' is not a word char. 671e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ExternalReference word_map = ExternalReference::re_word_character_map(); 672e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ testb(Operand(rbx, current_character(), times_1, 0), 673e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke current_character()); 674e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke BranchOrBacktrack(not_zero, on_no_match); 675e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (mode_ != ASCII) { 676e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(&done); 677e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 678e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return true; 679e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 680e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case '*': 682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Match any character. 683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 684e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // No custom implementation (yet): s(UC16), S(UC16). 685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return false; 687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::Fail() { 692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(FAILURE == 0); // Return value for failure is zero. 693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ xor_(rax, rax); // zero rax. 694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&exit_label_); 695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockHandle<Object> RegExpMacroAssemblerX64::GetCode(Handle<String> source) { 699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Finalize code - write the entry point code now we know how many 700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // registers we need. 701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Entry code: 702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&entry_label_); 703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Start new stack frame. 704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(rbp); 705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rbp, rsp); 706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Save parameters and callee-save registers. Order here should correspond 707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to order of kBackup_ebx etc. 708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef _WIN64 709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // MSVC passes arguments in rcx, rdx, r8, r9, with backing stack slots. 710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Store register parameters in pre-allocated stack slots, 711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(Operand(rbp, kInputString), rcx); 712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(Operand(rbp, kStartIndex), rdx); // Passed as int32 in edx. 713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(Operand(rbp, kInputStart), r8); 714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(Operand(rbp, kInputEnd), r9); 715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Callee-save on Win64. 716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(rsi); 717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(rdi); 718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(rbx); 719a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#else 720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // GCC passes arguments in rdi, rsi, rdx, rcx, r8, r9 (and then on stack). 721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Push register parameters on stack for reference. 722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(kInputString, -1 * kPointerSize); 723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(kStartIndex, -2 * kPointerSize); 724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(kInputStart, -3 * kPointerSize); 725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(kInputEnd, -4 * kPointerSize); 726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(kRegisterOutput, -5 * kPointerSize); 727d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke ASSERT_EQ(kStackHighEnd, -6 * kPointerSize); 728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(rdi); 729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(rsi); 730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(rdx); 731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(rcx); 732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(r8); 733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(r9); 734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(rbx); // Callee-save 736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 7374515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 738d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ push(Immediate(0)); // Make room for "at start" constant. 739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if we have space on the stack for registers. 741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label stack_limit_hit; 742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label stack_ok; 743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 744d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ExternalReference stack_limit = 745d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ExternalReference::address_of_stack_limit(); 746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rcx, rsp); 747d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ movq(kScratchRegister, stack_limit); 748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ subq(rcx, Operand(kScratchRegister, 0)); 749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle it if the stack pointer is already below the stack limit. 750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(below_equal, &stack_limit_hit); 751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if there is room for the variable number of registers above 752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the stack limit. 753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpq(rcx, Immediate(num_registers_ * kPointerSize)); 754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(above_equal, &stack_ok); 755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Exit with OutOfMemory exception. There is not enough space on the stack 756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // for our working registers. 757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rax, Immediate(EXCEPTION)); 758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&exit_label_); 759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&stack_limit_hit); 761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Move(code_object_pointer(), masm_->CodeObject()); 762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CallCheckStackGuardState(); // Preserves no registers beside rbp and rsp. 763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ testq(rax, rax); 764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If returned value is non-zero, we exit with the returned value as result. 765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_zero, &exit_label_); 766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&stack_ok); 768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Allocate space on stack for registers. 770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ subq(rsp, Immediate(num_registers_ * kPointerSize)); 771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load string length. 772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rsi, Operand(rbp, kInputEnd)); 773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load input position. 774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rdi, Operand(rbp, kInputStart)); 775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set up rdi to be negative offset from string end. 776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ subq(rdi, rsi); 7776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Set rax to address of char before start of the string 778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // (effectively string position -1). 7796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ movq(rbx, Operand(rbp, kStartIndex)); 7806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ neg(rbx); 7816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (mode_ == UC16) { 7826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ lea(rax, Operand(rdi, rbx, times_2, -char_size())); 7836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 7846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ lea(rax, Operand(rdi, rbx, times_1, -char_size())); 7856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Store this value in a local variable, for use when clearing 787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // position registers. 788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(Operand(rbp, kInputStartMinusOne), rax); 789d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (num_saved_registers_ > 0) { 791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fill saved registers with initial value = start offset - 1 792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fill in stack push order, to avoid accessing across an unwritten 793a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // page (a problem on Windows). 794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rcx, Immediate(kRegisterZero)); 795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label init_loop; 796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&init_loop); 797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(Operand(rbp, rcx, times_1, 0), rax); 798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ subq(rcx, Immediate(kPointerSize)); 799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpq(rcx, 800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Immediate(kRegisterZero - num_saved_registers_ * kPointerSize)); 801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(greater, &init_loop); 802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Ensure that we have written to each stack page, in order. Skipping a page 804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // on Windows can cause segmentation faults. Assuming page size is 4k. 805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int kPageSize = 4096; 806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int kRegistersPerPage = kPageSize / kPointerSize; 807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = num_saved_registers_ + kRegistersPerPage - 1; 808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i < num_registers_; 809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i += kRegistersPerPage) { 810a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(register_location(i), rax); // One write every page. 811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Initialize backtrack stack pointer. 814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(backtrack_stackpointer(), Operand(rbp, kStackHighEnd)); 815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Initialize code object pointer. 816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Move(code_object_pointer(), masm_->CodeObject()); 817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load previous char as initial value of current-character. 818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label at_start; 81925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ cmpb(Operand(rbp, kStartIndex), Immediate(0)); 82025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ j(equal, &at_start); 821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LoadCurrentCharacterUnchecked(-1, 1); // Load previous char. 822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&start_label_); 823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&at_start); 824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(current_character(), Immediate('\n')); 825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&start_label_); 826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Exit code: 829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (success_label_.is_linked()) { 830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Save captures when successful. 831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&success_label_); 832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (num_saved_registers_ > 0) { 833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // copy captures to output 8346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ movq(rdx, Operand(rbp, kStartIndex)); 835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rbx, Operand(rbp, kRegisterOutput)); 836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rcx, Operand(rbp, kInputEnd)); 837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ subq(rcx, Operand(rbp, kInputStart)); 8386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (mode_ == UC16) { 8396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ lea(rcx, Operand(rcx, rdx, times_2, 0)); 8406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 8416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ addq(rcx, rdx); 8426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < num_saved_registers_; i++) { 844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rax, register_location(i)); 845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ addq(rax, rcx); // Convert to index from start, not end. 846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mode_ == UC16) { 847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sar(rax, Immediate(1)); // Convert byte index to character index. 848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movl(Operand(rbx, i * kIntSize), rax); 850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rax, Immediate(SUCCESS)); 853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Exit and return rax 856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&exit_label_); 857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef _WIN64 859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore callee save registers. 860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(rsp, Operand(rbp, kLastCalleeSaveRegister)); 861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(rbx); 862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(rdi); 863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(rsi); 864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Stack now at rbp. 865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#else 866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore callee save register. 867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rbx, Operand(rbp, kBackup_rbx)); 868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Skip rsp to rbp. 869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rsp, rbp); 870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Exit function frame, restore previous one. 872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(rbp); 873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Backtrack code (branch target for conditional backtracks). 876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (backtrack_label_.is_linked()) { 877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&backtrack_label_); 878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Backtrack(); 879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label exit_with_exception; 882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Preempt-code 884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (check_preempt_label_.is_linked()) { 885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SafeCallTarget(&check_preempt_label_); 886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(backtrack_stackpointer()); 888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(rdi); 889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CallCheckStackGuardState(); 891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ testq(rax, rax); 892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If returning non-zero, we should end execution with the given 893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // result as return value. 894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_zero, &exit_label_); 895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore registers. 897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Move(code_object_pointer(), masm_->CodeObject()); 898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(rdi); 899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(backtrack_stackpointer()); 900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // String might have moved: Reload esi from frame. 901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rsi, Operand(rbp, kInputEnd)); 902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SafeReturn(); 903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Backtrack stack overflow code. 906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (stack_overflow_label_.is_linked()) { 907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SafeCallTarget(&stack_overflow_label_); 908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Reached if the backtrack-stack limit has been hit. 909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label grow_failed; 911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Save registers before calling C function 912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifndef _WIN64 913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Callee-save in Microsoft 64-bit ABI, but not in AMD64 ABI. 914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(rsi); 915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(rdi); 916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Call GrowStack(backtrack_stackpointer()) 9196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block static const int num_arguments = 2; 9204515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ PrepareCallCFunction(num_arguments); 921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef _WIN64 922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Microsoft passes parameters in rcx, rdx. 923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // First argument, backtrack stackpointer, is already in rcx. 924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(rdx, Operand(rbp, kStackHighEnd)); // Second argument 925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#else 926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // AMD64 ABI passes parameters in rdi, rsi. 927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rdi, backtrack_stackpointer()); // First argument. 928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(rsi, Operand(rbp, kStackHighEnd)); // Second argument. 929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference grow_stack = ExternalReference::re_grow_stack(); 9314515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ CallCFunction(grow_stack, num_arguments); 932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If return NULL, we have failed to grow the stack, and 933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // must exit with a stack-overflow exception. 934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ testq(rax, rax); 935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, &exit_with_exception); 936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Otherwise use return value as new stack pointer. 937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(backtrack_stackpointer(), rax); 938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore saved registers and continue. 939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Move(code_object_pointer(), masm_->CodeObject()); 940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifndef _WIN64 941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(rdi); 942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(rsi); 943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SafeReturn(); 945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (exit_with_exception.is_linked()) { 948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If any of the code above needed to exit with an exception. 949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&exit_with_exception); 950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Exit with Result EXCEPTION(-1) to signal thrown exception. 951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rax, Immediate(EXCEPTION)); 952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&exit_label_); 953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FixupCodeRelativePositions(); 956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CodeDesc code_desc; 958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm_->GetCode(&code_desc); 959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code> code = Factory::NewCode(code_desc, 960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code::ComputeFlags(Code::REGEXP), 961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm_->CodeObject()); 9626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block PROFILE(RegExpCodeCreateEvent(*code, *source)); 963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return Handle<Object>::cast(code); 964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::GoTo(Label* to) { 968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(no_condition, to); 969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::IfRegisterGE(int reg, 973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int comparand, 974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* if_ge) { 975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpq(register_location(reg), Immediate(comparand)); 976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(greater_equal, if_ge); 977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::IfRegisterLT(int reg, 981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int comparand, 982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* if_lt) { 983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpq(register_location(reg), Immediate(comparand)); 984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(less, if_lt); 985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::IfRegisterEqPos(int reg, 989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* if_eq) { 990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpq(rdi, register_location(reg)); 991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(equal, if_eq); 992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegExpMacroAssembler::IrregexpImplementation 996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RegExpMacroAssemblerX64::Implementation() { 997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return kX64Implementation; 998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::LoadCurrentCharacter(int cp_offset, 1002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_end_of_input, 1003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool check_bounds, 1004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int characters) { 1005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(cp_offset >= -1); // ^ and \b can look behind one character. 1006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(cp_offset < (1<<30)); // Be sane! (And ensure negation works) 1007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (check_bounds) { 1008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CheckPosition(cp_offset + characters - 1, on_end_of_input); 1009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LoadCurrentCharacterUnchecked(cp_offset, characters); 1011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::PopCurrentPosition() { 1015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Pop(rdi); 1016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::PopRegister(int register_index) { 1020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Pop(rax); 1021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(register_location(register_index), rax); 1022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::PushBacktrack(Label* label) { 1026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Push(label); 1027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CheckStackLimit(); 1028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::PushCurrentPosition() { 1032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Push(rdi); 1033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::PushRegister(int register_index, 1037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StackCheckFlag check_stack_limit) { 1038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rax, register_location(register_index)); 1039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Push(rax); 1040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (check_stack_limit) CheckStackLimit(); 1041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::ReadCurrentPositionFromRegister(int reg) { 1045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rdi, register_location(reg)); 1046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::ReadStackPointerFromRegister(int reg) { 1050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(backtrack_stackpointer(), register_location(reg)); 1051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ addq(backtrack_stackpointer(), Operand(rbp, kStackHighEnd)); 1052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1055f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdochvoid RegExpMacroAssemblerX64::SetCurrentPositionFromEnd(int by) { 1056f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch NearLabel after_position; 1057f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ cmpq(rdi, Immediate(-by * char_size())); 1058f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ j(greater_equal, &after_position); 1059f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ movq(rdi, Immediate(-by * char_size())); 1060f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // On RegExp code entry (where this operation is used), the character before 1061f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // the current position is expected to be already loaded. 1062f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // We have advanced the position, so it's safe to read backwards. 1063f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch LoadCurrentCharacterUnchecked(-1, 1); 1064f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ bind(&after_position); 1065f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch} 1066f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 1067f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 1068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::SetRegister(int register_index, int to) { 1069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(register_index >= num_saved_registers_); // Reserved for positions! 1070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(register_location(register_index), Immediate(to)); 1071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::Succeed() { 1075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&success_label_); 1076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::WriteCurrentPositionToRegister(int reg, 1080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int cp_offset) { 1081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (cp_offset == 0) { 1082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(register_location(reg), rdi); 1083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1084a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(rax, Operand(rdi, cp_offset * char_size())); 1085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(register_location(reg), rax); 1086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::ClearRegisters(int reg_from, int reg_to) { 1091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(reg_from <= reg_to); 1092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rax, Operand(rbp, kInputStartMinusOne)); 1093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int reg = reg_from; reg <= reg_to; reg++) { 1094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(register_location(reg), rax); 1095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::WriteStackPointerToRegister(int reg) { 1100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rax, backtrack_stackpointer()); 1101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ subq(rax, Operand(rbp, kStackHighEnd)); 1102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(register_location(reg), rax); 1103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Private methods: 1107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::CallCheckStackGuardState() { 1109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // This function call preserves no register values. Caller should 1110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // store anything volatile in a C call or overwritten by this function. 11116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block static const int num_arguments = 3; 11124515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ PrepareCallCFunction(num_arguments); 1113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef _WIN64 1114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Second argument: Code* of self. (Do this before overwriting r8). 1115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rdx, code_object_pointer()); 1116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Third argument: RegExp code frame pointer. 1117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(r8, rbp); 1118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // First argument: Next address on the stack (will be address of 1119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // return address). 1120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(rcx, Operand(rsp, -kPointerSize)); 1121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#else 1122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Third argument: RegExp code frame pointer. 1123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rdx, rbp); 1124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Second argument: Code* of self. 1125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rsi, code_object_pointer()); 1126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // First argument: Next address on the stack (will be address of 1127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // return address). 1128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(rdi, Operand(rsp, -kPointerSize)); 1129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 1130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference stack_check = 1131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference::re_check_stack_guard_state(); 11324515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ CallCFunction(stack_check, num_arguments); 1133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Helper function for reading a value out of a stack frame. 1137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocktemplate <typename T> 1138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic T& frame_entry(Address re_frame, int frame_offset) { 1139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return reinterpret_cast<T&>(Memory::int32_at(re_frame + frame_offset)); 1140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint RegExpMacroAssemblerX64::CheckStackGuardState(Address* return_address, 1144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code* re_code, 1145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address re_frame) { 1146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (StackGuard::IsStackOverflow()) { 1147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Top::StackOverflow(); 1148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return EXCEPTION; 1149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If not real stack overflow the stack guard was used to interrupt 1152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // execution for another purpose. 1153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 11544515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // If this is a direct call from JavaScript retry the RegExp forcing the call 11554515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // through the runtime system. Currently the direct call cannot handle a GC. 11564515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke if (frame_entry<int>(re_frame, kDirectCall) == 1) { 11574515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke return RETRY; 11584515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } 11594515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 1160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Prepare for possible GC. 1161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block HandleScope handles; 1162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code> code_handle(re_code); 1163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<String> subject(frame_entry<String*>(re_frame, kInputString)); 1165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Current string. 1166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool is_ascii = subject->IsAsciiRepresentation(); 1167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(re_code->instruction_start() <= *return_address); 1169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(*return_address <= 1170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block re_code->instruction_start() + re_code->instruction_size()); 1171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Object* result = Execution::HandleStackGuardInterrupt(); 1173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (*code_handle != re_code) { // Return address no longer valid 1175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block intptr_t delta = *code_handle - re_code; 1176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Overwrite the return address on the stack. 1177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *return_address += delta; 1178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (result->IsException()) { 1181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return EXCEPTION; 1182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // String might have changed. 1185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (subject->IsAsciiRepresentation() != is_ascii) { 1186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If we changed between an ASCII and an UC16 string, the specialized 1187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // code cannot be used, and we need to restart regexp matching from 1188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // scratch (including, potentially, compiling a new version of the code). 1189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return RETRY; 1190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Otherwise, the content of the string might have moved. It must still 1193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // be a sequential or external string with the same content. 1194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Update the start and end pointers in the stack frame to the current 1195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // location (whether it has actually moved or not). 1196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(StringShape(*subject).IsSequential() || 1197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StringShape(*subject).IsExternal()); 1198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The original start address of the characters to match. 1200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const byte* start_address = frame_entry<const byte*>(re_frame, kInputStart); 1201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Find the current start address of the same character at the current string 1203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // position. 1204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int start_index = frame_entry<int>(re_frame, kStartIndex); 1205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const byte* new_address = StringCharacterPosition(*subject, start_index); 1206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (start_address != new_address) { 1208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If there is a difference, update the object pointer and start and end 1209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // addresses in the RegExp stack frame to match the new value. 1210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const byte* end_address = frame_entry<const byte* >(re_frame, kInputEnd); 1211d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int byte_length = static_cast<int>(end_address - start_address); 1212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block frame_entry<const String*>(re_frame, kInputString) = *subject; 1213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block frame_entry<const byte*>(re_frame, kInputStart) = new_address; 1214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block frame_entry<const byte*>(re_frame, kInputEnd) = new_address + byte_length; 1215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 0; 1218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockOperand RegExpMacroAssemblerX64::register_location(int register_index) { 1222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(register_index < (1<<30)); 1223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (num_registers_ <= register_index) { 1224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block num_registers_ = register_index + 1; 1225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return Operand(rbp, kRegisterZero - register_index * kPointerSize); 1227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::CheckPosition(int cp_offset, 1231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_outside_input) { 1232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpl(rdi, Immediate(-cp_offset * char_size())); 1233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(greater_equal, on_outside_input); 1234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::BranchOrBacktrack(Condition condition, 1238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* to) { 1239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (condition < 0) { // No condition 1240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (to == NULL) { 1241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Backtrack(); 1242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 1243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(to); 1245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 1246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (to == NULL) { 1248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(condition, &backtrack_label_); 1249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 1250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(condition, to); 1252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::SafeCall(Label* to) { 1256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ call(to); 1257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::SafeCallTarget(Label* label) { 1261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(label); 1262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ subq(Operand(rsp, 0), code_object_pointer()); 1263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::SafeReturn() { 1267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ addq(Operand(rsp, 0), code_object_pointer()); 1268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 1269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::Push(Register source) { 1273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!source.is(backtrack_stackpointer())); 1274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Notice: This updates flags, unlike normal Push. 1275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ subq(backtrack_stackpointer(), Immediate(kIntSize)); 1276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movl(Operand(backtrack_stackpointer(), 0), source); 1277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::Push(Immediate value) { 1281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Notice: This updates flags, unlike normal Push. 1282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ subq(backtrack_stackpointer(), Immediate(kIntSize)); 1283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movl(Operand(backtrack_stackpointer(), 0), value); 1284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::FixupCodeRelativePositions() { 1288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0, n = code_relative_fixup_positions_.length(); i < n; i++) { 1289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int position = code_relative_fixup_positions_[i]; 1290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The position succeeds a relative label offset from position. 1291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Patch the relative offset to be relative to the Code object pointer 1292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // instead. 1293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int patch_position = position - kIntSize; 1294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int offset = masm_->long_at(patch_position); 1295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block masm_->long_at_put(patch_position, 1296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block offset 1297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block + position 1298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block + Code::kHeaderSize 1299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block - kHeapObjectTag); 1300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block code_relative_fixup_positions_.Clear(); 1302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::Push(Label* backtrack_target) { 1306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ subq(backtrack_stackpointer(), Immediate(kIntSize)); 1307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movl(Operand(backtrack_stackpointer(), 0), backtrack_target); 1308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MarkPositionForCodeRelativeFixup(); 1309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::Pop(Register target) { 1313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!target.is(backtrack_stackpointer())); 1314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movsxlq(target, Operand(backtrack_stackpointer(), 0)); 1315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Notice: This updates flags, unlike normal Pop. 1316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ addq(backtrack_stackpointer(), Immediate(kIntSize)); 1317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::Drop() { 1321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ addq(backtrack_stackpointer(), Immediate(kIntSize)); 1322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::CheckPreemption() { 1326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check for preemption. 1327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label no_preempt; 1328d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ExternalReference stack_limit = 1329d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ExternalReference::address_of_stack_limit(); 1330d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ load_rax(stack_limit); 1331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpq(rsp, rax); 1332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(above, &no_preempt); 1333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SafeCall(&check_preempt_label_); 1335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&no_preempt); 1337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::CheckStackLimit() { 1341d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Label no_stack_overflow; 1342d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ExternalReference stack_limit = 1343d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ExternalReference::address_of_regexp_stack_limit(); 1344d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ load_rax(stack_limit); 1345d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ cmpq(backtrack_stackpointer(), rax); 1346d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ j(above, &no_stack_overflow); 1347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1348d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block SafeCall(&stack_overflow_label_); 1349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1350d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ bind(&no_stack_overflow); 1351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::LoadCurrentCharacterUnchecked(int cp_offset, 1355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int characters) { 1356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mode_ == ASCII) { 1357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (characters == 4) { 1358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movl(current_character(), Operand(rsi, rdi, times_1, cp_offset)); 1359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (characters == 2) { 1360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzxwl(current_character(), Operand(rsi, rdi, times_1, cp_offset)); 1361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(characters == 1); 1363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzxbl(current_character(), Operand(rsi, rdi, times_1, cp_offset)); 1364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(mode_ == UC16); 1367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (characters == 2) { 1368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movl(current_character(), 1369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Operand(rsi, rdi, times_1, cp_offset * sizeof(uc16))); 1370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(characters == 1); 1372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzxwl(current_character(), 1373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Operand(rsi, rdi, times_1, cp_offset * sizeof(uc16))); 1374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __ 1379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 13806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#endif // V8_INTERPRETED_REGEXP 1381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}} // namespace v8::internal 1383f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1384f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif // V8_TARGET_ARCH_X64 1385