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