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 16 namespace v8 { 17 namespace 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 132 RegExpMacroAssemblerMIPS::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 158 RegExpMacroAssemblerMIPS::~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 172 int RegExpMacroAssemblerMIPS::stack_limit_slack() { 173 return RegExpStack::kStackLimitSlack; 174 } 175 176 177 void 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 185 void 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 196 void 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 205 void RegExpMacroAssemblerMIPS::Bind(Label* label) { 206 __ bind(label); 207 } 208 209 210 void RegExpMacroAssemblerMIPS::CheckCharacter(uint32_t c, Label* on_equal) { 211 BranchOrBacktrack(on_equal, eq, current_character(), Operand(c)); 212 } 213 214 215 void RegExpMacroAssemblerMIPS::CheckCharacterGT(uc16 limit, Label* on_greater) { 216 BranchOrBacktrack(on_greater, gt, current_character(), Operand(limit)); 217 } 218 219 220 void 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 227 void 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 236 void RegExpMacroAssemblerMIPS::CheckCharacterLT(uc16 limit, Label* on_less) { 237 BranchOrBacktrack(on_less, lt, current_character(), Operand(limit)); 238 } 239 240 241 void 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 253 void RegExpMacroAssemblerMIPS::CheckNotBackReferenceIgnoreCase( 254 int start_reg, bool read_backward, 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. 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 __ li(a3, Operand(ExternalReference::isolate_address(masm_->isolate()))); 364 365 { 366 AllowExternalCallThatCantCauseGC scope(masm_); 367 ExternalReference function = 368 ExternalReference::re_case_insensitive_compare_uc16(masm_->isolate()); 369 __ CallCFunction(function, argument_count); 370 } 371 372 // Restore regexp engine registers. 373 __ MultiPop(regexp_registers_to_retain); 374 __ li(code_pointer(), Operand(masm_->CodeObject()), CONSTANT_SIZE); 375 __ ld(end_of_input_address(), MemOperand(frame_pointer(), kInputEnd)); 376 377 // Check if function returned non-zero for success or zero for failure. 378 BranchOrBacktrack(on_no_match, eq, v0, Operand(zero_reg)); 379 // On success, increment position by length of capture. 380 if (read_backward) { 381 __ Dsubu(current_input_offset(), current_input_offset(), Operand(s3)); 382 } else { 383 __ Daddu(current_input_offset(), current_input_offset(), Operand(s3)); 384 } 385 } 386 387 __ bind(&fallthrough); 388 } 389 390 391 void RegExpMacroAssemblerMIPS::CheckNotBackReference(int start_reg, 392 bool read_backward, 393 Label* on_no_match) { 394 Label fallthrough; 395 Label success; 396 397 // Find length of back-referenced capture. 398 __ ld(a0, register_location(start_reg)); 399 __ ld(a1, register_location(start_reg + 1)); 400 __ Dsubu(a1, a1, a0); // Length to check. 401 402 // At this point, the capture registers are either both set or both cleared. 403 // If the capture length is zero, then the capture is either empty or cleared. 404 // Fall through in both cases. 405 __ Branch(&fallthrough, eq, a1, Operand(zero_reg)); 406 407 if (read_backward) { 408 __ ld(t1, MemOperand(frame_pointer(), kStringStartMinusOne)); 409 __ Daddu(t1, t1, a1); 410 BranchOrBacktrack(on_no_match, le, current_input_offset(), Operand(t1)); 411 } else { 412 __ Daddu(t1, a1, current_input_offset()); 413 // Check that there are enough characters left in the input. 414 BranchOrBacktrack(on_no_match, gt, t1, Operand(zero_reg)); 415 } 416 417 // Compute pointers to match string and capture string. 418 __ Daddu(a0, a0, Operand(end_of_input_address())); 419 __ Daddu(a2, end_of_input_address(), Operand(current_input_offset())); 420 if (read_backward) { 421 __ Dsubu(a2, a2, Operand(a1)); 422 } 423 __ Daddu(a1, a1, Operand(a0)); 424 425 Label loop; 426 __ bind(&loop); 427 if (mode_ == LATIN1) { 428 __ lbu(a3, MemOperand(a0, 0)); 429 __ daddiu(a0, a0, char_size()); 430 __ lbu(a4, MemOperand(a2, 0)); 431 __ daddiu(a2, a2, char_size()); 432 } else { 433 DCHECK(mode_ == UC16); 434 __ lhu(a3, MemOperand(a0, 0)); 435 __ daddiu(a0, a0, char_size()); 436 __ lhu(a4, MemOperand(a2, 0)); 437 __ daddiu(a2, a2, char_size()); 438 } 439 BranchOrBacktrack(on_no_match, ne, a3, Operand(a4)); 440 __ Branch(&loop, lt, a0, Operand(a1)); 441 442 // Move current character position to position after match. 443 __ Dsubu(current_input_offset(), a2, end_of_input_address()); 444 if (read_backward) { 445 __ ld(t1, register_location(start_reg)); // Index of start of capture. 446 __ ld(a2, register_location(start_reg + 1)); // Index of end of capture. 447 __ Daddu(current_input_offset(), current_input_offset(), Operand(t1)); 448 __ Dsubu(current_input_offset(), current_input_offset(), Operand(a2)); 449 } 450 __ bind(&fallthrough); 451 } 452 453 454 void RegExpMacroAssemblerMIPS::CheckNotCharacter(uint32_t c, 455 Label* on_not_equal) { 456 BranchOrBacktrack(on_not_equal, ne, current_character(), Operand(c)); 457 } 458 459 460 void RegExpMacroAssemblerMIPS::CheckCharacterAfterAnd(uint32_t c, 461 uint32_t mask, 462 Label* on_equal) { 463 __ And(a0, current_character(), Operand(mask)); 464 Operand rhs = (c == 0) ? Operand(zero_reg) : Operand(c); 465 BranchOrBacktrack(on_equal, eq, a0, rhs); 466 } 467 468 469 void RegExpMacroAssemblerMIPS::CheckNotCharacterAfterAnd(uint32_t c, 470 uint32_t mask, 471 Label* on_not_equal) { 472 __ And(a0, current_character(), Operand(mask)); 473 Operand rhs = (c == 0) ? Operand(zero_reg) : Operand(c); 474 BranchOrBacktrack(on_not_equal, ne, a0, rhs); 475 } 476 477 478 void RegExpMacroAssemblerMIPS::CheckNotCharacterAfterMinusAnd( 479 uc16 c, 480 uc16 minus, 481 uc16 mask, 482 Label* on_not_equal) { 483 DCHECK(minus < String::kMaxUtf16CodeUnit); 484 __ Dsubu(a0, current_character(), Operand(minus)); 485 __ And(a0, a0, Operand(mask)); 486 BranchOrBacktrack(on_not_equal, ne, a0, Operand(c)); 487 } 488 489 490 void RegExpMacroAssemblerMIPS::CheckCharacterInRange( 491 uc16 from, 492 uc16 to, 493 Label* on_in_range) { 494 __ Dsubu(a0, current_character(), Operand(from)); 495 // Unsigned lower-or-same condition. 496 BranchOrBacktrack(on_in_range, ls, a0, Operand(to - from)); 497 } 498 499 500 void RegExpMacroAssemblerMIPS::CheckCharacterNotInRange( 501 uc16 from, 502 uc16 to, 503 Label* on_not_in_range) { 504 __ Dsubu(a0, current_character(), Operand(from)); 505 // Unsigned higher condition. 506 BranchOrBacktrack(on_not_in_range, hi, a0, Operand(to - from)); 507 } 508 509 510 void RegExpMacroAssemblerMIPS::CheckBitInTable( 511 Handle<ByteArray> table, 512 Label* on_bit_set) { 513 __ li(a0, Operand(table)); 514 if (mode_ != LATIN1 || kTableMask != String::kMaxOneByteCharCode) { 515 __ And(a1, current_character(), Operand(kTableSize - 1)); 516 __ Daddu(a0, a0, a1); 517 } else { 518 __ Daddu(a0, a0, current_character()); 519 } 520 521 __ lbu(a0, FieldMemOperand(a0, ByteArray::kHeaderSize)); 522 BranchOrBacktrack(on_bit_set, ne, a0, Operand(zero_reg)); 523 } 524 525 526 bool RegExpMacroAssemblerMIPS::CheckSpecialCharacterClass(uc16 type, 527 Label* on_no_match) { 528 // Range checks (c in min..max) are generally implemented by an unsigned 529 // (c - min) <= (max - min) check. 530 switch (type) { 531 case 's': 532 // Match space-characters. 533 if (mode_ == LATIN1) { 534 // One byte space characters are '\t'..'\r', ' ' and \u00a0. 535 Label success; 536 __ Branch(&success, eq, current_character(), Operand(' ')); 537 // Check range 0x09..0x0d. 538 __ Dsubu(a0, current_character(), Operand('\t')); 539 __ Branch(&success, ls, a0, Operand('\r' - '\t')); 540 // \u00a0 (NBSP). 541 BranchOrBacktrack(on_no_match, ne, a0, Operand(0x00a0 - '\t')); 542 __ bind(&success); 543 return true; 544 } 545 return false; 546 case 'S': 547 // The emitted code for generic character classes is good enough. 548 return false; 549 case 'd': 550 // Match Latin1 digits ('0'..'9'). 551 __ Dsubu(a0, current_character(), Operand('0')); 552 BranchOrBacktrack(on_no_match, hi, a0, Operand('9' - '0')); 553 return true; 554 case 'D': 555 // Match non Latin1-digits. 556 __ Dsubu(a0, current_character(), Operand('0')); 557 BranchOrBacktrack(on_no_match, ls, a0, Operand('9' - '0')); 558 return true; 559 case '.': { 560 // Match non-newlines (not 0x0a('\n'), 0x0d('\r'), 0x2028 and 0x2029). 561 __ Xor(a0, current_character(), Operand(0x01)); 562 // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c. 563 __ Dsubu(a0, a0, Operand(0x0b)); 564 BranchOrBacktrack(on_no_match, ls, a0, Operand(0x0c - 0x0b)); 565 if (mode_ == UC16) { 566 // Compare original value to 0x2028 and 0x2029, using the already 567 // computed (current_char ^ 0x01 - 0x0b). I.e., check for 568 // 0x201d (0x2028 - 0x0b) or 0x201e. 569 __ Dsubu(a0, a0, Operand(0x2028 - 0x0b)); 570 BranchOrBacktrack(on_no_match, ls, a0, Operand(1)); 571 } 572 return true; 573 } 574 case 'n': { 575 // Match newlines (0x0a('\n'), 0x0d('\r'), 0x2028 and 0x2029). 576 __ Xor(a0, current_character(), Operand(0x01)); 577 // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c. 578 __ Dsubu(a0, a0, Operand(0x0b)); 579 if (mode_ == LATIN1) { 580 BranchOrBacktrack(on_no_match, hi, a0, Operand(0x0c - 0x0b)); 581 } else { 582 Label done; 583 BranchOrBacktrack(&done, ls, a0, Operand(0x0c - 0x0b)); 584 // Compare original value to 0x2028 and 0x2029, using the already 585 // computed (current_char ^ 0x01 - 0x0b). I.e., check for 586 // 0x201d (0x2028 - 0x0b) or 0x201e. 587 __ Dsubu(a0, a0, Operand(0x2028 - 0x0b)); 588 BranchOrBacktrack(on_no_match, hi, a0, Operand(1)); 589 __ bind(&done); 590 } 591 return true; 592 } 593 case 'w': { 594 if (mode_ != LATIN1) { 595 // Table is 256 entries, so all Latin1 characters can be tested. 596 BranchOrBacktrack(on_no_match, hi, current_character(), Operand('z')); 597 } 598 ExternalReference map = ExternalReference::re_word_character_map(); 599 __ li(a0, Operand(map)); 600 __ Daddu(a0, a0, current_character()); 601 __ lbu(a0, MemOperand(a0, 0)); 602 BranchOrBacktrack(on_no_match, eq, a0, Operand(zero_reg)); 603 return true; 604 } 605 case 'W': { 606 Label done; 607 if (mode_ != LATIN1) { 608 // Table is 256 entries, so all Latin1 characters can be tested. 609 __ Branch(&done, hi, current_character(), Operand('z')); 610 } 611 ExternalReference map = ExternalReference::re_word_character_map(); 612 __ li(a0, Operand(map)); 613 __ Daddu(a0, a0, current_character()); 614 __ lbu(a0, MemOperand(a0, 0)); 615 BranchOrBacktrack(on_no_match, ne, a0, Operand(zero_reg)); 616 if (mode_ != LATIN1) { 617 __ bind(&done); 618 } 619 return true; 620 } 621 case '*': 622 // Match any character. 623 return true; 624 // No custom implementation (yet): s(UC16), S(UC16). 625 default: 626 return false; 627 } 628 } 629 630 631 void RegExpMacroAssemblerMIPS::Fail() { 632 __ li(v0, Operand(FAILURE)); 633 __ jmp(&exit_label_); 634 } 635 636 637 Handle<HeapObject> RegExpMacroAssemblerMIPS::GetCode(Handle<String> source) { 638 Label return_v0; 639 if (masm_->has_exception()) { 640 // If the code gets corrupted due to long regular expressions and lack of 641 // space on trampolines, an internal exception flag is set. If this case 642 // is detected, we will jump into exit sequence right away. 643 __ bind_to(&entry_label_, internal_failure_label_.pos()); 644 } else { 645 // Finalize code - write the entry point code now we know how many 646 // registers we need. 647 648 // Entry code: 649 __ bind(&entry_label_); 650 651 // Tell the system that we have a stack frame. Because the type is MANUAL, 652 // no is generated. 653 FrameScope scope(masm_, StackFrame::MANUAL); 654 655 // Actually emit code to start a new stack frame. 656 // Push arguments 657 // Save callee-save registers. 658 // Start new stack frame. 659 // Store link register in existing stack-cell. 660 // Order here should correspond to order of offset constants in header file. 661 // TODO(plind): we save s0..s7, but ONLY use s3 here - use the regs 662 // or dont save. 663 RegList registers_to_retain = s0.bit() | s1.bit() | s2.bit() | 664 s3.bit() | s4.bit() | s5.bit() | s6.bit() | s7.bit() | fp.bit(); 665 RegList argument_registers = a0.bit() | a1.bit() | a2.bit() | a3.bit(); 666 667 if (kMipsAbi == kN64) { 668 // TODO(plind): Should probably alias a4-a7, for clarity. 669 argument_registers |= a4.bit() | a5.bit() | a6.bit() | a7.bit(); 670 } 671 672 __ MultiPush(argument_registers | registers_to_retain | ra.bit()); 673 // Set frame pointer in space for it if this is not a direct call 674 // from generated code. 675 // TODO(plind): this 8 is the # of argument regs, should have definition. 676 __ Daddu(frame_pointer(), sp, Operand(8 * kPointerSize)); 677 __ mov(a0, zero_reg); 678 __ push(a0); // Make room for success counter and initialize it to 0. 679 __ push(a0); // Make room for "string start - 1" constant. 680 681 // Check if we have space on the stack for registers. 682 Label stack_limit_hit; 683 Label stack_ok; 684 685 ExternalReference stack_limit = 686 ExternalReference::address_of_stack_limit(masm_->isolate()); 687 __ li(a0, Operand(stack_limit)); 688 __ ld(a0, MemOperand(a0)); 689 __ Dsubu(a0, sp, a0); 690 // Handle it if the stack pointer is already below the stack limit. 691 __ Branch(&stack_limit_hit, le, a0, Operand(zero_reg)); 692 // Check if there is room for the variable number of registers above 693 // the stack limit. 694 __ Branch(&stack_ok, hs, a0, Operand(num_registers_ * kPointerSize)); 695 // Exit with OutOfMemory exception. There is not enough space on the stack 696 // for our working registers. 697 __ li(v0, Operand(EXCEPTION)); 698 __ jmp(&return_v0); 699 700 __ bind(&stack_limit_hit); 701 CallCheckStackGuardState(a0); 702 // If returned value is non-zero, we exit with the returned value as result. 703 __ Branch(&return_v0, ne, v0, Operand(zero_reg)); 704 705 __ bind(&stack_ok); 706 // Allocate space on stack for registers. 707 __ Dsubu(sp, sp, Operand(num_registers_ * kPointerSize)); 708 // Load string end. 709 __ ld(end_of_input_address(), MemOperand(frame_pointer(), kInputEnd)); 710 // Load input start. 711 __ ld(a0, MemOperand(frame_pointer(), kInputStart)); 712 // Find negative length (offset of start relative to end). 713 __ Dsubu(current_input_offset(), a0, end_of_input_address()); 714 // Set a0 to address of char before start of the input string 715 // (effectively string position -1). 716 __ ld(a1, MemOperand(frame_pointer(), kStartIndex)); 717 __ Dsubu(a0, current_input_offset(), Operand(char_size())); 718 __ dsll(t1, a1, (mode_ == UC16) ? 1 : 0); 719 __ Dsubu(a0, a0, t1); 720 // Store this value in a local variable, for use when clearing 721 // position registers. 722 __ sd(a0, MemOperand(frame_pointer(), kStringStartMinusOne)); 723 724 // Initialize code pointer register 725 __ li(code_pointer(), Operand(masm_->CodeObject()), CONSTANT_SIZE); 726 727 Label load_char_start_regexp, start_regexp; 728 // Load newline if index is at start, previous character otherwise. 729 __ Branch(&load_char_start_regexp, ne, a1, Operand(zero_reg)); 730 __ li(current_character(), Operand('\n')); 731 __ jmp(&start_regexp); 732 733 // Global regexp restarts matching here. 734 __ bind(&load_char_start_regexp); 735 // Load previous char as initial value of current character register. 736 LoadCurrentCharacterUnchecked(-1, 1); 737 __ bind(&start_regexp); 738 739 // Initialize on-stack registers. 740 if (num_saved_registers_ > 0) { // Always is, if generated from a regexp. 741 // Fill saved registers with initial value = start offset - 1. 742 if (num_saved_registers_ > 8) { 743 // Address of register 0. 744 __ Daddu(a1, frame_pointer(), Operand(kRegisterZero)); 745 __ li(a2, Operand(num_saved_registers_)); 746 Label init_loop; 747 __ bind(&init_loop); 748 __ sd(a0, MemOperand(a1)); 749 __ Daddu(a1, a1, Operand(-kPointerSize)); 750 __ Dsubu(a2, a2, Operand(1)); 751 __ Branch(&init_loop, ne, a2, Operand(zero_reg)); 752 } else { 753 for (int i = 0; i < num_saved_registers_; i++) { 754 __ sd(a0, register_location(i)); 755 } 756 } 757 } 758 759 // Initialize backtrack stack pointer. 760 __ ld(backtrack_stackpointer(), MemOperand(frame_pointer(), kStackHighEnd)); 761 762 __ jmp(&start_label_); 763 764 765 // Exit code: 766 if (success_label_.is_linked()) { 767 // Save captures when successful. 768 __ bind(&success_label_); 769 if (num_saved_registers_ > 0) { 770 // Copy captures to output. 771 __ ld(a1, MemOperand(frame_pointer(), kInputStart)); 772 __ ld(a0, MemOperand(frame_pointer(), kRegisterOutput)); 773 __ ld(a2, MemOperand(frame_pointer(), kStartIndex)); 774 __ Dsubu(a1, end_of_input_address(), a1); 775 // a1 is length of input in bytes. 776 if (mode_ == UC16) { 777 __ dsrl(a1, a1, 1); 778 } 779 // a1 is length of input in characters. 780 __ Daddu(a1, a1, Operand(a2)); 781 // a1 is length of string in characters. 782 783 DCHECK_EQ(0, num_saved_registers_ % 2); 784 // Always an even number of capture registers. This allows us to 785 // unroll the loop once to add an operation between a load of a register 786 // and the following use of that register. 787 for (int i = 0; i < num_saved_registers_; i += 2) { 788 __ ld(a2, register_location(i)); 789 __ ld(a3, register_location(i + 1)); 790 if (i == 0 && global_with_zero_length_check()) { 791 // Keep capture start in a4 for the zero-length check later. 792 __ mov(t3, a2); 793 } 794 if (mode_ == UC16) { 795 __ dsra(a2, a2, 1); 796 __ Daddu(a2, a2, a1); 797 __ dsra(a3, a3, 1); 798 __ Daddu(a3, a3, a1); 799 } else { 800 __ Daddu(a2, a1, Operand(a2)); 801 __ Daddu(a3, a1, Operand(a3)); 802 } 803 // V8 expects the output to be an int32_t array. 804 __ sw(a2, MemOperand(a0)); 805 __ Daddu(a0, a0, kIntSize); 806 __ sw(a3, MemOperand(a0)); 807 __ Daddu(a0, a0, kIntSize); 808 } 809 } 810 811 if (global()) { 812 // Restart matching if the regular expression is flagged as global. 813 __ ld(a0, MemOperand(frame_pointer(), kSuccessfulCaptures)); 814 __ ld(a1, MemOperand(frame_pointer(), kNumOutputRegisters)); 815 __ ld(a2, MemOperand(frame_pointer(), kRegisterOutput)); 816 // Increment success counter. 817 __ Daddu(a0, a0, 1); 818 __ sd(a0, MemOperand(frame_pointer(), kSuccessfulCaptures)); 819 // Capture results have been stored, so the number of remaining global 820 // output registers is reduced by the number of stored captures. 821 __ Dsubu(a1, a1, num_saved_registers_); 822 // Check whether we have enough room for another set of capture results. 823 __ mov(v0, a0); 824 __ Branch(&return_v0, lt, a1, Operand(num_saved_registers_)); 825 826 __ sd(a1, MemOperand(frame_pointer(), kNumOutputRegisters)); 827 // Advance the location for output. 828 __ Daddu(a2, a2, num_saved_registers_ * kIntSize); 829 __ sd(a2, MemOperand(frame_pointer(), kRegisterOutput)); 830 831 // Prepare a0 to initialize registers with its value in the next run. 832 __ ld(a0, MemOperand(frame_pointer(), kStringStartMinusOne)); 833 834 if (global_with_zero_length_check()) { 835 // Special case for zero-length matches. 836 // t3: capture start index 837 // Not a zero-length match, restart. 838 __ Branch( 839 &load_char_start_regexp, ne, current_input_offset(), Operand(t3)); 840 // Offset from the end is zero if we already reached the end. 841 __ Branch(&exit_label_, eq, current_input_offset(), 842 Operand(zero_reg)); 843 // Advance current position after a zero-length match. 844 __ Daddu(current_input_offset(), 845 current_input_offset(), 846 Operand((mode_ == UC16) ? 2 : 1)); 847 } 848 849 __ Branch(&load_char_start_regexp); 850 } else { 851 __ li(v0, Operand(SUCCESS)); 852 } 853 } 854 // Exit and return v0. 855 __ bind(&exit_label_); 856 if (global()) { 857 __ ld(v0, MemOperand(frame_pointer(), kSuccessfulCaptures)); 858 } 859 860 __ bind(&return_v0); 861 // Skip sp past regexp registers and local variables.. 862 __ mov(sp, frame_pointer()); 863 // Restore registers s0..s7 and return (restoring ra to pc). 864 __ MultiPop(registers_to_retain | ra.bit()); 865 __ Ret(); 866 867 // Backtrack code (branch target for conditional backtracks). 868 if (backtrack_label_.is_linked()) { 869 __ bind(&backtrack_label_); 870 Backtrack(); 871 } 872 873 Label exit_with_exception; 874 875 // Preempt-code. 876 if (check_preempt_label_.is_linked()) { 877 SafeCallTarget(&check_preempt_label_); 878 // Put regexp engine registers on stack. 879 RegList regexp_registers_to_retain = current_input_offset().bit() | 880 current_character().bit() | backtrack_stackpointer().bit(); 881 __ MultiPush(regexp_registers_to_retain); 882 CallCheckStackGuardState(a0); 883 __ MultiPop(regexp_registers_to_retain); 884 // If returning non-zero, we should end execution with the given 885 // result as return value. 886 __ Branch(&return_v0, ne, v0, Operand(zero_reg)); 887 888 // String might have moved: Reload end of string from frame. 889 __ ld(end_of_input_address(), MemOperand(frame_pointer(), kInputEnd)); 890 __ li(code_pointer(), Operand(masm_->CodeObject()), CONSTANT_SIZE); 891 SafeReturn(); 892 } 893 894 // Backtrack stack overflow code. 895 if (stack_overflow_label_.is_linked()) { 896 SafeCallTarget(&stack_overflow_label_); 897 // Reached if the backtrack-stack limit has been hit. 898 // Put regexp engine registers on stack first. 899 RegList regexp_registers = current_input_offset().bit() | 900 current_character().bit(); 901 __ MultiPush(regexp_registers); 902 Label grow_failed; 903 // Call GrowStack(backtrack_stackpointer(), &stack_base) 904 static const int num_arguments = 3; 905 __ PrepareCallCFunction(num_arguments, a0); 906 __ mov(a0, backtrack_stackpointer()); 907 __ Daddu(a1, frame_pointer(), Operand(kStackHighEnd)); 908 __ li(a2, Operand(ExternalReference::isolate_address(masm_->isolate()))); 909 ExternalReference grow_stack = 910 ExternalReference::re_grow_stack(masm_->isolate()); 911 __ CallCFunction(grow_stack, num_arguments); 912 // Restore regexp registers. 913 __ MultiPop(regexp_registers); 914 // If return NULL, we have failed to grow the stack, and 915 // must exit with a stack-overflow exception. 916 __ Branch(&exit_with_exception, eq, v0, Operand(zero_reg)); 917 // Otherwise use return value as new stack pointer. 918 __ mov(backtrack_stackpointer(), v0); 919 // Restore saved registers and continue. 920 __ li(code_pointer(), Operand(masm_->CodeObject()), CONSTANT_SIZE); 921 __ ld(end_of_input_address(), MemOperand(frame_pointer(), kInputEnd)); 922 SafeReturn(); 923 } 924 925 if (exit_with_exception.is_linked()) { 926 // If any of the code above needed to exit with an exception. 927 __ bind(&exit_with_exception); 928 // Exit with Result EXCEPTION(-1) to signal thrown exception. 929 __ li(v0, Operand(EXCEPTION)); 930 __ jmp(&return_v0); 931 } 932 } 933 934 CodeDesc code_desc; 935 masm_->GetCode(&code_desc); 936 Handle<Code> code = isolate()->factory()->NewCode( 937 code_desc, Code::ComputeFlags(Code::REGEXP), masm_->CodeObject()); 938 LOG(masm_->isolate(), RegExpCodeCreateEvent(*code, *source)); 939 return Handle<HeapObject>::cast(code); 940 } 941 942 943 void RegExpMacroAssemblerMIPS::GoTo(Label* to) { 944 if (to == NULL) { 945 Backtrack(); 946 return; 947 } 948 __ jmp(to); 949 return; 950 } 951 952 953 void RegExpMacroAssemblerMIPS::IfRegisterGE(int reg, 954 int comparand, 955 Label* if_ge) { 956 __ ld(a0, register_location(reg)); 957 BranchOrBacktrack(if_ge, ge, a0, Operand(comparand)); 958 } 959 960 961 void RegExpMacroAssemblerMIPS::IfRegisterLT(int reg, 962 int comparand, 963 Label* if_lt) { 964 __ ld(a0, register_location(reg)); 965 BranchOrBacktrack(if_lt, lt, a0, Operand(comparand)); 966 } 967 968 969 void RegExpMacroAssemblerMIPS::IfRegisterEqPos(int reg, 970 Label* if_eq) { 971 __ ld(a0, register_location(reg)); 972 BranchOrBacktrack(if_eq, eq, a0, Operand(current_input_offset())); 973 } 974 975 976 RegExpMacroAssembler::IrregexpImplementation 977 RegExpMacroAssemblerMIPS::Implementation() { 978 return kMIPSImplementation; 979 } 980 981 982 void RegExpMacroAssemblerMIPS::LoadCurrentCharacter(int cp_offset, 983 Label* on_end_of_input, 984 bool check_bounds, 985 int characters) { 986 DCHECK(cp_offset < (1<<30)); // Be sane! (And ensure negation works). 987 if (check_bounds) { 988 if (cp_offset >= 0) { 989 CheckPosition(cp_offset + characters - 1, on_end_of_input); 990 } else { 991 CheckPosition(cp_offset, on_end_of_input); 992 } 993 } 994 LoadCurrentCharacterUnchecked(cp_offset, characters); 995 } 996 997 998 void RegExpMacroAssemblerMIPS::PopCurrentPosition() { 999 Pop(current_input_offset()); 1000 } 1001 1002 1003 void RegExpMacroAssemblerMIPS::PopRegister(int register_index) { 1004 Pop(a0); 1005 __ sd(a0, register_location(register_index)); 1006 } 1007 1008 1009 void RegExpMacroAssemblerMIPS::PushBacktrack(Label* label) { 1010 if (label->is_bound()) { 1011 int target = label->pos(); 1012 __ li(a0, Operand(target + Code::kHeaderSize - kHeapObjectTag)); 1013 } else { 1014 Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_); 1015 Label after_constant; 1016 __ Branch(&after_constant); 1017 int offset = masm_->pc_offset(); 1018 int cp_offset = offset + Code::kHeaderSize - kHeapObjectTag; 1019 __ emit(0); 1020 masm_->label_at_put(label, offset); 1021 __ bind(&after_constant); 1022 if (is_int16(cp_offset)) { 1023 __ lwu(a0, MemOperand(code_pointer(), cp_offset)); 1024 } else { 1025 __ Daddu(a0, code_pointer(), cp_offset); 1026 __ lwu(a0, MemOperand(a0, 0)); 1027 } 1028 } 1029 Push(a0); 1030 CheckStackLimit(); 1031 } 1032 1033 1034 void RegExpMacroAssemblerMIPS::PushCurrentPosition() { 1035 Push(current_input_offset()); 1036 } 1037 1038 1039 void RegExpMacroAssemblerMIPS::PushRegister(int register_index, 1040 StackCheckFlag check_stack_limit) { 1041 __ ld(a0, register_location(register_index)); 1042 Push(a0); 1043 if (check_stack_limit) CheckStackLimit(); 1044 } 1045 1046 1047 void RegExpMacroAssemblerMIPS::ReadCurrentPositionFromRegister(int reg) { 1048 __ ld(current_input_offset(), register_location(reg)); 1049 } 1050 1051 1052 void RegExpMacroAssemblerMIPS::ReadStackPointerFromRegister(int reg) { 1053 __ ld(backtrack_stackpointer(), register_location(reg)); 1054 __ ld(a0, MemOperand(frame_pointer(), kStackHighEnd)); 1055 __ Daddu(backtrack_stackpointer(), backtrack_stackpointer(), Operand(a0)); 1056 } 1057 1058 1059 void RegExpMacroAssemblerMIPS::SetCurrentPositionFromEnd(int by) { 1060 Label after_position; 1061 __ Branch(&after_position, 1062 ge, 1063 current_input_offset(), 1064 Operand(-by * char_size())); 1065 __ li(current_input_offset(), -by * char_size()); 1066 // On RegExp code entry (where this operation is used), the character before 1067 // the current position is expected to be already loaded. 1068 // We have advanced the position, so it's safe to read backwards. 1069 LoadCurrentCharacterUnchecked(-1, 1); 1070 __ bind(&after_position); 1071 } 1072 1073 1074 void RegExpMacroAssemblerMIPS::SetRegister(int register_index, int to) { 1075 DCHECK(register_index >= num_saved_registers_); // Reserved for positions! 1076 __ li(a0, Operand(to)); 1077 __ sd(a0, register_location(register_index)); 1078 } 1079 1080 1081 bool RegExpMacroAssemblerMIPS::Succeed() { 1082 __ jmp(&success_label_); 1083 return global(); 1084 } 1085 1086 1087 void RegExpMacroAssemblerMIPS::WriteCurrentPositionToRegister(int reg, 1088 int cp_offset) { 1089 if (cp_offset == 0) { 1090 __ sd(current_input_offset(), register_location(reg)); 1091 } else { 1092 __ Daddu(a0, current_input_offset(), Operand(cp_offset * char_size())); 1093 __ sd(a0, register_location(reg)); 1094 } 1095 } 1096 1097 1098 void RegExpMacroAssemblerMIPS::ClearRegisters(int reg_from, int reg_to) { 1099 DCHECK(reg_from <= reg_to); 1100 __ ld(a0, MemOperand(frame_pointer(), kStringStartMinusOne)); 1101 for (int reg = reg_from; reg <= reg_to; reg++) { 1102 __ sd(a0, register_location(reg)); 1103 } 1104 } 1105 1106 1107 void RegExpMacroAssemblerMIPS::WriteStackPointerToRegister(int reg) { 1108 __ ld(a1, MemOperand(frame_pointer(), kStackHighEnd)); 1109 __ Dsubu(a0, backtrack_stackpointer(), a1); 1110 __ sd(a0, register_location(reg)); 1111 } 1112 1113 1114 bool RegExpMacroAssemblerMIPS::CanReadUnaligned() { 1115 return false; 1116 } 1117 1118 1119 // Private methods: 1120 1121 void RegExpMacroAssemblerMIPS::CallCheckStackGuardState(Register scratch) { 1122 int stack_alignment = base::OS::ActivationFrameAlignment(); 1123 1124 // Align the stack pointer and save the original sp value on the stack. 1125 __ mov(scratch, sp); 1126 __ Dsubu(sp, sp, Operand(kPointerSize)); 1127 DCHECK(base::bits::IsPowerOfTwo32(stack_alignment)); 1128 __ And(sp, sp, Operand(-stack_alignment)); 1129 __ sd(scratch, MemOperand(sp)); 1130 1131 __ mov(a2, frame_pointer()); 1132 // Code* of self. 1133 __ li(a1, Operand(masm_->CodeObject()), CONSTANT_SIZE); 1134 1135 // We need to make room for the return address on the stack. 1136 DCHECK(IsAligned(stack_alignment, kPointerSize)); 1137 __ Dsubu(sp, sp, Operand(stack_alignment)); 1138 1139 // Stack pointer now points to cell where return address is to be written. 1140 // Arguments are in registers, meaning we teat the return address as 1141 // argument 5. Since DirectCEntryStub will handleallocating space for the C 1142 // argument slots, we don't need to care about that here. This is how the 1143 // stack will look (sp meaning the value of sp at this moment): 1144 // [sp + 3] - empty slot if needed for alignment. 1145 // [sp + 2] - saved sp. 1146 // [sp + 1] - second word reserved for return value. 1147 // [sp + 0] - first word reserved for return value. 1148 1149 // a0 will point to the return address, placed by DirectCEntry. 1150 __ mov(a0, sp); 1151 1152 ExternalReference stack_guard_check = 1153 ExternalReference::re_check_stack_guard_state(masm_->isolate()); 1154 __ li(t9, Operand(stack_guard_check)); 1155 DirectCEntryStub stub(isolate()); 1156 stub.GenerateCall(masm_, t9); 1157 1158 // DirectCEntryStub allocated space for the C argument slots so we have to 1159 // drop them with the return address from the stack with loading saved sp. 1160 // At this point stack must look: 1161 // [sp + 7] - empty slot if needed for alignment. 1162 // [sp + 6] - saved sp. 1163 // [sp + 5] - second word reserved for return value. 1164 // [sp + 4] - first word reserved for return value. 1165 // [sp + 3] - C argument slot. 1166 // [sp + 2] - C argument slot. 1167 // [sp + 1] - C argument slot. 1168 // [sp + 0] - C argument slot. 1169 __ ld(sp, MemOperand(sp, stack_alignment + kCArgsSlotsSize)); 1170 1171 __ li(code_pointer(), Operand(masm_->CodeObject())); 1172 } 1173 1174 1175 // Helper function for reading a value out of a stack frame. 1176 template <typename T> 1177 static T& frame_entry(Address re_frame, int frame_offset) { 1178 return reinterpret_cast<T&>(Memory::int32_at(re_frame + frame_offset)); 1179 } 1180 1181 1182 template <typename T> 1183 static T* frame_entry_address(Address re_frame, int frame_offset) { 1184 return reinterpret_cast<T*>(re_frame + frame_offset); 1185 } 1186 1187 1188 int64_t RegExpMacroAssemblerMIPS::CheckStackGuardState(Address* return_address, 1189 Code* re_code, 1190 Address re_frame) { 1191 return NativeRegExpMacroAssembler::CheckStackGuardState( 1192 frame_entry<Isolate*>(re_frame, kIsolate), 1193 static_cast<int>(frame_entry<int64_t>(re_frame, kStartIndex)), 1194 frame_entry<int64_t>(re_frame, kDirectCall) == 1, return_address, re_code, 1195 frame_entry_address<String*>(re_frame, kInputString), 1196 frame_entry_address<const byte*>(re_frame, kInputStart), 1197 frame_entry_address<const byte*>(re_frame, kInputEnd)); 1198 } 1199 1200 1201 MemOperand RegExpMacroAssemblerMIPS::register_location(int register_index) { 1202 DCHECK(register_index < (1<<30)); 1203 if (num_registers_ <= register_index) { 1204 num_registers_ = register_index + 1; 1205 } 1206 return MemOperand(frame_pointer(), 1207 kRegisterZero - register_index * kPointerSize); 1208 } 1209 1210 1211 void RegExpMacroAssemblerMIPS::CheckPosition(int cp_offset, 1212 Label* on_outside_input) { 1213 if (cp_offset >= 0) { 1214 BranchOrBacktrack(on_outside_input, ge, current_input_offset(), 1215 Operand(-cp_offset * char_size())); 1216 } else { 1217 __ ld(a1, MemOperand(frame_pointer(), kStringStartMinusOne)); 1218 __ Daddu(a0, current_input_offset(), Operand(cp_offset * char_size())); 1219 BranchOrBacktrack(on_outside_input, le, a0, Operand(a1)); 1220 } 1221 } 1222 1223 1224 void RegExpMacroAssemblerMIPS::BranchOrBacktrack(Label* to, 1225 Condition condition, 1226 Register rs, 1227 const Operand& rt) { 1228 if (condition == al) { // Unconditional. 1229 if (to == NULL) { 1230 Backtrack(); 1231 return; 1232 } 1233 __ jmp(to); 1234 return; 1235 } 1236 if (to == NULL) { 1237 __ Branch(&backtrack_label_, condition, rs, rt); 1238 return; 1239 } 1240 __ Branch(to, condition, rs, rt); 1241 } 1242 1243 1244 void RegExpMacroAssemblerMIPS::SafeCall(Label* to, 1245 Condition cond, 1246 Register rs, 1247 const Operand& rt) { 1248 __ BranchAndLink(to, cond, rs, rt); 1249 } 1250 1251 1252 void RegExpMacroAssemblerMIPS::SafeReturn() { 1253 __ pop(ra); 1254 __ Daddu(t1, ra, Operand(masm_->CodeObject())); 1255 __ Jump(t1); 1256 } 1257 1258 1259 void RegExpMacroAssemblerMIPS::SafeCallTarget(Label* name) { 1260 __ bind(name); 1261 __ Dsubu(ra, ra, Operand(masm_->CodeObject())); 1262 __ push(ra); 1263 } 1264 1265 1266 void RegExpMacroAssemblerMIPS::Push(Register source) { 1267 DCHECK(!source.is(backtrack_stackpointer())); 1268 __ Daddu(backtrack_stackpointer(), 1269 backtrack_stackpointer(), 1270 Operand(-kIntSize)); 1271 __ sw(source, MemOperand(backtrack_stackpointer())); 1272 } 1273 1274 1275 void RegExpMacroAssemblerMIPS::Pop(Register target) { 1276 DCHECK(!target.is(backtrack_stackpointer())); 1277 __ lw(target, MemOperand(backtrack_stackpointer())); 1278 __ Daddu(backtrack_stackpointer(), backtrack_stackpointer(), kIntSize); 1279 } 1280 1281 1282 void RegExpMacroAssemblerMIPS::CheckPreemption() { 1283 // Check for preemption. 1284 ExternalReference stack_limit = 1285 ExternalReference::address_of_stack_limit(masm_->isolate()); 1286 __ li(a0, Operand(stack_limit)); 1287 __ ld(a0, MemOperand(a0)); 1288 SafeCall(&check_preempt_label_, ls, sp, Operand(a0)); 1289 } 1290 1291 1292 void RegExpMacroAssemblerMIPS::CheckStackLimit() { 1293 ExternalReference stack_limit = 1294 ExternalReference::address_of_regexp_stack_limit(masm_->isolate()); 1295 1296 __ li(a0, Operand(stack_limit)); 1297 __ ld(a0, MemOperand(a0)); 1298 SafeCall(&stack_overflow_label_, ls, backtrack_stackpointer(), Operand(a0)); 1299 } 1300 1301 1302 void RegExpMacroAssemblerMIPS::LoadCurrentCharacterUnchecked(int cp_offset, 1303 int characters) { 1304 Register offset = current_input_offset(); 1305 if (cp_offset != 0) { 1306 // t3 is not being used to store the capture start index at this point. 1307 __ Daddu(t3, current_input_offset(), Operand(cp_offset * char_size())); 1308 offset = t3; 1309 } 1310 // We assume that we cannot do unaligned loads on MIPS, so this function 1311 // must only be used to load a single character at a time. 1312 DCHECK(characters == 1); 1313 __ Daddu(t1, end_of_input_address(), Operand(offset)); 1314 if (mode_ == LATIN1) { 1315 __ lbu(current_character(), MemOperand(t1, 0)); 1316 } else { 1317 DCHECK(mode_ == UC16); 1318 __ lhu(current_character(), MemOperand(t1, 0)); 1319 } 1320 } 1321 1322 #undef __ 1323 1324 #endif // V8_INTERPRETED_REGEXP 1325 1326 } // namespace internal 1327 } // namespace v8 1328 1329 #endif // V8_TARGET_ARCH_MIPS64 1330