1e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// Copyright 2011 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. 6644f0eee88ff00398ff7f715fab053374d808c90dSteve Block * The macro assembler special registers r12 and r13 (kSmiConstantRegister, 6744f0eee88ff00398ff7f715fab053374d808c90dSteve Block * kRootRegister) aren't special during execution of RegExp code (they don't 6844f0eee88ff00398ff7f715fab053374d808c90dSteve Block * hold the values assumed when creating JS code), so no Smi or Root related 6944f0eee88ff00398ff7f715fab053374d808c90dSteve Block * macro operations can be used. 70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * 71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * Each call to a C++ method should retain these registers. 72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * 73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * The stack will have the following content, in some order, indexable from the 74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * frame pointer (see, e.g., kStackHighEnd): 7544f0eee88ff00398ff7f715fab053374d808c90dSteve Block * - Isolate* isolate (Address of the current isolate) 76e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * - direct_call (if 1, direct call from JavaScript code, if 0 call 77e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * through the runtime system) 78e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * - stack_area_base (High end of the memory area to use as 79e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * backtracking stack) 80e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * - int* capture_array (int[num_saved_registers_], for output). 81e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * - end of input (Address of end of string) 82e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * - start of input (Address of first character in string) 83e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * - start index (character index of start) 84e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * - String* input_string (input string) 85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - return address 86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - backup of callee save registers (rbx, possibly rsi and rdi). 87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - Offset of location before start of input (effectively character 88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * position -1). Used to initialize capture registers to a non-position. 89d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke * - At start of string (if 1, we are starting at the start of the 90d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke * string, otherwise 0) 91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - register 0 rbp[-n] (Only positions must be stored in the first 92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - register 1 rbp[-n-8] num_saved_registers_ registers) 93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * - ... 94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * 95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * The first num_saved_registers_ registers are initialized to point to 96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * "character -1" in the string (i.e., char_size() bytes before the first 97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * character of the string). The remaining registers starts out uninitialized. 98a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * 99a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * The first seven values must be provided by the calling code by 100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * calling the code's entry address cast to a function pointer with the 101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * following signature: 102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * int (*match)(String* input_string, 103e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * int start_index, 104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * Address start, 105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * Address end, 106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * int* capture_output_array, 107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block * bool at_start, 108e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * byte* stack_area_base, 109e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke * bool direct_call) 110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block */ 111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 11244f0eee88ff00398ff7f715fab053374d808c90dSteve Block#define __ ACCESS_MASM((&masm_)) 113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegExpMacroAssemblerX64::RegExpMacroAssemblerX64( 115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Mode mode, 116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int registers_to_save) 1178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch : masm_(Isolate::Current(), NULL, kRegExpCodeSize), 11844f0eee88ff00398ff7f715fab053374d808c90dSteve Block no_root_array_scope_(&masm_), 119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block code_relative_fixup_positions_(4), 120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block mode_(mode), 121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block num_registers_(registers_to_save), 122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block num_saved_registers_(registers_to_save), 123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block entry_label_(), 124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block start_label_(), 125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block success_label_(), 126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block backtrack_label_(), 127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block exit_label_() { 128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(0, registers_to_save % 2); 129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&entry_label_); // We'll write the entry code when we know more. 130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&start_label_); // And then continue from here. 131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegExpMacroAssemblerX64::~RegExpMacroAssemblerX64() { 135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Unuse labels in case we throw away the assembler without calling GetCode. 136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block entry_label_.Unuse(); 137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block start_label_.Unuse(); 138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block success_label_.Unuse(); 139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block backtrack_label_.Unuse(); 140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block exit_label_.Unuse(); 141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block check_preempt_label_.Unuse(); 142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block stack_overflow_label_.Unuse(); 143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint RegExpMacroAssemblerX64::stack_limit_slack() { 147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return RegExpStack::kStackLimitSlack; 148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::AdvanceCurrentPosition(int by) { 152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (by != 0) { 153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ addq(rdi, Immediate(by * char_size())); 154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::AdvanceRegister(int reg, int by) { 159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(reg >= 0); 160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(reg < num_registers_); 161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (by != 0) { 162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ addq(register_location(reg), Immediate(by)); 163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::Backtrack() { 168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CheckPreemption(); 169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Pop Code* offset from backtrack stack, add Code* and jump to location. 170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Pop(rbx); 171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ addq(rbx, code_object_pointer()); 172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(rbx); 173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::Bind(Label* label) { 177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(label); 178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::CheckCharacter(uint32_t c, Label* on_equal) { 182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpl(current_character(), Immediate(c)); 183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(equal, on_equal); 184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::CheckCharacterGT(uc16 limit, Label* on_greater) { 188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpl(current_character(), Immediate(limit)); 189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(greater, on_greater); 190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::CheckAtStart(Label* on_at_start) { 194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label not_at_start; 195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Did we start the match at the start of the string at all? 1963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmpl(Operand(rbp, kStartIndex), Immediate(0)); 19725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen BranchOrBacktrack(not_equal, ¬_at_start); 198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If we did, are we still at the start of the input? 199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(rax, Operand(rsi, rdi, times_1, 0)); 200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpq(rax, Operand(rbp, kInputStart)); 201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(equal, on_at_start); 202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(¬_at_start); 203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::CheckNotAtStart(Label* on_not_at_start) { 207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Did we start the match at the start of the string at all? 2083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmpl(Operand(rbp, kStartIndex), Immediate(0)); 20925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen BranchOrBacktrack(not_equal, on_not_at_start); 210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If we did, are we still at the start of the input? 211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(rax, Operand(rsi, rdi, times_1, 0)); 212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpq(rax, Operand(rbp, kInputStart)); 213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(not_equal, on_not_at_start); 214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::CheckCharacterLT(uc16 limit, Label* on_less) { 218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpl(current_character(), Immediate(limit)); 219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(less, on_less); 220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::CheckCharacters(Vector<const uc16> str, 224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int cp_offset, 225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_failure, 226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool check_end_of_string) { 22725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen#ifdef DEBUG 22825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // If input is ASCII, don't even bother calling here if the string to 2293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // match contains a non-ASCII character. 23025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen if (mode_ == ASCII) { 2319fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block ASSERT(String::IsAscii(str.start(), str.length())); 23225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } 23325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen#endif 234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int byte_length = str.length() * char_size(); 235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int byte_offset = cp_offset * char_size(); 236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (check_end_of_string) { 237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that there are at least str.length() characters left in the input. 238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpl(rdi, Immediate(-(byte_offset + byte_length))); 239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(greater, on_failure); 240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (on_failure == NULL) { 243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Instead of inlining a backtrack, (re)use the global backtrack target. 244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block on_failure = &backtrack_label_; 245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 24725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // Do one character test first to minimize loading for the case that 24825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // we don't match at all (loading more than one character introduces that 24925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // chance of reading unaligned and reading across cache boundaries). 25025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // If the first character matches, expect a larger chance of matching the 25125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // string, and start loading more characters at a time. 25225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen if (mode_ == ASCII) { 25325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ cmpb(Operand(rsi, rdi, times_1, byte_offset), 25425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen Immediate(static_cast<int8_t>(str[0]))); 25525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } else { 25625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // Don't use 16-bit immediate. The size changing prefix throws off 25725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen // pre-decoding. 25825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ movzxwl(rax, 25925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen Operand(rsi, rdi, times_1, byte_offset)); 26025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ cmpl(rax, Immediate(static_cast<int32_t>(str[0]))); 26125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } 26225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen BranchOrBacktrack(not_equal, on_failure); 26325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen 26425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ lea(rbx, Operand(rsi, rdi, times_1, 0)); 26525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen for (int i = 1, n = str.length(); i < n; ) { 266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mode_ == ASCII) { 26725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen if (i + 8 <= n) { 26825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen uint64_t combined_chars = 26925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen (static_cast<uint64_t>(str[i + 0]) << 0) || 27025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen (static_cast<uint64_t>(str[i + 1]) << 8) || 27125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen (static_cast<uint64_t>(str[i + 2]) << 16) || 27225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen (static_cast<uint64_t>(str[i + 3]) << 24) || 27325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen (static_cast<uint64_t>(str[i + 4]) << 32) || 27425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen (static_cast<uint64_t>(str[i + 5]) << 40) || 27525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen (static_cast<uint64_t>(str[i + 6]) << 48) || 27625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen (static_cast<uint64_t>(str[i + 7]) << 56); 27725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ movq(rax, combined_chars, RelocInfo::NONE); 27825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ cmpq(rax, Operand(rbx, byte_offset + i)); 27925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen i += 8; 28025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } else if (i + 4 <= n) { 28125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen uint32_t combined_chars = 28225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen (static_cast<uint32_t>(str[i + 0]) << 0) || 28325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen (static_cast<uint32_t>(str[i + 1]) << 8) || 28425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen (static_cast<uint32_t>(str[i + 2]) << 16) || 28525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen (static_cast<uint32_t>(str[i + 3]) << 24); 28625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ cmpl(Operand(rbx, byte_offset + i), Immediate(combined_chars)); 28725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen i += 4; 28825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } else { 28925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ cmpb(Operand(rbx, byte_offset + i), 29025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen Immediate(static_cast<int8_t>(str[i]))); 29125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen i++; 29225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } 293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(mode_ == UC16); 29525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen if (i + 4 <= n) { 29625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen uint64_t combined_chars = *reinterpret_cast<const uint64_t*>(&str[i]); 29725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ movq(rax, combined_chars, RelocInfo::NONE); 29825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ cmpq(rax, 29925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen Operand(rsi, rdi, times_1, byte_offset + i * sizeof(uc16))); 30025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen i += 4; 30125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } else if (i + 2 <= n) { 30225f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen uint32_t combined_chars = *reinterpret_cast<const uint32_t*>(&str[i]); 30325f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ cmpl(Operand(rsi, rdi, times_1, byte_offset + i * sizeof(uc16)), 30425f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen Immediate(combined_chars)); 30525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen i += 2; 30625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } else { 30725f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ movzxwl(rax, 30825f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen Operand(rsi, rdi, times_1, byte_offset + i * sizeof(uc16))); 30925f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ cmpl(rax, Immediate(str[i])); 31025f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen i++; 31125f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen } 312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(not_equal, on_failure); 314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::CheckGreedyLoop(Label* on_equal) { 319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label fallthrough; 320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpl(rdi, Operand(backtrack_stackpointer(), 0)); 321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &fallthrough); 322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Drop(); 323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(no_condition, on_equal); 324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&fallthrough); 325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::CheckNotBackReferenceIgnoreCase( 329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int start_reg, 330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_no_match) { 331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label fallthrough; 332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rdx, register_location(start_reg)); // Offset of start of capture 333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rbx, register_location(start_reg + 1)); // Offset of end of capture 334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ subq(rbx, rdx); // Length of capture. 335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------- 337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // rdx = Start offset of capture. 338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // rbx = Length of capture 339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If length is negative, this code will fail (it's a symptom of a partial or 341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // illegal capture where start of capture after end of capture). 342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // This must not happen (no back-reference can reference a capture that wasn't 343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // closed before in the reg-exp, and we must not generate code that can cause 344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // this condition). 345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If length is zero, either the capture is empty or it is nonparticipating. 347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // In either case succeed immediately. 348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, &fallthrough); 349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mode_ == ASCII) { 351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label loop_increment; 352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (on_no_match == NULL) { 353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block on_no_match = &backtrack_label_; 354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(r9, Operand(rsi, rdx, times_1, 0)); 357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(r11, Operand(rsi, rdi, times_1, 0)); 358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ addq(rbx, r9); // End of capture 359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // --------------------- 360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r11 - current input character address 361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r9 - current capture character address 362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // rbx - end of capture 363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label loop; 365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&loop); 366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzxbl(rdx, Operand(r9, 0)); 367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzxbl(rax, Operand(r11, 0)); 368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // al - input character 369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // dl - capture character 370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpb(rax, rdx); 371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, &loop_increment); 372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Mismatch, try case-insensitive match (converting letters to lower-case). 374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // I.e., if or-ing with 0x20 makes values equal and in range 'a'-'z', it's 375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // a match. 376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ or_(rax, Immediate(0x20)); // Convert match character to lower-case. 377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ or_(rdx, Immediate(0x20)); // Convert capture character to lower-case. 378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpb(rax, rdx); 379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, on_no_match); // Definitely not equal. 380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ subb(rax, Immediate('a')); 381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpb(rax, Immediate('z' - 'a')); 382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(above, on_no_match); // Weren't letters anyway. 383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&loop_increment); 385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Increment pointers into match and capture strings. 386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ addq(r11, Immediate(1)); 387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ addq(r9, Immediate(1)); 388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compare to end of capture, and loop if not done. 389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpq(r9, rbx); 390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(below, &loop); 391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compute new value of character position after the matched part. 393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rdi, r11); 394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ subq(rdi, rsi); 395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(mode_ == UC16); 397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Save important/volatile registers before calling C function. 398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifndef _WIN64 3994515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // Caller save on Linux and callee save in Windows. 400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(rsi); 401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(rdi); 402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(backtrack_stackpointer()); 404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 4058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch static const int num_arguments = 4; 4064515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ PrepareCallCFunction(num_arguments); 407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Put arguments into parameter registers. Parameters are 409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Address byte_offset1 - Address captured substring's start. 410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Address byte_offset2 - Address of current character position. 411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // size_t byte_length - length of capture in bytes(!) 4128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // Isolate* isolate 413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef _WIN64 414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compute and set byte_offset1 (start of capture). 415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(rcx, Operand(rsi, rdx, times_1, 0)); 416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set byte_offset2. 417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(rdx, Operand(rsi, rdi, times_1, 0)); 418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set byte_length. 419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(r8, rbx); 4208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // Isolate. 4218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ LoadAddress(r9, ExternalReference::isolate_address()); 422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#else // AMD64 calling convention 423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compute byte_offset2 (current position = rsi+rdi). 424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(rax, Operand(rsi, rdi, times_1, 0)); 425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compute and set byte_offset1 (start of capture). 426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(rdi, Operand(rsi, rdx, times_1, 0)); 427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set byte_offset2. 428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rsi, rax); 429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set byte_length. 430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rdx, rbx); 4318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // Isolate. 4328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ LoadAddress(rcx, ExternalReference::isolate_address()); 433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 4343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { // NOLINT: Can't find a way to open this scope without confusing the 4363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // linter. 4373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AllowExternalCallThatCantCauseGC scope(&masm_); 4383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference compare = 4393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference::re_case_insensitive_compare_uc16(masm_.isolate()); 4403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallCFunction(compare, num_arguments); 4413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore original values before reacting on result value. 44444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Move(code_object_pointer(), masm_.CodeObject()); 445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(backtrack_stackpointer()); 446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifndef _WIN64 447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(rdi); 448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(rsi); 449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if function returned non-zero for success or zero for failure. 452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ testq(rax, rax); 453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(zero, on_no_match); 454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // On success, increment position by length of capture. 455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Requires that rbx is callee save (true for both Win64 and AMD64 ABIs). 456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ addq(rdi, rbx); 457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&fallthrough); 459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::CheckNotBackReference( 463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int start_reg, 464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_no_match) { 465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label fallthrough; 466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Find length of back-referenced capture. 468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rdx, register_location(start_reg)); 469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rax, register_location(start_reg + 1)); 470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ subq(rax, rdx); // Length to check. 471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fail on partial or illegal capture (start of capture after end of capture). 473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // This must not happen (no back-reference can reference a capture that wasn't 474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // closed before in the reg-exp). 475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Check(greater_equal, "Invalid capture referenced"); 476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Succeed on empty capture (including non-participating capture) 478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, &fallthrough); 479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------- 481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // rdx - Start of capture 482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // rax - length of capture 483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that there are sufficient characters left in the input. 485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movl(rbx, rdi); 486a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ addl(rbx, rax); 487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(greater, on_no_match); 488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compute pointers to match string and capture string 490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(rbx, Operand(rsi, rdi, times_1, 0)); // Start of match. 491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ addq(rdx, rsi); // Start of capture. 492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(r9, Operand(rdx, rax, times_1, 0)); // End of capture 493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------- 495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // rbx - current capture character address. 496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // rbx - current input character address . 497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r9 - end of input to match (capture length after rbx). 498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label loop; 500a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&loop); 501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mode_ == ASCII) { 502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzxbl(rax, Operand(rdx, 0)); 503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpb(rax, Operand(rbx, 0)); 504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(mode_ == UC16); 506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzxwl(rax, Operand(rdx, 0)); 507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpw(rax, Operand(rbx, 0)); 508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(not_equal, on_no_match); 510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Increment pointers into capture and match string. 511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ addq(rbx, Immediate(char_size())); 512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ addq(rdx, Immediate(char_size())); 513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if we have reached end of match area. 514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpq(rdx, r9); 515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(below, &loop); 516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Success. 518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set current character position to position after match. 519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rdi, rbx); 520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ subq(rdi, rsi); 521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&fallthrough); 523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::CheckNotRegistersEqual(int reg1, 527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int reg2, 528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_not_equal) { 529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rax, register_location(reg1)); 530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpq(rax, register_location(reg2)); 531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(not_equal, on_not_equal); 532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::CheckNotCharacter(uint32_t c, 536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_not_equal) { 537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpl(current_character(), Immediate(c)); 538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(not_equal, on_not_equal); 539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::CheckCharacterAfterAnd(uint32_t c, 543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uint32_t mask, 544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_equal) { 545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movl(rax, current_character()); 546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ and_(rax, Immediate(mask)); 547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpl(rax, Immediate(c)); 548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(equal, on_equal); 549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::CheckNotCharacterAfterAnd(uint32_t c, 553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uint32_t mask, 554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_not_equal) { 555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movl(rax, current_character()); 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 Blockvoid RegExpMacroAssemblerX64::CheckNotCharacterAfterMinusAnd( 563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uc16 c, 564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uc16 minus, 565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uc16 mask, 566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_not_equal) { 5673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(minus < String::kMaxUtf16CodeUnit); 568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(rax, Operand(current_character(), -minus)); 569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ and_(rax, Immediate(mask)); 570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpl(rax, Immediate(c)); 571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(not_equal, on_not_equal); 572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool RegExpMacroAssemblerX64::CheckSpecialCharacterClass(uc16 type, 576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_no_match) { 577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Range checks (c in min..max) are generally implemented by an unsigned 578e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // (c - min) <= (max - min) check, using the sequence: 579e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // lea(rax, Operand(current_character(), -min)) or sub(rax, Immediate(min)) 580e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // cmp(rax, Immediate(max - min)) 581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block switch (type) { 582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 's': 583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Match space-characters 584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mode_ == ASCII) { 585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ASCII space characters are '\t'..'\r' and ' '. 586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label success; 587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpl(current_character(), Immediate(' ')); 588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, &success); 589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check range 0x09..0x0d 590e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ lea(rax, Operand(current_character(), -'\t')); 591e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmpl(rax, Immediate('\r' - '\t')); 592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(above, on_no_match); 593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&success); 594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return false; 597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 'S': 598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Match non-space characters. 599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mode_ == ASCII) { 600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ASCII space characters are '\t'..'\r' and ' '. 601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpl(current_character(), Immediate(' ')); 602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(equal, on_no_match); 603e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ lea(rax, Operand(current_character(), -'\t')); 604e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmpl(rax, Immediate('\r' - '\t')); 605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(below_equal, on_no_match); 606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return false; 609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 'd': 610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Match ASCII digits ('0'..'9') 611e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ lea(rax, Operand(current_character(), -'0')); 612e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmpl(rax, Immediate('9' - '0')); 613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(above, on_no_match); 614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case 'D': 616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Match non ASCII-digits 617e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ lea(rax, Operand(current_character(), -'0')); 618e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmpl(rax, Immediate('9' - '0')); 619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(below_equal, on_no_match); 620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case '.': { 622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Match non-newlines (not 0x0a('\n'), 0x0d('\r'), 0x2028 and 0x2029) 623e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movl(rax, current_character()); 624e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ xor_(rax, Immediate(0x01)); 625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c 626e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ subl(rax, Immediate(0x0b)); 627e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmpl(rax, Immediate(0x0c - 0x0b)); 628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(below_equal, on_no_match); 629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mode_ == UC16) { 630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Compare original value to 0x2028 and 0x2029, using the already 631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // computed (current_char ^ 0x01 - 0x0b). I.e., check for 632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 0x201d (0x2028 - 0x0b) or 0x201e. 633e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ subl(rax, Immediate(0x2028 - 0x0b)); 634e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmpl(rax, Immediate(0x2029 - 0x2028)); 635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(below_equal, on_no_match); 636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 639e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case 'n': { 640e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Match newlines (0x0a('\n'), 0x0d('\r'), 0x2028 and 0x2029) 641e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movl(rax, current_character()); 642e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ xor_(rax, Immediate(0x01)); 643e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c 644e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ subl(rax, Immediate(0x0b)); 645e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmpl(rax, Immediate(0x0c - 0x0b)); 646e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (mode_ == ASCII) { 647e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke BranchOrBacktrack(above, on_no_match); 648e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } else { 649e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label done; 650e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke BranchOrBacktrack(below_equal, &done); 651e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Compare original value to 0x2028 and 0x2029, using the already 652e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // computed (current_char ^ 0x01 - 0x0b). I.e., check for 653e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // 0x201d (0x2028 - 0x0b) or 0x201e. 654e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ subl(rax, Immediate(0x2028 - 0x0b)); 655e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmpl(rax, Immediate(0x2029 - 0x2028)); 656e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke BranchOrBacktrack(above, on_no_match); 657e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(&done); 658e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 659e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return true; 660e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 661e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case 'w': { 662e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (mode_ != ASCII) { 663e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Table is 128 entries, so all ASCII characters can be tested. 664e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmpl(current_character(), Immediate('z')); 665e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke BranchOrBacktrack(above, on_no_match); 666e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 667e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(rbx, ExternalReference::re_word_character_map()); 668e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_EQ(0, word_character_map[0]); // Character '\0' is not a word char. 669e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ testb(Operand(rbx, current_character(), times_1, 0), 670e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke current_character()); 671e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke BranchOrBacktrack(zero, on_no_match); 672e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return true; 673e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 674e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke case 'W': { 675e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke Label done; 676e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (mode_ != ASCII) { 677e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Table is 128 entries, so all ASCII characters can be tested. 678e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmpl(current_character(), Immediate('z')); 679e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ j(above, &done); 680e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 681e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(rbx, ExternalReference::re_word_character_map()); 682e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke ASSERT_EQ(0, word_character_map[0]); // Character '\0' is not a word char. 683e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ testb(Operand(rbx, current_character(), times_1, 0), 684e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke current_character()); 685e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke BranchOrBacktrack(not_zero, on_no_match); 686e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke if (mode_ != ASCII) { 687e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ bind(&done); 688e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 689e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke return true; 690e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke } 691e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 692a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block case '*': 693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Match any character. 694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 695e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // No custom implementation (yet): s(UC16), S(UC16). 696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block default: 697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return false; 698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::Fail() { 703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(FAILURE == 0); // Return value for failure is zero. 7049fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ Set(rax, 0); 705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&exit_label_); 706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 709053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve BlockHandle<HeapObject> RegExpMacroAssemblerX64::GetCode(Handle<String> source) { 710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Finalize code - write the entry point code now we know how many 711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // registers we need. 712a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Entry code: 713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&entry_label_); 7143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 7153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Tell the system that we have a stack frame. Because the type is MANUAL, no 7163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // is generated. 7173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameScope scope(&masm_, StackFrame::MANUAL); 7183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 7193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Actually emit code to start a new stack frame. 720a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(rbp); 721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rbp, rsp); 722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Save parameters and callee-save registers. Order here should correspond 723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // to order of kBackup_ebx etc. 724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef _WIN64 725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // MSVC passes arguments in rcx, rdx, r8, r9, with backing stack slots. 726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Store register parameters in pre-allocated stack slots, 727a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(Operand(rbp, kInputString), rcx); 728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(Operand(rbp, kStartIndex), rdx); // Passed as int32 in edx. 729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(Operand(rbp, kInputStart), r8); 730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(Operand(rbp, kInputEnd), r9); 731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Callee-save on Win64. 732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(rsi); 733a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(rdi); 734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(rbx); 735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#else 736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // GCC passes arguments in rdi, rsi, rdx, rcx, r8, r9 (and then on stack). 737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Push register parameters on stack for reference. 738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(kInputString, -1 * kPointerSize); 739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(kStartIndex, -2 * kPointerSize); 740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(kInputStart, -3 * kPointerSize); 741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(kInputEnd, -4 * kPointerSize); 742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT_EQ(kRegisterOutput, -5 * kPointerSize); 743d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke ASSERT_EQ(kStackHighEnd, -6 * kPointerSize); 744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(rdi); 745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(rsi); 746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(rdx); 747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(rcx); 748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(r8); 749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(r9); 750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(rbx); // Callee-save 752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 7534515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 754d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke __ push(Immediate(0)); // Make room for "at start" constant. 755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if we have space on the stack for registers. 757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label stack_limit_hit; 758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label stack_ok; 759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 760d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ExternalReference stack_limit = 76144f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference::address_of_stack_limit(masm_.isolate()); 762a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rcx, rsp); 763d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ movq(kScratchRegister, stack_limit); 764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ subq(rcx, Operand(kScratchRegister, 0)); 765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle it if the stack pointer is already below the stack limit. 766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(below_equal, &stack_limit_hit); 767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if there is room for the variable number of registers above 768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // the stack limit. 769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpq(rcx, Immediate(num_registers_ * kPointerSize)); 770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(above_equal, &stack_ok); 771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Exit with OutOfMemory exception. There is not enough space on the stack 772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // for our working registers. 7738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ Set(rax, EXCEPTION); 774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&exit_label_); 775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&stack_limit_hit); 77744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Move(code_object_pointer(), masm_.CodeObject()); 778a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CallCheckStackGuardState(); // Preserves no registers beside rbp and rsp. 779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ testq(rax, rax); 780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If returned value is non-zero, we exit with the returned value as result. 781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_zero, &exit_label_); 782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&stack_ok); 784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Allocate space on stack for registers. 786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ subq(rsp, Immediate(num_registers_ * kPointerSize)); 787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load string length. 788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rsi, Operand(rbp, kInputEnd)); 789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load input position. 790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rdi, Operand(rbp, kInputStart)); 791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set up rdi to be negative offset from string end. 792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ subq(rdi, rsi); 7936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Set rax to address of char before start of the string 794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // (effectively string position -1). 7956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ movq(rbx, Operand(rbp, kStartIndex)); 7966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ neg(rbx); 7976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (mode_ == UC16) { 7986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ lea(rax, Operand(rdi, rbx, times_2, -char_size())); 7996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 8006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ lea(rax, Operand(rdi, rbx, times_1, -char_size())); 8016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Store this value in a local variable, for use when clearing 803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // position registers. 804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(Operand(rbp, kInputStartMinusOne), rax); 805d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke 806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (num_saved_registers_ > 0) { 807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fill saved registers with initial value = start offset - 1 808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fill in stack push order, to avoid accessing across an unwritten 809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // page (a problem on Windows). 8108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ Set(rcx, kRegisterZero); 811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label init_loop; 812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&init_loop); 813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(Operand(rbp, rcx, times_1, 0), rax); 814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ subq(rcx, Immediate(kPointerSize)); 815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpq(rcx, 816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Immediate(kRegisterZero - num_saved_registers_ * kPointerSize)); 817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(greater, &init_loop); 818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Ensure that we have written to each stack page, in order. Skipping a page 820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // on Windows can cause segmentation faults. Assuming page size is 4k. 821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int kPageSize = 4096; 822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int kRegistersPerPage = kPageSize / kPointerSize; 823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = num_saved_registers_ + kRegistersPerPage - 1; 824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i < num_registers_; 825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i += kRegistersPerPage) { 826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(register_location(i), rax); // One write every page. 827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Initialize backtrack stack pointer. 830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(backtrack_stackpointer(), Operand(rbp, kStackHighEnd)); 831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Initialize code object pointer. 83244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Move(code_object_pointer(), masm_.CodeObject()); 833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load previous char as initial value of current-character. 834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label at_start; 83525f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ cmpb(Operand(rbp, kStartIndex), Immediate(0)); 83625f6136652d8341ed047e7fc1a450af5bd218ea9Kristian Monsen __ j(equal, &at_start); 837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LoadCurrentCharacterUnchecked(-1, 1); // Load previous char. 838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&start_label_); 839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&at_start); 8408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ Set(current_character(), '\n'); 841a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&start_label_); 842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Exit code: 845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (success_label_.is_linked()) { 846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Save captures when successful. 847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&success_label_); 848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (num_saved_registers_ > 0) { 849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // copy captures to output 8506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ movq(rdx, Operand(rbp, kStartIndex)); 851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rbx, Operand(rbp, kRegisterOutput)); 852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rcx, Operand(rbp, kInputEnd)); 853a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ subq(rcx, Operand(rbp, kInputStart)); 8546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (mode_ == UC16) { 8556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ lea(rcx, Operand(rcx, rdx, times_2, 0)); 8566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 8576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ addq(rcx, rdx); 8586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < num_saved_registers_; i++) { 860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rax, register_location(i)); 861a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ addq(rax, rcx); // Convert to index from start, not end. 862a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mode_ == UC16) { 863a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ sar(rax, Immediate(1)); // Convert byte index to character index. 864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movl(Operand(rbx, i * kIntSize), rax); 866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 8688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ Set(rax, SUCCESS); 869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Exit and return rax 872a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&exit_label_); 873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef _WIN64 875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore callee save registers. 876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(rsp, Operand(rbp, kLastCalleeSaveRegister)); 877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(rbx); 878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(rdi); 879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(rsi); 880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Stack now at rbp. 881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#else 882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore callee save register. 883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rbx, Operand(rbp, kBackup_rbx)); 884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Skip rsp to rbp. 885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rsp, rbp); 886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Exit function frame, restore previous one. 888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(rbp); 889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Backtrack code (branch target for conditional backtracks). 892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (backtrack_label_.is_linked()) { 893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&backtrack_label_); 894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Backtrack(); 895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label exit_with_exception; 898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Preempt-code 900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (check_preempt_label_.is_linked()) { 901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SafeCallTarget(&check_preempt_label_); 902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(backtrack_stackpointer()); 904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(rdi); 905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CallCheckStackGuardState(); 907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ testq(rax, rax); 908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If returning non-zero, we should end execution with the given 909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // result as return value. 910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_zero, &exit_label_); 911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore registers. 91344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Move(code_object_pointer(), masm_.CodeObject()); 914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(rdi); 915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(backtrack_stackpointer()); 916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // String might have moved: Reload esi from frame. 917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rsi, Operand(rbp, kInputEnd)); 918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SafeReturn(); 919a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Backtrack stack overflow code. 922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (stack_overflow_label_.is_linked()) { 923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SafeCallTarget(&stack_overflow_label_); 924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Reached if the backtrack-stack limit has been hit. 925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label grow_failed; 927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Save registers before calling C function 928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifndef _WIN64 929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Callee-save in Microsoft 64-bit ABI, but not in AMD64 ABI. 930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(rsi); 931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(rdi); 932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Call GrowStack(backtrack_stackpointer()) 9358b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch static const int num_arguments = 3; 9364515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ PrepareCallCFunction(num_arguments); 937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef _WIN64 9388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // Microsoft passes parameters in rcx, rdx, r8. 939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // First argument, backtrack stackpointer, is already in rcx. 940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(rdx, Operand(rbp, kStackHighEnd)); // Second argument 9418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ LoadAddress(r8, ExternalReference::isolate_address()); 942a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#else 9438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // AMD64 ABI passes parameters in rdi, rsi, rdx. 944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rdi, backtrack_stackpointer()); // First argument. 945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(rsi, Operand(rbp, kStackHighEnd)); // Second argument. 9468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ LoadAddress(rdx, ExternalReference::isolate_address()); 947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 94844f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference grow_stack = 94944f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference::re_grow_stack(masm_.isolate()); 9504515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ CallCFunction(grow_stack, num_arguments); 951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If return NULL, we have failed to grow the stack, and 952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // must exit with a stack-overflow exception. 953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ testq(rax, rax); 954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(equal, &exit_with_exception); 955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Otherwise use return value as new stack pointer. 956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(backtrack_stackpointer(), rax); 957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Restore saved registers and continue. 95844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Move(code_object_pointer(), masm_.CodeObject()); 959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifndef _WIN64 960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(rdi); 961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(rsi); 962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SafeReturn(); 964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (exit_with_exception.is_linked()) { 967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If any of the code above needed to exit with an exception. 968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&exit_with_exception); 969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Exit with Result EXCEPTION(-1) to signal thrown exception. 9708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ Set(rax, EXCEPTION); 971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&exit_label_); 972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block FixupCodeRelativePositions(); 975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CodeDesc code_desc; 97744f0eee88ff00398ff7f715fab053374d808c90dSteve Block masm_.GetCode(&code_desc); 97844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Isolate* isolate = ISOLATE; 97944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> code = isolate->factory()->NewCode( 98044f0eee88ff00398ff7f715fab053374d808c90dSteve Block code_desc, Code::ComputeFlags(Code::REGEXP), 98144f0eee88ff00398ff7f715fab053374d808c90dSteve Block masm_.CodeObject()); 98244f0eee88ff00398ff7f715fab053374d808c90dSteve Block PROFILE(isolate, RegExpCodeCreateEvent(*code, *source)); 983053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block return Handle<HeapObject>::cast(code); 984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::GoTo(Label* to) { 988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(no_condition, to); 989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::IfRegisterGE(int reg, 993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int comparand, 994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* if_ge) { 995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpq(register_location(reg), Immediate(comparand)); 996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(greater_equal, if_ge); 997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::IfRegisterLT(int reg, 1001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int comparand, 1002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* if_lt) { 1003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpq(register_location(reg), Immediate(comparand)); 1004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(less, if_lt); 1005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::IfRegisterEqPos(int reg, 1009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* if_eq) { 1010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpq(rdi, register_location(reg)); 1011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(equal, if_eq); 1012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockRegExpMacroAssembler::IrregexpImplementation 1016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block RegExpMacroAssemblerX64::Implementation() { 1017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return kX64Implementation; 1018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::LoadCurrentCharacter(int cp_offset, 1022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_end_of_input, 1023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool check_bounds, 1024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int characters) { 1025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(cp_offset >= -1); // ^ and \b can look behind one character. 1026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(cp_offset < (1<<30)); // Be sane! (And ensure negation works) 1027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (check_bounds) { 1028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CheckPosition(cp_offset + characters - 1, on_end_of_input); 1029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LoadCurrentCharacterUnchecked(cp_offset, characters); 1031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::PopCurrentPosition() { 1035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Pop(rdi); 1036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::PopRegister(int register_index) { 1040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Pop(rax); 1041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(register_location(register_index), rax); 1042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::PushBacktrack(Label* label) { 1046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Push(label); 1047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CheckStackLimit(); 1048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::PushCurrentPosition() { 1052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Push(rdi); 1053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::PushRegister(int register_index, 1057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block StackCheckFlag check_stack_limit) { 1058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rax, register_location(register_index)); 1059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Push(rax); 1060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (check_stack_limit) CheckStackLimit(); 1061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::ReadCurrentPositionFromRegister(int reg) { 1065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rdi, register_location(reg)); 1066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::ReadStackPointerFromRegister(int reg) { 1070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(backtrack_stackpointer(), register_location(reg)); 1071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ addq(backtrack_stackpointer(), Operand(rbp, kStackHighEnd)); 1072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1075f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdochvoid RegExpMacroAssemblerX64::SetCurrentPositionFromEnd(int by) { 1076257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label after_position; 1077f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ cmpq(rdi, Immediate(-by * char_size())); 1078257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(greater_equal, &after_position, Label::kNear); 1079f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ movq(rdi, Immediate(-by * char_size())); 1080f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // On RegExp code entry (where this operation is used), the character before 1081f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // the current position is expected to be already loaded. 1082f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // We have advanced the position, so it's safe to read backwards. 1083f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch LoadCurrentCharacterUnchecked(-1, 1); 1084f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ bind(&after_position); 1085f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch} 1086f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 1087f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 1088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::SetRegister(int register_index, int to) { 1089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(register_index >= num_saved_registers_); // Reserved for positions! 1090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(register_location(register_index), Immediate(to)); 1091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::Succeed() { 1095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(&success_label_); 1096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::WriteCurrentPositionToRegister(int reg, 1100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int cp_offset) { 1101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (cp_offset == 0) { 1102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(register_location(reg), rdi); 1103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(rax, Operand(rdi, cp_offset * char_size())); 1105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(register_location(reg), rax); 1106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::ClearRegisters(int reg_from, int reg_to) { 1111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(reg_from <= reg_to); 1112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rax, Operand(rbp, kInputStartMinusOne)); 1113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int reg = reg_from; reg <= reg_to; reg++) { 1114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(register_location(reg), rax); 1115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::WriteStackPointerToRegister(int reg) { 1120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rax, backtrack_stackpointer()); 1121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ subq(rax, Operand(rbp, kStackHighEnd)); 1122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(register_location(reg), rax); 1123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Private methods: 1127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::CallCheckStackGuardState() { 1129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // This function call preserves no register values. Caller should 1130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // store anything volatile in a C call or overwritten by this function. 11316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block static const int num_arguments = 3; 11324515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ PrepareCallCFunction(num_arguments); 1133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef _WIN64 1134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Second argument: Code* of self. (Do this before overwriting r8). 1135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rdx, code_object_pointer()); 1136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Third argument: RegExp code frame pointer. 1137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(r8, rbp); 1138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // First argument: Next address on the stack (will be address of 1139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // return address). 1140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(rcx, Operand(rsp, -kPointerSize)); 1141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#else 1142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Third argument: RegExp code frame pointer. 1143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rdx, rbp); 1144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Second argument: Code* of self. 1145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rsi, code_object_pointer()); 1146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // First argument: Next address on the stack (will be address of 1147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // return address). 1148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(rdi, Operand(rsp, -kPointerSize)); 1149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 1150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference stack_check = 115144f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference::re_check_stack_guard_state(masm_.isolate()); 11524515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ CallCFunction(stack_check, num_arguments); 1153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Helper function for reading a value out of a stack frame. 1157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocktemplate <typename T> 1158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic T& frame_entry(Address re_frame, int frame_offset) { 1159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return reinterpret_cast<T&>(Memory::int32_at(re_frame + frame_offset)); 1160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint RegExpMacroAssemblerX64::CheckStackGuardState(Address* return_address, 1164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code* re_code, 1165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Address re_frame) { 116644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Isolate* isolate = frame_entry<Isolate*>(re_frame, kIsolate); 116744f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(isolate == Isolate::Current()); 116844f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (isolate->stack_guard()->IsStackOverflow()) { 116944f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate->StackOverflow(); 1170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return EXCEPTION; 1171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If not real stack overflow the stack guard was used to interrupt 1174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // execution for another purpose. 1175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 11764515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // If this is a direct call from JavaScript retry the RegExp forcing the call 11774515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // through the runtime system. Currently the direct call cannot handle a GC. 11784515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke if (frame_entry<int>(re_frame, kDirectCall) == 1) { 11794515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke return RETRY; 11804515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke } 11814515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke 1182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Prepare for possible GC. 118369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch HandleScope handles(isolate); 1184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Code> code_handle(re_code); 1185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<String> subject(frame_entry<String*>(re_frame, kInputString)); 118769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 1188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Current string. 118969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch bool is_ascii = subject->IsAsciiRepresentationUnderneath(); 1190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(re_code->instruction_start() <= *return_address); 1192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(*return_address <= 1193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block re_code->instruction_start() + re_code->instruction_size()); 1194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 11953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MaybeObject* result = Execution::HandleStackGuardInterrupt(isolate); 1196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (*code_handle != re_code) { // Return address no longer valid 119869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch intptr_t delta = code_handle->address() - re_code->address(); 1199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Overwrite the return address on the stack. 1200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block *return_address += delta; 1201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (result->IsException()) { 1204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return EXCEPTION; 1205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 120769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Handle<String> subject_tmp = subject; 120869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch int slice_offset = 0; 120969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 121069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Extract the underlying string and the slice offset. 121169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (StringShape(*subject_tmp).IsCons()) { 121269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch subject_tmp = Handle<String>(ConsString::cast(*subject_tmp)->first()); 121369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } else if (StringShape(*subject_tmp).IsSliced()) { 121469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch SlicedString* slice = SlicedString::cast(*subject_tmp); 121569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch subject_tmp = Handle<String>(slice->parent()); 121669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch slice_offset = slice->offset(); 121769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 121869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 1219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // String might have changed. 122069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (subject_tmp->IsAsciiRepresentation() != is_ascii) { 1221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If we changed between an ASCII and an UC16 string, the specialized 1222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // code cannot be used, and we need to restart regexp matching from 1223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // scratch (including, potentially, compiling a new version of the code). 1224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return RETRY; 1225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Otherwise, the content of the string might have moved. It must still 1228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // be a sequential or external string with the same content. 1229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Update the start and end pointers in the stack frame to the current 1230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // location (whether it has actually moved or not). 123169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch ASSERT(StringShape(*subject_tmp).IsSequential() || 123269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch StringShape(*subject_tmp).IsExternal()); 1233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The original start address of the characters to match. 1235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const byte* start_address = frame_entry<const byte*>(re_frame, kInputStart); 1236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Find the current start address of the same character at the current string 1238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // position. 1239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int start_index = frame_entry<int>(re_frame, kStartIndex); 124069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch const byte* new_address = StringCharacterPosition(*subject_tmp, 124169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch start_index + slice_offset); 1242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (start_address != new_address) { 1244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If there is a difference, update the object pointer and start and end 1245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // addresses in the RegExp stack frame to match the new value. 1246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const byte* end_address = frame_entry<const byte* >(re_frame, kInputEnd); 1247d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block int byte_length = static_cast<int>(end_address - start_address); 1248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block frame_entry<const String*>(re_frame, kInputString) = *subject; 1249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block frame_entry<const byte*>(re_frame, kInputStart) = new_address; 1250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block frame_entry<const byte*>(re_frame, kInputEnd) = new_address + byte_length; 12513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (frame_entry<const String*>(re_frame, kInputString) != *subject) { 12523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Subject string might have been a ConsString that underwent 12533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // short-circuiting during GC. That will not change start_address but 12543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // will change pointer inside the subject handle. 12553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch frame_entry<const String*>(re_frame, kInputString) = *subject; 1256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return 0; 1259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockOperand RegExpMacroAssemblerX64::register_location(int register_index) { 1263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(register_index < (1<<30)); 1264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (num_registers_ <= register_index) { 1265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block num_registers_ = register_index + 1; 1266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return Operand(rbp, kRegisterZero - register_index * kPointerSize); 1268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::CheckPosition(int cp_offset, 1272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* on_outside_input) { 1273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpl(rdi, Immediate(-cp_offset * char_size())); 1274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block BranchOrBacktrack(greater_equal, on_outside_input); 1275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::BranchOrBacktrack(Condition condition, 1279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* to) { 1280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (condition < 0) { // No condition 1281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (to == NULL) { 1282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Backtrack(); 1283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 1284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(to); 1286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 1287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (to == NULL) { 1289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(condition, &backtrack_label_); 1290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return; 1291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(condition, to); 1293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::SafeCall(Label* to) { 1297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ call(to); 1298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::SafeCallTarget(Label* label) { 1302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(label); 1303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ subq(Operand(rsp, 0), code_object_pointer()); 1304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::SafeReturn() { 1308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ addq(Operand(rsp, 0), code_object_pointer()); 1309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 1310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::Push(Register source) { 1314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!source.is(backtrack_stackpointer())); 1315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Notice: This updates flags, unlike normal Push. 1316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ subq(backtrack_stackpointer(), Immediate(kIntSize)); 1317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movl(Operand(backtrack_stackpointer(), 0), source); 1318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::Push(Immediate value) { 1322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Notice: This updates flags, unlike normal Push. 1323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ subq(backtrack_stackpointer(), Immediate(kIntSize)); 1324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movl(Operand(backtrack_stackpointer(), 0), value); 1325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::FixupCodeRelativePositions() { 1329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0, n = code_relative_fixup_positions_.length(); i < n; i++) { 1330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int position = code_relative_fixup_positions_[i]; 1331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The position succeeds a relative label offset from position. 1332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Patch the relative offset to be relative to the Code object pointer 1333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // instead. 1334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int patch_position = position - kIntSize; 133544f0eee88ff00398ff7f715fab053374d808c90dSteve Block int offset = masm_.long_at(patch_position); 133644f0eee88ff00398ff7f715fab053374d808c90dSteve Block masm_.long_at_put(patch_position, 1337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block offset 1338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block + position 1339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block + Code::kHeaderSize 1340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block - kHeapObjectTag); 1341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block code_relative_fixup_positions_.Clear(); 1343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::Push(Label* backtrack_target) { 1347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ subq(backtrack_stackpointer(), Immediate(kIntSize)); 1348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movl(Operand(backtrack_stackpointer(), 0), backtrack_target); 1349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block MarkPositionForCodeRelativeFixup(); 1350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::Pop(Register target) { 1354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!target.is(backtrack_stackpointer())); 1355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movsxlq(target, Operand(backtrack_stackpointer(), 0)); 1356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Notice: This updates flags, unlike normal Pop. 1357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ addq(backtrack_stackpointer(), Immediate(kIntSize)); 1358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::Drop() { 1362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ addq(backtrack_stackpointer(), Immediate(kIntSize)); 1363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::CheckPreemption() { 1367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check for preemption. 1368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label no_preempt; 1369d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ExternalReference stack_limit = 137044f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference::address_of_stack_limit(masm_.isolate()); 1371d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ load_rax(stack_limit); 1372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpq(rsp, rax); 1373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(above, &no_preempt); 1374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block SafeCall(&check_preempt_label_); 1376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&no_preempt); 1378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::CheckStackLimit() { 1382d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block Label no_stack_overflow; 1383d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block ExternalReference stack_limit = 138444f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference::address_of_regexp_stack_limit(masm_.isolate()); 1385d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ load_rax(stack_limit); 1386d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ cmpq(backtrack_stackpointer(), rax); 1387d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ j(above, &no_stack_overflow); 1388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1389d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block SafeCall(&stack_overflow_label_); 1390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1391d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ bind(&no_stack_overflow); 1392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid RegExpMacroAssemblerX64::LoadCurrentCharacterUnchecked(int cp_offset, 1396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int characters) { 1397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (mode_ == ASCII) { 1398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (characters == 4) { 1399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movl(current_character(), Operand(rsi, rdi, times_1, cp_offset)); 1400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else if (characters == 2) { 1401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzxwl(current_character(), Operand(rsi, rdi, times_1, cp_offset)); 1402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(characters == 1); 1404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzxbl(current_character(), Operand(rsi, rdi, times_1, cp_offset)); 1405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(mode_ == UC16); 1408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (characters == 2) { 1409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movl(current_character(), 1410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Operand(rsi, rdi, times_1, cp_offset * sizeof(uc16))); 1411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 1412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(characters == 1); 1413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzxwl(current_character(), 1414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Operand(rsi, rdi, times_1, cp_offset * sizeof(uc16))); 1415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __ 1420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 14216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#endif // V8_INTERPRETED_REGEXP 1422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}} // namespace v8::internal 1424f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 1425f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif // V8_TARGET_ARCH_X64 1426