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