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