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