1// Copyright 2012 the V8 project authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#if V8_TARGET_ARCH_MIPS64 6 7#include "src/regexp/mips64/regexp-macro-assembler-mips64.h" 8 9#include "src/code-stubs.h" 10#include "src/log.h" 11#include "src/macro-assembler.h" 12#include "src/regexp/regexp-macro-assembler.h" 13#include "src/regexp/regexp-stack.h" 14#include "src/unicode.h" 15 16namespace v8 { 17namespace internal { 18 19#ifndef V8_INTERPRETED_REGEXP 20/* 21 * This assembler uses the following register assignment convention 22 * - t3 : Temporarily stores the index of capture start after a matching pass 23 * for a global regexp. 24 * - a5 : Pointer to current code object (Code*) including heap object tag. 25 * - a6 : Current position in input, as negative offset from end of string. 26 * Please notice that this is the byte offset, not the character offset! 27 * - a7 : Currently loaded character. Must be loaded using 28 * LoadCurrentCharacter before using any of the dispatch methods. 29 * - t0 : Points to tip of backtrack stack 30 * - t1 : Unused. 31 * - t2 : End of input (points to byte after last character in input). 32 * - fp : Frame pointer. Used to access arguments, local variables and 33 * RegExp registers. 34 * - sp : Points to tip of C stack. 35 * 36 * The remaining registers are free for computations. 37 * Each call to a public method should retain this convention. 38 * 39 * TODO(plind): O32 documented here with intent of having single 32/64 codebase 40 * in the future. 41 * 42 * The O32 stack will have the following structure: 43 * 44 * - fp[76] Isolate* isolate (address of the current isolate) 45 * - fp[72] direct_call (if 1, direct call from JavaScript code, 46 * if 0, call through the runtime system). 47 * - fp[68] stack_area_base (High end of the memory area to use as 48 * backtracking stack). 49 * - fp[64] capture array size (may fit multiple sets of matches) 50 * - fp[60] int* capture_array (int[num_saved_registers_], for output). 51 * - fp[44..59] MIPS O32 four argument slots 52 * - fp[40] secondary link/return address used by native call. 53 * --- sp when called --- 54 * - fp[36] return address (lr). 55 * - fp[32] old frame pointer (r11). 56 * - fp[0..31] backup of registers s0..s7. 57 * --- frame pointer ---- 58 * - fp[-4] end of input (address of end of string). 59 * - fp[-8] start of input (address of first character in string). 60 * - fp[-12] start index (character index of start). 61 * - fp[-16] void* input_string (location of a handle containing the string). 62 * - fp[-20] success counter (only for global regexps to count matches). 63 * - fp[-24] Offset of location before start of input (effectively character 64 * string start - 1). Used to initialize capture registers to a 65 * non-position. 66 * - fp[-28] At start (if 1, we are starting at the start of the 67 * string, otherwise 0) 68 * - fp[-32] register 0 (Only positions must be stored in the first 69 * - register 1 num_saved_registers_ registers) 70 * - ... 71 * - register num_registers-1 72 * --- sp --- 73 * 74 * 75 * The N64 stack will have the following structure: 76 * 77 * - fp[88] Isolate* isolate (address of the current isolate) kIsolate 78 * - fp[80] secondary link/return address used by exit frame on native call. kSecondaryReturnAddress 79 kStackFrameHeader 80 * --- sp when called --- 81 * - fp[72] ra Return from RegExp code (ra). kReturnAddress 82 * - fp[64] s9, old-fp Old fp, callee saved(s9). 83 * - fp[0..63] s0..s7 Callee-saved registers s0..s7. 84 * --- frame pointer ---- 85 * - fp[-8] direct_call (1 = direct call from JS, 0 = from runtime) kDirectCall 86 * - fp[-16] stack_base (Top of backtracking stack). kStackHighEnd 87 * - fp[-24] capture array size (may fit multiple sets of matches) kNumOutputRegisters 88 * - fp[-32] int* capture_array (int[num_saved_registers_], for output). kRegisterOutput 89 * - fp[-40] end of input (address of end of string). kInputEnd 90 * - fp[-48] start of input (address of first character in string). kInputStart 91 * - fp[-56] start index (character index of start). kStartIndex 92 * - fp[-64] void* input_string (location of a handle containing the string). kInputString 93 * - fp[-72] success counter (only for global regexps to count matches). kSuccessfulCaptures 94 * - fp[-80] Offset of location before start of input (effectively character kStringStartMinusOne 95 * position -1). Used to initialize capture registers to a 96 * non-position. 97 * --------- The following output registers are 32-bit values. --------- 98 * - fp[-88] register 0 (Only positions must be stored in the first kRegisterZero 99 * - register 1 num_saved_registers_ registers) 100 * - ... 101 * - register num_registers-1 102 * --- sp --- 103 * 104 * The first num_saved_registers_ registers are initialized to point to 105 * "character -1" in the string (i.e., char_size() bytes before the first 106 * character of the string). The remaining registers start out as garbage. 107 * 108 * The data up to the return address must be placed there by the calling 109 * code and the remaining arguments are passed in registers, e.g. by calling the 110 * code entry as cast to a function with the signature: 111 * int (*match)(String* input_string, 112 * int start_index, 113 * Address start, 114 * Address end, 115 * Address secondary_return_address, // Only used by native call. 116 * int* capture_output_array, 117 * byte* stack_area_base, 118 * bool direct_call = false, 119 * void* return_address, 120 * Isolate* isolate); 121 * The call is performed by NativeRegExpMacroAssembler::Execute() 122 * (in regexp-macro-assembler.cc) via the CALL_GENERATED_REGEXP_CODE macro 123 * in mips/simulator-mips.h. 124 * When calling as a non-direct call (i.e., from C++ code), the return address 125 * area is overwritten with the ra register by the RegExp code. When doing a 126 * direct call from generated code, the return address is placed there by 127 * the calling code, as in a normal exit frame. 128 */ 129 130#define __ ACCESS_MASM(masm_) 131 132RegExpMacroAssemblerMIPS::RegExpMacroAssemblerMIPS(Isolate* isolate, Zone* zone, 133 Mode mode, 134 int registers_to_save) 135 : NativeRegExpMacroAssembler(isolate, zone), 136 masm_(new MacroAssembler(isolate, NULL, kRegExpCodeSize, 137 CodeObjectRequired::kYes)), 138 mode_(mode), 139 num_registers_(registers_to_save), 140 num_saved_registers_(registers_to_save), 141 entry_label_(), 142 start_label_(), 143 success_label_(), 144 backtrack_label_(), 145 exit_label_(), 146 internal_failure_label_() { 147 DCHECK_EQ(0, registers_to_save % 2); 148 __ jmp(&entry_label_); // We'll write the entry code later. 149 // If the code gets too big or corrupted, an internal exception will be 150 // raised, and we will exit right away. 151 __ bind(&internal_failure_label_); 152 __ li(v0, Operand(FAILURE)); 153 __ Ret(); 154 __ bind(&start_label_); // And then continue from here. 155} 156 157 158RegExpMacroAssemblerMIPS::~RegExpMacroAssemblerMIPS() { 159 delete masm_; 160 // Unuse labels in case we throw away the assembler without calling GetCode. 161 entry_label_.Unuse(); 162 start_label_.Unuse(); 163 success_label_.Unuse(); 164 backtrack_label_.Unuse(); 165 exit_label_.Unuse(); 166 check_preempt_label_.Unuse(); 167 stack_overflow_label_.Unuse(); 168 internal_failure_label_.Unuse(); 169} 170 171 172int RegExpMacroAssemblerMIPS::stack_limit_slack() { 173 return RegExpStack::kStackLimitSlack; 174} 175 176 177void RegExpMacroAssemblerMIPS::AdvanceCurrentPosition(int by) { 178 if (by != 0) { 179 __ Daddu(current_input_offset(), 180 current_input_offset(), Operand(by * char_size())); 181 } 182} 183 184 185void RegExpMacroAssemblerMIPS::AdvanceRegister(int reg, int by) { 186 DCHECK(reg >= 0); 187 DCHECK(reg < num_registers_); 188 if (by != 0) { 189 __ ld(a0, register_location(reg)); 190 __ Daddu(a0, a0, Operand(by)); 191 __ sd(a0, register_location(reg)); 192 } 193} 194 195 196void RegExpMacroAssemblerMIPS::Backtrack() { 197 CheckPreemption(); 198 // Pop Code* offset from backtrack stack, add Code* and jump to location. 199 Pop(a0); 200 __ Daddu(a0, a0, code_pointer()); 201 __ Jump(a0); 202} 203 204 205void RegExpMacroAssemblerMIPS::Bind(Label* label) { 206 __ bind(label); 207} 208 209 210void RegExpMacroAssemblerMIPS::CheckCharacter(uint32_t c, Label* on_equal) { 211 BranchOrBacktrack(on_equal, eq, current_character(), Operand(c)); 212} 213 214 215void RegExpMacroAssemblerMIPS::CheckCharacterGT(uc16 limit, Label* on_greater) { 216 BranchOrBacktrack(on_greater, gt, current_character(), Operand(limit)); 217} 218 219 220void RegExpMacroAssemblerMIPS::CheckAtStart(Label* on_at_start) { 221 __ ld(a1, MemOperand(frame_pointer(), kStringStartMinusOne)); 222 __ Daddu(a0, current_input_offset(), Operand(-char_size())); 223 BranchOrBacktrack(on_at_start, eq, a0, Operand(a1)); 224} 225 226 227void RegExpMacroAssemblerMIPS::CheckNotAtStart(int cp_offset, 228 Label* on_not_at_start) { 229 __ ld(a1, MemOperand(frame_pointer(), kStringStartMinusOne)); 230 __ Daddu(a0, current_input_offset(), 231 Operand(-char_size() + cp_offset * char_size())); 232 BranchOrBacktrack(on_not_at_start, ne, a0, Operand(a1)); 233} 234 235 236void RegExpMacroAssemblerMIPS::CheckCharacterLT(uc16 limit, Label* on_less) { 237 BranchOrBacktrack(on_less, lt, current_character(), Operand(limit)); 238} 239 240 241void RegExpMacroAssemblerMIPS::CheckGreedyLoop(Label* on_equal) { 242 Label backtrack_non_equal; 243 __ lw(a0, MemOperand(backtrack_stackpointer(), 0)); 244 __ Branch(&backtrack_non_equal, ne, current_input_offset(), Operand(a0)); 245 __ Daddu(backtrack_stackpointer(), 246 backtrack_stackpointer(), 247 Operand(kIntSize)); 248 __ bind(&backtrack_non_equal); 249 BranchOrBacktrack(on_equal, eq, current_input_offset(), Operand(a0)); 250} 251 252 253void RegExpMacroAssemblerMIPS::CheckNotBackReferenceIgnoreCase( 254 int start_reg, bool read_backward, bool unicode, Label* on_no_match) { 255 Label fallthrough; 256 __ ld(a0, register_location(start_reg)); // Index of start of capture. 257 __ ld(a1, register_location(start_reg + 1)); // Index of end of capture. 258 __ Dsubu(a1, a1, a0); // Length of capture. 259 260 // At this point, the capture registers are either both set or both cleared. 261 // If the capture length is zero, then the capture is either empty or cleared. 262 // Fall through in both cases. 263 __ Branch(&fallthrough, eq, a1, Operand(zero_reg)); 264 265 if (read_backward) { 266 __ ld(t1, MemOperand(frame_pointer(), kStringStartMinusOne)); 267 __ Daddu(t1, t1, a1); 268 BranchOrBacktrack(on_no_match, le, current_input_offset(), Operand(t1)); 269 } else { 270 __ Daddu(t1, a1, current_input_offset()); 271 // Check that there are enough characters left in the input. 272 BranchOrBacktrack(on_no_match, gt, t1, Operand(zero_reg)); 273 } 274 275 if (mode_ == LATIN1) { 276 Label success; 277 Label fail; 278 Label loop_check; 279 280 // a0 - offset of start of capture. 281 // a1 - length of capture. 282 __ Daddu(a0, a0, Operand(end_of_input_address())); 283 __ Daddu(a2, end_of_input_address(), Operand(current_input_offset())); 284 if (read_backward) { 285 __ Dsubu(a2, a2, Operand(a1)); 286 } 287 __ Daddu(a1, a0, Operand(a1)); 288 289 // a0 - Address of start of capture. 290 // a1 - Address of end of capture. 291 // a2 - Address of current input position. 292 293 Label loop; 294 __ bind(&loop); 295 __ lbu(a3, MemOperand(a0, 0)); 296 __ daddiu(a0, a0, char_size()); 297 __ lbu(a4, MemOperand(a2, 0)); 298 __ daddiu(a2, a2, char_size()); 299 300 __ Branch(&loop_check, eq, a4, Operand(a3)); 301 302 // Mismatch, try case-insensitive match (converting letters to lower-case). 303 __ Or(a3, a3, Operand(0x20)); // Convert capture character to lower-case. 304 __ Or(a4, a4, Operand(0x20)); // Also convert input character. 305 __ Branch(&fail, ne, a4, Operand(a3)); 306 __ Dsubu(a3, a3, Operand('a')); 307 __ Branch(&loop_check, ls, a3, Operand('z' - 'a')); 308 // Latin-1: Check for values in range [224,254] but not 247. 309 __ Dsubu(a3, a3, Operand(224 - 'a')); 310 // Weren't Latin-1 letters. 311 __ Branch(&fail, hi, a3, Operand(254 - 224)); 312 // Check for 247. 313 __ Branch(&fail, eq, a3, Operand(247 - 224)); 314 315 __ bind(&loop_check); 316 __ Branch(&loop, lt, a0, Operand(a1)); 317 __ jmp(&success); 318 319 __ bind(&fail); 320 GoTo(on_no_match); 321 322 __ bind(&success); 323 // Compute new value of character position after the matched part. 324 __ Dsubu(current_input_offset(), a2, end_of_input_address()); 325 if (read_backward) { 326 __ ld(t1, register_location(start_reg)); // Index of start of capture. 327 __ ld(a2, register_location(start_reg + 1)); // Index of end of capture. 328 __ Daddu(current_input_offset(), current_input_offset(), Operand(t1)); 329 __ Dsubu(current_input_offset(), current_input_offset(), Operand(a2)); 330 } 331 } else { 332 DCHECK(mode_ == UC16); 333 // Put regexp engine registers on stack. 334 RegList regexp_registers_to_retain = current_input_offset().bit() | 335 current_character().bit() | backtrack_stackpointer().bit(); 336 __ MultiPush(regexp_registers_to_retain); 337 338 int argument_count = 4; 339 __ PrepareCallCFunction(argument_count, a2); 340 341 // a0 - offset of start of capture. 342 // a1 - length of capture. 343 344 // Put arguments into arguments registers. 345 // Parameters are 346 // a0: Address byte_offset1 - Address captured substring's start. 347 // a1: Address byte_offset2 - Address of current character position. 348 // a2: size_t byte_length - length of capture in bytes(!). 349 // a3: Isolate* isolate or 0 if unicode flag. 350 351 // Address of start of capture. 352 __ Daddu(a0, a0, Operand(end_of_input_address())); 353 // Length of capture. 354 __ mov(a2, a1); 355 // Save length in callee-save register for use on return. 356 __ mov(s3, a1); 357 // Address of current input position. 358 __ Daddu(a1, current_input_offset(), Operand(end_of_input_address())); 359 if (read_backward) { 360 __ Dsubu(a1, a1, Operand(s3)); 361 } 362 // Isolate. 363#ifdef V8_I18N_SUPPORT 364 if (unicode) { 365 __ mov(a3, zero_reg); 366 } else // NOLINT 367#endif // V8_I18N_SUPPORT 368 { 369 __ li(a3, Operand(ExternalReference::isolate_address(masm_->isolate()))); 370 } 371 372 { 373 AllowExternalCallThatCantCauseGC scope(masm_); 374 ExternalReference function = 375 ExternalReference::re_case_insensitive_compare_uc16(masm_->isolate()); 376 __ CallCFunction(function, argument_count); 377 } 378 379 // Restore regexp engine registers. 380 __ MultiPop(regexp_registers_to_retain); 381 __ li(code_pointer(), Operand(masm_->CodeObject()), CONSTANT_SIZE); 382 __ ld(end_of_input_address(), MemOperand(frame_pointer(), kInputEnd)); 383 384 // Check if function returned non-zero for success or zero for failure. 385 BranchOrBacktrack(on_no_match, eq, v0, Operand(zero_reg)); 386 // On success, increment position by length of capture. 387 if (read_backward) { 388 __ Dsubu(current_input_offset(), current_input_offset(), Operand(s3)); 389 } else { 390 __ Daddu(current_input_offset(), current_input_offset(), Operand(s3)); 391 } 392 } 393 394 __ bind(&fallthrough); 395} 396 397 398void RegExpMacroAssemblerMIPS::CheckNotBackReference(int start_reg, 399 bool read_backward, 400 Label* on_no_match) { 401 Label fallthrough; 402 Label success; 403 404 // Find length of back-referenced capture. 405 __ ld(a0, register_location(start_reg)); 406 __ ld(a1, register_location(start_reg + 1)); 407 __ Dsubu(a1, a1, a0); // Length to check. 408 409 // At this point, the capture registers are either both set or both cleared. 410 // If the capture length is zero, then the capture is either empty or cleared. 411 // Fall through in both cases. 412 __ Branch(&fallthrough, eq, a1, Operand(zero_reg)); 413 414 if (read_backward) { 415 __ ld(t1, MemOperand(frame_pointer(), kStringStartMinusOne)); 416 __ Daddu(t1, t1, a1); 417 BranchOrBacktrack(on_no_match, le, current_input_offset(), Operand(t1)); 418 } else { 419 __ Daddu(t1, a1, current_input_offset()); 420 // Check that there are enough characters left in the input. 421 BranchOrBacktrack(on_no_match, gt, t1, Operand(zero_reg)); 422 } 423 424 // Compute pointers to match string and capture string. 425 __ Daddu(a0, a0, Operand(end_of_input_address())); 426 __ Daddu(a2, end_of_input_address(), Operand(current_input_offset())); 427 if (read_backward) { 428 __ Dsubu(a2, a2, Operand(a1)); 429 } 430 __ Daddu(a1, a1, Operand(a0)); 431 432 Label loop; 433 __ bind(&loop); 434 if (mode_ == LATIN1) { 435 __ lbu(a3, MemOperand(a0, 0)); 436 __ daddiu(a0, a0, char_size()); 437 __ lbu(a4, MemOperand(a2, 0)); 438 __ daddiu(a2, a2, char_size()); 439 } else { 440 DCHECK(mode_ == UC16); 441 __ lhu(a3, MemOperand(a0, 0)); 442 __ daddiu(a0, a0, char_size()); 443 __ lhu(a4, MemOperand(a2, 0)); 444 __ daddiu(a2, a2, char_size()); 445 } 446 BranchOrBacktrack(on_no_match, ne, a3, Operand(a4)); 447 __ Branch(&loop, lt, a0, Operand(a1)); 448 449 // Move current character position to position after match. 450 __ Dsubu(current_input_offset(), a2, end_of_input_address()); 451 if (read_backward) { 452 __ ld(t1, register_location(start_reg)); // Index of start of capture. 453 __ ld(a2, register_location(start_reg + 1)); // Index of end of capture. 454 __ Daddu(current_input_offset(), current_input_offset(), Operand(t1)); 455 __ Dsubu(current_input_offset(), current_input_offset(), Operand(a2)); 456 } 457 __ bind(&fallthrough); 458} 459 460 461void RegExpMacroAssemblerMIPS::CheckNotCharacter(uint32_t c, 462 Label* on_not_equal) { 463 BranchOrBacktrack(on_not_equal, ne, current_character(), Operand(c)); 464} 465 466 467void RegExpMacroAssemblerMIPS::CheckCharacterAfterAnd(uint32_t c, 468 uint32_t mask, 469 Label* on_equal) { 470 __ And(a0, current_character(), Operand(mask)); 471 Operand rhs = (c == 0) ? Operand(zero_reg) : Operand(c); 472 BranchOrBacktrack(on_equal, eq, a0, rhs); 473} 474 475 476void RegExpMacroAssemblerMIPS::CheckNotCharacterAfterAnd(uint32_t c, 477 uint32_t mask, 478 Label* on_not_equal) { 479 __ And(a0, current_character(), Operand(mask)); 480 Operand rhs = (c == 0) ? Operand(zero_reg) : Operand(c); 481 BranchOrBacktrack(on_not_equal, ne, a0, rhs); 482} 483 484 485void RegExpMacroAssemblerMIPS::CheckNotCharacterAfterMinusAnd( 486 uc16 c, 487 uc16 minus, 488 uc16 mask, 489 Label* on_not_equal) { 490 DCHECK(minus < String::kMaxUtf16CodeUnit); 491 __ Dsubu(a0, current_character(), Operand(minus)); 492 __ And(a0, a0, Operand(mask)); 493 BranchOrBacktrack(on_not_equal, ne, a0, Operand(c)); 494} 495 496 497void RegExpMacroAssemblerMIPS::CheckCharacterInRange( 498 uc16 from, 499 uc16 to, 500 Label* on_in_range) { 501 __ Dsubu(a0, current_character(), Operand(from)); 502 // Unsigned lower-or-same condition. 503 BranchOrBacktrack(on_in_range, ls, a0, Operand(to - from)); 504} 505 506 507void RegExpMacroAssemblerMIPS::CheckCharacterNotInRange( 508 uc16 from, 509 uc16 to, 510 Label* on_not_in_range) { 511 __ Dsubu(a0, current_character(), Operand(from)); 512 // Unsigned higher condition. 513 BranchOrBacktrack(on_not_in_range, hi, a0, Operand(to - from)); 514} 515 516 517void RegExpMacroAssemblerMIPS::CheckBitInTable( 518 Handle<ByteArray> table, 519 Label* on_bit_set) { 520 __ li(a0, Operand(table)); 521 if (mode_ != LATIN1 || kTableMask != String::kMaxOneByteCharCode) { 522 __ And(a1, current_character(), Operand(kTableSize - 1)); 523 __ Daddu(a0, a0, a1); 524 } else { 525 __ Daddu(a0, a0, current_character()); 526 } 527 528 __ lbu(a0, FieldMemOperand(a0, ByteArray::kHeaderSize)); 529 BranchOrBacktrack(on_bit_set, ne, a0, Operand(zero_reg)); 530} 531 532 533bool RegExpMacroAssemblerMIPS::CheckSpecialCharacterClass(uc16 type, 534 Label* on_no_match) { 535 // Range checks (c in min..max) are generally implemented by an unsigned 536 // (c - min) <= (max - min) check. 537 switch (type) { 538 case 's': 539 // Match space-characters. 540 if (mode_ == LATIN1) { 541 // One byte space characters are '\t'..'\r', ' ' and \u00a0. 542 Label success; 543 __ Branch(&success, eq, current_character(), Operand(' ')); 544 // Check range 0x09..0x0d. 545 __ Dsubu(a0, current_character(), Operand('\t')); 546 __ Branch(&success, ls, a0, Operand('\r' - '\t')); 547 // \u00a0 (NBSP). 548 BranchOrBacktrack(on_no_match, ne, a0, Operand(0x00a0 - '\t')); 549 __ bind(&success); 550 return true; 551 } 552 return false; 553 case 'S': 554 // The emitted code for generic character classes is good enough. 555 return false; 556 case 'd': 557 // Match Latin1 digits ('0'..'9'). 558 __ Dsubu(a0, current_character(), Operand('0')); 559 BranchOrBacktrack(on_no_match, hi, a0, Operand('9' - '0')); 560 return true; 561 case 'D': 562 // Match non Latin1-digits. 563 __ Dsubu(a0, current_character(), Operand('0')); 564 BranchOrBacktrack(on_no_match, ls, a0, Operand('9' - '0')); 565 return true; 566 case '.': { 567 // Match non-newlines (not 0x0a('\n'), 0x0d('\r'), 0x2028 and 0x2029). 568 __ Xor(a0, current_character(), Operand(0x01)); 569 // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c. 570 __ Dsubu(a0, a0, Operand(0x0b)); 571 BranchOrBacktrack(on_no_match, ls, a0, Operand(0x0c - 0x0b)); 572 if (mode_ == UC16) { 573 // Compare original value to 0x2028 and 0x2029, using the already 574 // computed (current_char ^ 0x01 - 0x0b). I.e., check for 575 // 0x201d (0x2028 - 0x0b) or 0x201e. 576 __ Dsubu(a0, a0, Operand(0x2028 - 0x0b)); 577 BranchOrBacktrack(on_no_match, ls, a0, Operand(1)); 578 } 579 return true; 580 } 581 case 'n': { 582 // Match newlines (0x0a('\n'), 0x0d('\r'), 0x2028 and 0x2029). 583 __ Xor(a0, current_character(), Operand(0x01)); 584 // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c. 585 __ Dsubu(a0, a0, Operand(0x0b)); 586 if (mode_ == LATIN1) { 587 BranchOrBacktrack(on_no_match, hi, a0, Operand(0x0c - 0x0b)); 588 } else { 589 Label done; 590 BranchOrBacktrack(&done, ls, a0, Operand(0x0c - 0x0b)); 591 // Compare original value to 0x2028 and 0x2029, using the already 592 // computed (current_char ^ 0x01 - 0x0b). I.e., check for 593 // 0x201d (0x2028 - 0x0b) or 0x201e. 594 __ Dsubu(a0, a0, Operand(0x2028 - 0x0b)); 595 BranchOrBacktrack(on_no_match, hi, a0, Operand(1)); 596 __ bind(&done); 597 } 598 return true; 599 } 600 case 'w': { 601 if (mode_ != LATIN1) { 602 // Table is 256 entries, so all Latin1 characters can be tested. 603 BranchOrBacktrack(on_no_match, hi, current_character(), Operand('z')); 604 } 605 ExternalReference map = ExternalReference::re_word_character_map(); 606 __ li(a0, Operand(map)); 607 __ Daddu(a0, a0, current_character()); 608 __ lbu(a0, MemOperand(a0, 0)); 609 BranchOrBacktrack(on_no_match, eq, a0, Operand(zero_reg)); 610 return true; 611 } 612 case 'W': { 613 Label done; 614 if (mode_ != LATIN1) { 615 // Table is 256 entries, so all Latin1 characters can be tested. 616 __ Branch(&done, hi, current_character(), Operand('z')); 617 } 618 ExternalReference map = ExternalReference::re_word_character_map(); 619 __ li(a0, Operand(map)); 620 __ Daddu(a0, a0, current_character()); 621 __ lbu(a0, MemOperand(a0, 0)); 622 BranchOrBacktrack(on_no_match, ne, a0, Operand(zero_reg)); 623 if (mode_ != LATIN1) { 624 __ bind(&done); 625 } 626 return true; 627 } 628 case '*': 629 // Match any character. 630 return true; 631 // No custom implementation (yet): s(UC16), S(UC16). 632 default: 633 return false; 634 } 635} 636 637 638void RegExpMacroAssemblerMIPS::Fail() { 639 __ li(v0, Operand(FAILURE)); 640 __ jmp(&exit_label_); 641} 642 643 644Handle<HeapObject> RegExpMacroAssemblerMIPS::GetCode(Handle<String> source) { 645 Label return_v0; 646 if (masm_->has_exception()) { 647 // If the code gets corrupted due to long regular expressions and lack of 648 // space on trampolines, an internal exception flag is set. If this case 649 // is detected, we will jump into exit sequence right away. 650 __ bind_to(&entry_label_, internal_failure_label_.pos()); 651 } else { 652 // Finalize code - write the entry point code now we know how many 653 // registers we need. 654 655 // Entry code: 656 __ bind(&entry_label_); 657 658 // Tell the system that we have a stack frame. Because the type is MANUAL, 659 // no is generated. 660 FrameScope scope(masm_, StackFrame::MANUAL); 661 662 // Actually emit code to start a new stack frame. 663 // Push arguments 664 // Save callee-save registers. 665 // Start new stack frame. 666 // Store link register in existing stack-cell. 667 // Order here should correspond to order of offset constants in header file. 668 // TODO(plind): we save s0..s7, but ONLY use s3 here - use the regs 669 // or dont save. 670 RegList registers_to_retain = s0.bit() | s1.bit() | s2.bit() | 671 s3.bit() | s4.bit() | s5.bit() | s6.bit() | s7.bit() | fp.bit(); 672 RegList argument_registers = a0.bit() | a1.bit() | a2.bit() | a3.bit(); 673 674 argument_registers |= a4.bit() | a5.bit() | a6.bit() | a7.bit(); 675 676 __ MultiPush(argument_registers | registers_to_retain | ra.bit()); 677 // Set frame pointer in space for it if this is not a direct call 678 // from generated code. 679 // TODO(plind): this 8 is the # of argument regs, should have definition. 680 __ Daddu(frame_pointer(), sp, Operand(8 * kPointerSize)); 681 __ mov(a0, zero_reg); 682 __ push(a0); // Make room for success counter and initialize it to 0. 683 __ push(a0); // Make room for "string start - 1" constant. 684 685 // Check if we have space on the stack for registers. 686 Label stack_limit_hit; 687 Label stack_ok; 688 689 ExternalReference stack_limit = 690 ExternalReference::address_of_stack_limit(masm_->isolate()); 691 __ li(a0, Operand(stack_limit)); 692 __ ld(a0, MemOperand(a0)); 693 __ Dsubu(a0, sp, a0); 694 // Handle it if the stack pointer is already below the stack limit. 695 __ Branch(&stack_limit_hit, le, a0, Operand(zero_reg)); 696 // Check if there is room for the variable number of registers above 697 // the stack limit. 698 __ Branch(&stack_ok, hs, a0, Operand(num_registers_ * kPointerSize)); 699 // Exit with OutOfMemory exception. There is not enough space on the stack 700 // for our working registers. 701 __ li(v0, Operand(EXCEPTION)); 702 __ jmp(&return_v0); 703 704 __ bind(&stack_limit_hit); 705 CallCheckStackGuardState(a0); 706 // If returned value is non-zero, we exit with the returned value as result. 707 __ Branch(&return_v0, ne, v0, Operand(zero_reg)); 708 709 __ bind(&stack_ok); 710 // Allocate space on stack for registers. 711 __ Dsubu(sp, sp, Operand(num_registers_ * kPointerSize)); 712 // Load string end. 713 __ ld(end_of_input_address(), MemOperand(frame_pointer(), kInputEnd)); 714 // Load input start. 715 __ ld(a0, MemOperand(frame_pointer(), kInputStart)); 716 // Find negative length (offset of start relative to end). 717 __ Dsubu(current_input_offset(), a0, end_of_input_address()); 718 // Set a0 to address of char before start of the input string 719 // (effectively string position -1). 720 __ ld(a1, MemOperand(frame_pointer(), kStartIndex)); 721 __ Dsubu(a0, current_input_offset(), Operand(char_size())); 722 __ dsll(t1, a1, (mode_ == UC16) ? 1 : 0); 723 __ Dsubu(a0, a0, t1); 724 // Store this value in a local variable, for use when clearing 725 // position registers. 726 __ sd(a0, MemOperand(frame_pointer(), kStringStartMinusOne)); 727 728 // Initialize code pointer register 729 __ li(code_pointer(), Operand(masm_->CodeObject()), CONSTANT_SIZE); 730 731 Label load_char_start_regexp, start_regexp; 732 // Load newline if index is at start, previous character otherwise. 733 __ Branch(&load_char_start_regexp, ne, a1, Operand(zero_reg)); 734 __ li(current_character(), Operand('\n')); 735 __ jmp(&start_regexp); 736 737 // Global regexp restarts matching here. 738 __ bind(&load_char_start_regexp); 739 // Load previous char as initial value of current character register. 740 LoadCurrentCharacterUnchecked(-1, 1); 741 __ bind(&start_regexp); 742 743 // Initialize on-stack registers. 744 if (num_saved_registers_ > 0) { // Always is, if generated from a regexp. 745 // Fill saved registers with initial value = start offset - 1. 746 if (num_saved_registers_ > 8) { 747 // Address of register 0. 748 __ Daddu(a1, frame_pointer(), Operand(kRegisterZero)); 749 __ li(a2, Operand(num_saved_registers_)); 750 Label init_loop; 751 __ bind(&init_loop); 752 __ sd(a0, MemOperand(a1)); 753 __ Daddu(a1, a1, Operand(-kPointerSize)); 754 __ Dsubu(a2, a2, Operand(1)); 755 __ Branch(&init_loop, ne, a2, Operand(zero_reg)); 756 } else { 757 for (int i = 0; i < num_saved_registers_; i++) { 758 __ sd(a0, register_location(i)); 759 } 760 } 761 } 762 763 // Initialize backtrack stack pointer. 764 __ ld(backtrack_stackpointer(), MemOperand(frame_pointer(), kStackHighEnd)); 765 766 __ jmp(&start_label_); 767 768 769 // Exit code: 770 if (success_label_.is_linked()) { 771 // Save captures when successful. 772 __ bind(&success_label_); 773 if (num_saved_registers_ > 0) { 774 // Copy captures to output. 775 __ ld(a1, MemOperand(frame_pointer(), kInputStart)); 776 __ ld(a0, MemOperand(frame_pointer(), kRegisterOutput)); 777 __ ld(a2, MemOperand(frame_pointer(), kStartIndex)); 778 __ Dsubu(a1, end_of_input_address(), a1); 779 // a1 is length of input in bytes. 780 if (mode_ == UC16) { 781 __ dsrl(a1, a1, 1); 782 } 783 // a1 is length of input in characters. 784 __ Daddu(a1, a1, Operand(a2)); 785 // a1 is length of string in characters. 786 787 DCHECK_EQ(0, num_saved_registers_ % 2); 788 // Always an even number of capture registers. This allows us to 789 // unroll the loop once to add an operation between a load of a register 790 // and the following use of that register. 791 for (int i = 0; i < num_saved_registers_; i += 2) { 792 __ ld(a2, register_location(i)); 793 __ ld(a3, register_location(i + 1)); 794 if (i == 0 && global_with_zero_length_check()) { 795 // Keep capture start in a4 for the zero-length check later. 796 __ mov(t3, a2); 797 } 798 if (mode_ == UC16) { 799 __ dsra(a2, a2, 1); 800 __ Daddu(a2, a2, a1); 801 __ dsra(a3, a3, 1); 802 __ Daddu(a3, a3, a1); 803 } else { 804 __ Daddu(a2, a1, Operand(a2)); 805 __ Daddu(a3, a1, Operand(a3)); 806 } 807 // V8 expects the output to be an int32_t array. 808 __ sw(a2, MemOperand(a0)); 809 __ Daddu(a0, a0, kIntSize); 810 __ sw(a3, MemOperand(a0)); 811 __ Daddu(a0, a0, kIntSize); 812 } 813 } 814 815 if (global()) { 816 // Restart matching if the regular expression is flagged as global. 817 __ ld(a0, MemOperand(frame_pointer(), kSuccessfulCaptures)); 818 __ ld(a1, MemOperand(frame_pointer(), kNumOutputRegisters)); 819 __ ld(a2, MemOperand(frame_pointer(), kRegisterOutput)); 820 // Increment success counter. 821 __ Daddu(a0, a0, 1); 822 __ sd(a0, MemOperand(frame_pointer(), kSuccessfulCaptures)); 823 // Capture results have been stored, so the number of remaining global 824 // output registers is reduced by the number of stored captures. 825 __ Dsubu(a1, a1, num_saved_registers_); 826 // Check whether we have enough room for another set of capture results. 827 __ mov(v0, a0); 828 __ Branch(&return_v0, lt, a1, Operand(num_saved_registers_)); 829 830 __ sd(a1, MemOperand(frame_pointer(), kNumOutputRegisters)); 831 // Advance the location for output. 832 __ Daddu(a2, a2, num_saved_registers_ * kIntSize); 833 __ sd(a2, MemOperand(frame_pointer(), kRegisterOutput)); 834 835 // Prepare a0 to initialize registers with its value in the next run. 836 __ ld(a0, MemOperand(frame_pointer(), kStringStartMinusOne)); 837 838 if (global_with_zero_length_check()) { 839 // Special case for zero-length matches. 840 // t3: capture start index 841 // Not a zero-length match, restart. 842 __ Branch( 843 &load_char_start_regexp, ne, current_input_offset(), Operand(t3)); 844 // Offset from the end is zero if we already reached the end. 845 __ Branch(&exit_label_, eq, current_input_offset(), 846 Operand(zero_reg)); 847 // Advance current position after a zero-length match. 848 Label advance; 849 __ bind(&advance); 850 __ Daddu(current_input_offset(), 851 current_input_offset(), 852 Operand((mode_ == UC16) ? 2 : 1)); 853 if (global_unicode()) CheckNotInSurrogatePair(0, &advance); 854 } 855 856 __ Branch(&load_char_start_regexp); 857 } else { 858 __ li(v0, Operand(SUCCESS)); 859 } 860 } 861 // Exit and return v0. 862 __ bind(&exit_label_); 863 if (global()) { 864 __ ld(v0, MemOperand(frame_pointer(), kSuccessfulCaptures)); 865 } 866 867 __ bind(&return_v0); 868 // Skip sp past regexp registers and local variables.. 869 __ mov(sp, frame_pointer()); 870 // Restore registers s0..s7 and return (restoring ra to pc). 871 __ MultiPop(registers_to_retain | ra.bit()); 872 __ Ret(); 873 874 // Backtrack code (branch target for conditional backtracks). 875 if (backtrack_label_.is_linked()) { 876 __ bind(&backtrack_label_); 877 Backtrack(); 878 } 879 880 Label exit_with_exception; 881 882 // Preempt-code. 883 if (check_preempt_label_.is_linked()) { 884 SafeCallTarget(&check_preempt_label_); 885 // Put regexp engine registers on stack. 886 RegList regexp_registers_to_retain = current_input_offset().bit() | 887 current_character().bit() | backtrack_stackpointer().bit(); 888 __ MultiPush(regexp_registers_to_retain); 889 CallCheckStackGuardState(a0); 890 __ MultiPop(regexp_registers_to_retain); 891 // If returning non-zero, we should end execution with the given 892 // result as return value. 893 __ Branch(&return_v0, ne, v0, Operand(zero_reg)); 894 895 // String might have moved: Reload end of string from frame. 896 __ ld(end_of_input_address(), MemOperand(frame_pointer(), kInputEnd)); 897 __ li(code_pointer(), Operand(masm_->CodeObject()), CONSTANT_SIZE); 898 SafeReturn(); 899 } 900 901 // Backtrack stack overflow code. 902 if (stack_overflow_label_.is_linked()) { 903 SafeCallTarget(&stack_overflow_label_); 904 // Reached if the backtrack-stack limit has been hit. 905 // Put regexp engine registers on stack first. 906 RegList regexp_registers = current_input_offset().bit() | 907 current_character().bit(); 908 __ MultiPush(regexp_registers); 909 Label grow_failed; 910 // Call GrowStack(backtrack_stackpointer(), &stack_base) 911 static const int num_arguments = 3; 912 __ PrepareCallCFunction(num_arguments, a0); 913 __ mov(a0, backtrack_stackpointer()); 914 __ Daddu(a1, frame_pointer(), Operand(kStackHighEnd)); 915 __ li(a2, Operand(ExternalReference::isolate_address(masm_->isolate()))); 916 ExternalReference grow_stack = 917 ExternalReference::re_grow_stack(masm_->isolate()); 918 __ CallCFunction(grow_stack, num_arguments); 919 // Restore regexp registers. 920 __ MultiPop(regexp_registers); 921 // If return NULL, we have failed to grow the stack, and 922 // must exit with a stack-overflow exception. 923 __ Branch(&exit_with_exception, eq, v0, Operand(zero_reg)); 924 // Otherwise use return value as new stack pointer. 925 __ mov(backtrack_stackpointer(), v0); 926 // Restore saved registers and continue. 927 __ li(code_pointer(), Operand(masm_->CodeObject()), CONSTANT_SIZE); 928 __ ld(end_of_input_address(), MemOperand(frame_pointer(), kInputEnd)); 929 SafeReturn(); 930 } 931 932 if (exit_with_exception.is_linked()) { 933 // If any of the code above needed to exit with an exception. 934 __ bind(&exit_with_exception); 935 // Exit with Result EXCEPTION(-1) to signal thrown exception. 936 __ li(v0, Operand(EXCEPTION)); 937 __ jmp(&return_v0); 938 } 939 } 940 941 CodeDesc code_desc; 942 masm_->GetCode(&code_desc); 943 Handle<Code> code = isolate()->factory()->NewCode( 944 code_desc, Code::ComputeFlags(Code::REGEXP), masm_->CodeObject()); 945 LOG(masm_->isolate(), 946 RegExpCodeCreateEvent(AbstractCode::cast(*code), *source)); 947 return Handle<HeapObject>::cast(code); 948} 949 950 951void RegExpMacroAssemblerMIPS::GoTo(Label* to) { 952 if (to == NULL) { 953 Backtrack(); 954 return; 955 } 956 __ jmp(to); 957 return; 958} 959 960 961void RegExpMacroAssemblerMIPS::IfRegisterGE(int reg, 962 int comparand, 963 Label* if_ge) { 964 __ ld(a0, register_location(reg)); 965 BranchOrBacktrack(if_ge, ge, a0, Operand(comparand)); 966} 967 968 969void RegExpMacroAssemblerMIPS::IfRegisterLT(int reg, 970 int comparand, 971 Label* if_lt) { 972 __ ld(a0, register_location(reg)); 973 BranchOrBacktrack(if_lt, lt, a0, Operand(comparand)); 974} 975 976 977void RegExpMacroAssemblerMIPS::IfRegisterEqPos(int reg, 978 Label* if_eq) { 979 __ ld(a0, register_location(reg)); 980 BranchOrBacktrack(if_eq, eq, a0, Operand(current_input_offset())); 981} 982 983 984RegExpMacroAssembler::IrregexpImplementation 985 RegExpMacroAssemblerMIPS::Implementation() { 986 return kMIPSImplementation; 987} 988 989 990void RegExpMacroAssemblerMIPS::LoadCurrentCharacter(int cp_offset, 991 Label* on_end_of_input, 992 bool check_bounds, 993 int characters) { 994 DCHECK(cp_offset < (1<<30)); // Be sane! (And ensure negation works). 995 if (check_bounds) { 996 if (cp_offset >= 0) { 997 CheckPosition(cp_offset + characters - 1, on_end_of_input); 998 } else { 999 CheckPosition(cp_offset, on_end_of_input); 1000 } 1001 } 1002 LoadCurrentCharacterUnchecked(cp_offset, characters); 1003} 1004 1005 1006void RegExpMacroAssemblerMIPS::PopCurrentPosition() { 1007 Pop(current_input_offset()); 1008} 1009 1010 1011void RegExpMacroAssemblerMIPS::PopRegister(int register_index) { 1012 Pop(a0); 1013 __ sd(a0, register_location(register_index)); 1014} 1015 1016 1017void RegExpMacroAssemblerMIPS::PushBacktrack(Label* label) { 1018 if (label->is_bound()) { 1019 int target = label->pos(); 1020 __ li(a0, Operand(target + Code::kHeaderSize - kHeapObjectTag)); 1021 } else { 1022 Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_); 1023 Label after_constant; 1024 __ Branch(&after_constant); 1025 int offset = masm_->pc_offset(); 1026 int cp_offset = offset + Code::kHeaderSize - kHeapObjectTag; 1027 __ emit(0); 1028 masm_->label_at_put(label, offset); 1029 __ bind(&after_constant); 1030 if (is_int16(cp_offset)) { 1031 __ lwu(a0, MemOperand(code_pointer(), cp_offset)); 1032 } else { 1033 __ Daddu(a0, code_pointer(), cp_offset); 1034 __ lwu(a0, MemOperand(a0, 0)); 1035 } 1036 } 1037 Push(a0); 1038 CheckStackLimit(); 1039} 1040 1041 1042void RegExpMacroAssemblerMIPS::PushCurrentPosition() { 1043 Push(current_input_offset()); 1044} 1045 1046 1047void RegExpMacroAssemblerMIPS::PushRegister(int register_index, 1048 StackCheckFlag check_stack_limit) { 1049 __ ld(a0, register_location(register_index)); 1050 Push(a0); 1051 if (check_stack_limit) CheckStackLimit(); 1052} 1053 1054 1055void RegExpMacroAssemblerMIPS::ReadCurrentPositionFromRegister(int reg) { 1056 __ ld(current_input_offset(), register_location(reg)); 1057} 1058 1059 1060void RegExpMacroAssemblerMIPS::ReadStackPointerFromRegister(int reg) { 1061 __ ld(backtrack_stackpointer(), register_location(reg)); 1062 __ ld(a0, MemOperand(frame_pointer(), kStackHighEnd)); 1063 __ Daddu(backtrack_stackpointer(), backtrack_stackpointer(), Operand(a0)); 1064} 1065 1066 1067void RegExpMacroAssemblerMIPS::SetCurrentPositionFromEnd(int by) { 1068 Label after_position; 1069 __ Branch(&after_position, 1070 ge, 1071 current_input_offset(), 1072 Operand(-by * char_size())); 1073 __ li(current_input_offset(), -by * char_size()); 1074 // On RegExp code entry (where this operation is used), the character before 1075 // the current position is expected to be already loaded. 1076 // We have advanced the position, so it's safe to read backwards. 1077 LoadCurrentCharacterUnchecked(-1, 1); 1078 __ bind(&after_position); 1079} 1080 1081 1082void RegExpMacroAssemblerMIPS::SetRegister(int register_index, int to) { 1083 DCHECK(register_index >= num_saved_registers_); // Reserved for positions! 1084 __ li(a0, Operand(to)); 1085 __ sd(a0, register_location(register_index)); 1086} 1087 1088 1089bool RegExpMacroAssemblerMIPS::Succeed() { 1090 __ jmp(&success_label_); 1091 return global(); 1092} 1093 1094 1095void RegExpMacroAssemblerMIPS::WriteCurrentPositionToRegister(int reg, 1096 int cp_offset) { 1097 if (cp_offset == 0) { 1098 __ sd(current_input_offset(), register_location(reg)); 1099 } else { 1100 __ Daddu(a0, current_input_offset(), Operand(cp_offset * char_size())); 1101 __ sd(a0, register_location(reg)); 1102 } 1103} 1104 1105 1106void RegExpMacroAssemblerMIPS::ClearRegisters(int reg_from, int reg_to) { 1107 DCHECK(reg_from <= reg_to); 1108 __ ld(a0, MemOperand(frame_pointer(), kStringStartMinusOne)); 1109 for (int reg = reg_from; reg <= reg_to; reg++) { 1110 __ sd(a0, register_location(reg)); 1111 } 1112} 1113 1114 1115void RegExpMacroAssemblerMIPS::WriteStackPointerToRegister(int reg) { 1116 __ ld(a1, MemOperand(frame_pointer(), kStackHighEnd)); 1117 __ Dsubu(a0, backtrack_stackpointer(), a1); 1118 __ sd(a0, register_location(reg)); 1119} 1120 1121 1122bool RegExpMacroAssemblerMIPS::CanReadUnaligned() { 1123 return false; 1124} 1125 1126 1127// Private methods: 1128 1129void RegExpMacroAssemblerMIPS::CallCheckStackGuardState(Register scratch) { 1130 int stack_alignment = base::OS::ActivationFrameAlignment(); 1131 1132 // Align the stack pointer and save the original sp value on the stack. 1133 __ mov(scratch, sp); 1134 __ Dsubu(sp, sp, Operand(kPointerSize)); 1135 DCHECK(base::bits::IsPowerOfTwo32(stack_alignment)); 1136 __ And(sp, sp, Operand(-stack_alignment)); 1137 __ sd(scratch, MemOperand(sp)); 1138 1139 __ mov(a2, frame_pointer()); 1140 // Code* of self. 1141 __ li(a1, Operand(masm_->CodeObject()), CONSTANT_SIZE); 1142 1143 // We need to make room for the return address on the stack. 1144 DCHECK(IsAligned(stack_alignment, kPointerSize)); 1145 __ Dsubu(sp, sp, Operand(stack_alignment)); 1146 1147 // Stack pointer now points to cell where return address is to be written. 1148 // Arguments are in registers, meaning we teat the return address as 1149 // argument 5. Since DirectCEntryStub will handleallocating space for the C 1150 // argument slots, we don't need to care about that here. This is how the 1151 // stack will look (sp meaning the value of sp at this moment): 1152 // [sp + 3] - empty slot if needed for alignment. 1153 // [sp + 2] - saved sp. 1154 // [sp + 1] - second word reserved for return value. 1155 // [sp + 0] - first word reserved for return value. 1156 1157 // a0 will point to the return address, placed by DirectCEntry. 1158 __ mov(a0, sp); 1159 1160 ExternalReference stack_guard_check = 1161 ExternalReference::re_check_stack_guard_state(masm_->isolate()); 1162 __ li(t9, Operand(stack_guard_check)); 1163 DirectCEntryStub stub(isolate()); 1164 stub.GenerateCall(masm_, t9); 1165 1166 // DirectCEntryStub allocated space for the C argument slots so we have to 1167 // drop them with the return address from the stack with loading saved sp. 1168 // At this point stack must look: 1169 // [sp + 7] - empty slot if needed for alignment. 1170 // [sp + 6] - saved sp. 1171 // [sp + 5] - second word reserved for return value. 1172 // [sp + 4] - first word reserved for return value. 1173 // [sp + 3] - C argument slot. 1174 // [sp + 2] - C argument slot. 1175 // [sp + 1] - C argument slot. 1176 // [sp + 0] - C argument slot. 1177 __ ld(sp, MemOperand(sp, stack_alignment + kCArgsSlotsSize)); 1178 1179 __ li(code_pointer(), Operand(masm_->CodeObject())); 1180} 1181 1182 1183// Helper function for reading a value out of a stack frame. 1184template <typename T> 1185static T& frame_entry(Address re_frame, int frame_offset) { 1186 return reinterpret_cast<T&>(Memory::int32_at(re_frame + frame_offset)); 1187} 1188 1189 1190template <typename T> 1191static T* frame_entry_address(Address re_frame, int frame_offset) { 1192 return reinterpret_cast<T*>(re_frame + frame_offset); 1193} 1194 1195 1196int64_t RegExpMacroAssemblerMIPS::CheckStackGuardState(Address* return_address, 1197 Code* re_code, 1198 Address re_frame) { 1199 return NativeRegExpMacroAssembler::CheckStackGuardState( 1200 frame_entry<Isolate*>(re_frame, kIsolate), 1201 static_cast<int>(frame_entry<int64_t>(re_frame, kStartIndex)), 1202 frame_entry<int64_t>(re_frame, kDirectCall) == 1, return_address, re_code, 1203 frame_entry_address<String*>(re_frame, kInputString), 1204 frame_entry_address<const byte*>(re_frame, kInputStart), 1205 frame_entry_address<const byte*>(re_frame, kInputEnd)); 1206} 1207 1208 1209MemOperand RegExpMacroAssemblerMIPS::register_location(int register_index) { 1210 DCHECK(register_index < (1<<30)); 1211 if (num_registers_ <= register_index) { 1212 num_registers_ = register_index + 1; 1213 } 1214 return MemOperand(frame_pointer(), 1215 kRegisterZero - register_index * kPointerSize); 1216} 1217 1218 1219void RegExpMacroAssemblerMIPS::CheckPosition(int cp_offset, 1220 Label* on_outside_input) { 1221 if (cp_offset >= 0) { 1222 BranchOrBacktrack(on_outside_input, ge, current_input_offset(), 1223 Operand(-cp_offset * char_size())); 1224 } else { 1225 __ ld(a1, MemOperand(frame_pointer(), kStringStartMinusOne)); 1226 __ Daddu(a0, current_input_offset(), Operand(cp_offset * char_size())); 1227 BranchOrBacktrack(on_outside_input, le, a0, Operand(a1)); 1228 } 1229} 1230 1231 1232void RegExpMacroAssemblerMIPS::BranchOrBacktrack(Label* to, 1233 Condition condition, 1234 Register rs, 1235 const Operand& rt) { 1236 if (condition == al) { // Unconditional. 1237 if (to == NULL) { 1238 Backtrack(); 1239 return; 1240 } 1241 __ jmp(to); 1242 return; 1243 } 1244 if (to == NULL) { 1245 __ Branch(&backtrack_label_, condition, rs, rt); 1246 return; 1247 } 1248 __ Branch(to, condition, rs, rt); 1249} 1250 1251 1252void RegExpMacroAssemblerMIPS::SafeCall(Label* to, 1253 Condition cond, 1254 Register rs, 1255 const Operand& rt) { 1256 __ BranchAndLink(to, cond, rs, rt); 1257} 1258 1259 1260void RegExpMacroAssemblerMIPS::SafeReturn() { 1261 __ pop(ra); 1262 __ Daddu(t1, ra, Operand(masm_->CodeObject())); 1263 __ Jump(t1); 1264} 1265 1266 1267void RegExpMacroAssemblerMIPS::SafeCallTarget(Label* name) { 1268 __ bind(name); 1269 __ Dsubu(ra, ra, Operand(masm_->CodeObject())); 1270 __ push(ra); 1271} 1272 1273 1274void RegExpMacroAssemblerMIPS::Push(Register source) { 1275 DCHECK(!source.is(backtrack_stackpointer())); 1276 __ Daddu(backtrack_stackpointer(), 1277 backtrack_stackpointer(), 1278 Operand(-kIntSize)); 1279 __ sw(source, MemOperand(backtrack_stackpointer())); 1280} 1281 1282 1283void RegExpMacroAssemblerMIPS::Pop(Register target) { 1284 DCHECK(!target.is(backtrack_stackpointer())); 1285 __ lw(target, MemOperand(backtrack_stackpointer())); 1286 __ Daddu(backtrack_stackpointer(), backtrack_stackpointer(), kIntSize); 1287} 1288 1289 1290void RegExpMacroAssemblerMIPS::CheckPreemption() { 1291 // Check for preemption. 1292 ExternalReference stack_limit = 1293 ExternalReference::address_of_stack_limit(masm_->isolate()); 1294 __ li(a0, Operand(stack_limit)); 1295 __ ld(a0, MemOperand(a0)); 1296 SafeCall(&check_preempt_label_, ls, sp, Operand(a0)); 1297} 1298 1299 1300void RegExpMacroAssemblerMIPS::CheckStackLimit() { 1301 ExternalReference stack_limit = 1302 ExternalReference::address_of_regexp_stack_limit(masm_->isolate()); 1303 1304 __ li(a0, Operand(stack_limit)); 1305 __ ld(a0, MemOperand(a0)); 1306 SafeCall(&stack_overflow_label_, ls, backtrack_stackpointer(), Operand(a0)); 1307} 1308 1309 1310void RegExpMacroAssemblerMIPS::LoadCurrentCharacterUnchecked(int cp_offset, 1311 int characters) { 1312 Register offset = current_input_offset(); 1313 if (cp_offset != 0) { 1314 // t3 is not being used to store the capture start index at this point. 1315 __ Daddu(t3, current_input_offset(), Operand(cp_offset * char_size())); 1316 offset = t3; 1317 } 1318 // We assume that we cannot do unaligned loads on MIPS, so this function 1319 // must only be used to load a single character at a time. 1320 DCHECK(characters == 1); 1321 __ Daddu(t1, end_of_input_address(), Operand(offset)); 1322 if (mode_ == LATIN1) { 1323 __ lbu(current_character(), MemOperand(t1, 0)); 1324 } else { 1325 DCHECK(mode_ == UC16); 1326 __ lhu(current_character(), MemOperand(t1, 0)); 1327 } 1328} 1329 1330#undef __ 1331 1332#endif // V8_INTERPRETED_REGEXP 1333 1334} // namespace internal 1335} // namespace v8 1336 1337#endif // V8_TARGET_ARCH_MIPS64 1338