1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #if V8_TARGET_ARCH_IA32
6 
7 #include "src/regexp/ia32/regexp-macro-assembler-ia32.h"
8 
9 #include "src/codegen/assembler-inl.h"
10 #include "src/codegen/macro-assembler.h"
11 #include "src/logging/log.h"
12 #include "src/objects/objects-inl.h"
13 #include "src/regexp/regexp-macro-assembler.h"
14 #include "src/regexp/regexp-stack.h"
15 #include "src/strings/unicode.h"
16 
17 namespace v8 {
18 namespace internal {
19 
20 /*
21  * This assembler uses the following register assignment convention
22  * - edx : Current character.  Must be loaded using LoadCurrentCharacter
23  *         before using any of the dispatch methods.  Temporarily stores the
24  *         index of capture start after a matching pass for a global regexp.
25  * - edi : Current position in input, as negative offset from end of string.
26  *         Please notice that this is the byte offset, not the character offset!
27  * - esi : end of input (points to byte after last character in input).
28  * - ebp : Frame pointer.  Used to access arguments, local variables and
29  *         RegExp registers.
30  * - esp : Points to tip of C stack.
31  * - ecx : Points to tip of backtrack stack
32  *
33  * The registers eax and ebx are free to use for computations.
34  *
35  * Each call to a public method should retain this convention.
36  * The stack will have the following structure:
37  *       - Address regexp       (address of the JSRegExp object; unused in
38  *                               native code, passed to match signature of
39  *                               the interpreter)
40  *       - Isolate* isolate     (address of the current isolate)
41  *       - direct_call          (if 1, direct call from JavaScript code, if 0
42  *                               call through the runtime system)
43  *       - capture array size   (may fit multiple sets of matches)
44  *       - int* capture_array   (int[num_saved_registers_], for output).
45  *       - end of input         (address of end of string)
46  *       - start of input       (address of first character in string)
47  *       - start index          (character index of start)
48  *       - String input_string  (location of a handle containing the string)
49  *       --- frame alignment (if applicable) ---
50  *       - return address
51  * ebp-> - old ebp
52  *       - backup of caller esi
53  *       - backup of caller edi
54  *       - backup of caller ebx
55  *       - success counter      (only for global regexps to count matches).
56  *       - Offset of location before start of input (effectively character
57  *         string start - 1). Used to initialize capture registers to a
58  *         non-position.
59  *       - register 0  ebp[-4]  (only positions must be stored in the first
60  *       - register 1  ebp[-8]   num_saved_registers_ registers)
61  *       - ...
62  *
63  * The first num_saved_registers_ registers are initialized to point to
64  * "character -1" in the string (i.e., char_size() bytes before the first
65  * character of the string). The remaining registers starts out as garbage.
66  *
67  * The data up to the return address must be placed there by the calling
68  * code, by calling the code entry as cast to a function with the signature:
69  * int (*match)(String input_string,
70  *              int start_index,
71  *              Address start,
72  *              Address end,
73  *              int* capture_output_array,
74  *              int num_capture_registers,
75  *              bool direct_call = false,
76  *              Isolate* isolate
77  *              Address regexp);
78  */
79 
80 #define __ ACCESS_MASM(masm_)
81 
82 const int RegExpMacroAssemblerIA32::kRegExpCodeSize;
83 
RegExpMacroAssemblerIA32(Isolate* isolate, Zone* zone, Mode mode, int registers_to_save)84 RegExpMacroAssemblerIA32::RegExpMacroAssemblerIA32(Isolate* isolate, Zone* zone,
85                                                    Mode mode,
86                                                    int registers_to_save)
87     : NativeRegExpMacroAssembler(isolate, zone),
88       masm_(std::make_unique<MacroAssembler>(
89           isolate, CodeObjectRequired::kYes,
90           NewAssemblerBuffer(kRegExpCodeSize))),
91       no_root_array_scope_(masm_.get()),
92       mode_(mode),
93       num_registers_(registers_to_save),
94       num_saved_registers_(registers_to_save),
95       entry_label_(),
96       start_label_(),
97       success_label_(),
98       backtrack_label_(),
99       exit_label_() {
100   DCHECK_EQ(0, registers_to_save % 2);
101   __ jmp(&entry_label_);   // We'll write the entry code later.
102   __ bind(&start_label_);  // And then continue from here.
103 }
104 
~RegExpMacroAssemblerIA32()105 RegExpMacroAssemblerIA32::~RegExpMacroAssemblerIA32() {
106   // Unuse labels in case we throw away the assembler without calling GetCode.
107   entry_label_.Unuse();
108   start_label_.Unuse();
109   success_label_.Unuse();
110   backtrack_label_.Unuse();
111   exit_label_.Unuse();
112   check_preempt_label_.Unuse();
113   stack_overflow_label_.Unuse();
114   fallback_label_.Unuse();
115 }
116 
117 
stack_limit_slack()118 int RegExpMacroAssemblerIA32::stack_limit_slack()  {
119   return RegExpStack::kStackLimitSlack;
120 }
121 
122 
AdvanceCurrentPosition(int by)123 void RegExpMacroAssemblerIA32::AdvanceCurrentPosition(int by) {
124   if (by != 0) {
125     __ add(edi, Immediate(by * char_size()));
126   }
127 }
128 
129 
AdvanceRegister(int reg, int by)130 void RegExpMacroAssemblerIA32::AdvanceRegister(int reg, int by) {
131   DCHECK_LE(0, reg);
132   DCHECK_GT(num_registers_, reg);
133   if (by != 0) {
134     __ add(register_location(reg), Immediate(by));
135   }
136 }
137 
138 
Backtrack()139 void RegExpMacroAssemblerIA32::Backtrack() {
140   CheckPreemption();
141   if (has_backtrack_limit()) {
142     Label next;
143     __ inc(Operand(ebp, kBacktrackCount));
144     __ cmp(Operand(ebp, kBacktrackCount), Immediate(backtrack_limit()));
145     __ j(not_equal, &next);
146 
147     // Backtrack limit exceeded.
148     if (can_fallback()) {
149       __ jmp(&fallback_label_);
150     } else {
151       // Can't fallback, so we treat it as a failed match.
152       Fail();
153     }
154 
155     __ bind(&next);
156   }
157   // Pop Code offset from backtrack stack, add Code and jump to location.
158   Pop(ebx);
159   __ add(ebx, Immediate(masm_->CodeObject()));
160   __ jmp(ebx);
161 }
162 
163 
Bind(Label* label)164 void RegExpMacroAssemblerIA32::Bind(Label* label) {
165   __ bind(label);
166 }
167 
168 
CheckCharacter(uint32_t c, Label* on_equal)169 void RegExpMacroAssemblerIA32::CheckCharacter(uint32_t c, Label* on_equal) {
170   __ cmp(current_character(), c);
171   BranchOrBacktrack(equal, on_equal);
172 }
173 
CheckCharacterGT(base::uc16 limit, Label* on_greater)174 void RegExpMacroAssemblerIA32::CheckCharacterGT(base::uc16 limit,
175                                                 Label* on_greater) {
176   __ cmp(current_character(), limit);
177   BranchOrBacktrack(greater, on_greater);
178 }
179 
CheckAtStart(int cp_offset, Label* on_at_start)180 void RegExpMacroAssemblerIA32::CheckAtStart(int cp_offset, Label* on_at_start) {
181   __ lea(eax, Operand(edi, -char_size() + cp_offset * char_size()));
182   __ cmp(eax, Operand(ebp, kStringStartMinusOne));
183   BranchOrBacktrack(equal, on_at_start);
184 }
185 
CheckNotAtStart(int cp_offset, Label* on_not_at_start)186 void RegExpMacroAssemblerIA32::CheckNotAtStart(int cp_offset,
187                                                Label* on_not_at_start) {
188   __ lea(eax, Operand(edi, -char_size() + cp_offset * char_size()));
189   __ cmp(eax, Operand(ebp, kStringStartMinusOne));
190   BranchOrBacktrack(not_equal, on_not_at_start);
191 }
192 
CheckCharacterLT(base::uc16 limit, Label* on_less)193 void RegExpMacroAssemblerIA32::CheckCharacterLT(base::uc16 limit,
194                                                 Label* on_less) {
195   __ cmp(current_character(), limit);
196   BranchOrBacktrack(less, on_less);
197 }
198 
CheckGreedyLoop(Label* on_equal)199 void RegExpMacroAssemblerIA32::CheckGreedyLoop(Label* on_equal) {
200   Label fallthrough;
201   __ cmp(edi, Operand(backtrack_stackpointer(), 0));
202   __ j(not_equal, &fallthrough);
203   __ add(backtrack_stackpointer(), Immediate(kSystemPointerSize));  // Pop.
204   BranchOrBacktrack(no_condition, on_equal);
205   __ bind(&fallthrough);
206 }
207 
PushCallerSavedRegisters()208 void RegExpMacroAssemblerIA32::PushCallerSavedRegisters() {
209   STATIC_ASSERT(backtrack_stackpointer() == ecx);
210   STATIC_ASSERT(current_character() == edx);
211   __ push(ecx);
212   __ push(edx);
213 }
214 
PopCallerSavedRegisters()215 void RegExpMacroAssemblerIA32::PopCallerSavedRegisters() {
216   __ pop(edx);
217   __ pop(ecx);
218 }
219 
CheckNotBackReferenceIgnoreCase( int start_reg, bool read_backward, bool unicode, Label* on_no_match)220 void RegExpMacroAssemblerIA32::CheckNotBackReferenceIgnoreCase(
221     int start_reg, bool read_backward, bool unicode, Label* on_no_match) {
222   Label fallthrough;
223   __ mov(edx, register_location(start_reg));  // Index of start of capture
224   __ mov(ebx, register_location(start_reg + 1));  // Index of end of capture
225   __ sub(ebx, edx);  // Length of capture.
226 
227   // At this point, the capture registers are either both set or both cleared.
228   // If the capture length is zero, then the capture is either empty or cleared.
229   // Fall through in both cases.
230   __ j(equal, &fallthrough);
231 
232   // Check that there are sufficient characters left in the input.
233   if (read_backward) {
234     __ mov(eax, Operand(ebp, kStringStartMinusOne));
235     __ add(eax, ebx);
236     __ cmp(edi, eax);
237     BranchOrBacktrack(less_equal, on_no_match);
238   } else {
239     __ mov(eax, edi);
240     __ add(eax, ebx);
241     BranchOrBacktrack(greater, on_no_match);
242   }
243 
244   if (mode_ == LATIN1) {
245     Label success;
246     Label fail;
247     Label loop_increment;
248     // Save register contents to make the registers available below.
249     __ push(edi);
250     __ push(backtrack_stackpointer());
251     // After this, the eax, ecx, and edi registers are available.
252 
253     __ add(edx, esi);  // Start of capture
254     __ add(edi, esi);  // Start of text to match against capture.
255     if (read_backward) {
256       __ sub(edi, ebx);  // Offset by length when matching backwards.
257     }
258     __ add(ebx, edi);  // End of text to match against capture.
259 
260     Label loop;
261     __ bind(&loop);
262     __ movzx_b(eax, Operand(edi, 0));
263     __ cmpb_al(Operand(edx, 0));
264     __ j(equal, &loop_increment);
265 
266     // Mismatch, try case-insensitive match (converting letters to lower-case).
267     __ or_(eax, 0x20);  // Convert match character to lower-case.
268     __ lea(ecx, Operand(eax, -'a'));
269     __ cmp(ecx, static_cast<int32_t>('z' - 'a'));  // Is eax a lowercase letter?
270     Label convert_capture;
271     __ j(below_equal, &convert_capture);  // In range 'a'-'z'.
272     // Latin-1: Check for values in range [224,254] but not 247.
273     __ sub(ecx, Immediate(224 - 'a'));
274     __ cmp(ecx, Immediate(254 - 224));
275     __ j(above, &fail);  // Weren't Latin-1 letters.
276     __ cmp(ecx, Immediate(247 - 224));  // Check for 247.
277     __ j(equal, &fail);
278     __ bind(&convert_capture);
279     // Also convert capture character.
280     __ movzx_b(ecx, Operand(edx, 0));
281     __ or_(ecx, 0x20);
282 
283     __ cmp(eax, ecx);
284     __ j(not_equal, &fail);
285 
286     __ bind(&loop_increment);
287     // Increment pointers into match and capture strings.
288     __ add(edx, Immediate(1));
289     __ add(edi, Immediate(1));
290     // Compare to end of match, and loop if not done.
291     __ cmp(edi, ebx);
292     __ j(below, &loop);
293     __ jmp(&success);
294 
295     __ bind(&fail);
296     // Restore original values before failing.
297     __ pop(backtrack_stackpointer());
298     __ pop(edi);
299     BranchOrBacktrack(no_condition, on_no_match);
300 
301     __ bind(&success);
302     // Restore original value before continuing.
303     __ pop(backtrack_stackpointer());
304     // Drop original value of character position.
305     __ add(esp, Immediate(kSystemPointerSize));
306     // Compute new value of character position after the matched part.
307     __ sub(edi, esi);
308     if (read_backward) {
309       // Subtract match length if we matched backward.
310       __ add(edi, register_location(start_reg));
311       __ sub(edi, register_location(start_reg + 1));
312     }
313   } else {
314     DCHECK(mode_ == UC16);
315     // Save registers before calling C function.
316     __ push(esi);
317     __ push(edi);
318     __ push(backtrack_stackpointer());
319     __ push(ebx);
320 
321     static const int argument_count = 4;
322     __ PrepareCallCFunction(argument_count, ecx);
323     // Put arguments into allocated stack area, last argument highest on stack.
324     // Parameters are
325     //   Address byte_offset1 - Address captured substring's start.
326     //   Address byte_offset2 - Address of current character position.
327     //   size_t byte_length - length of capture in bytes(!)
328     //   Isolate* isolate.
329 
330     // Set isolate.
331     __ mov(Operand(esp, 3 * kSystemPointerSize),
332            Immediate(ExternalReference::isolate_address(isolate())));
333     // Set byte_length.
334     __ mov(Operand(esp, 2 * kSystemPointerSize), ebx);
335     // Set byte_offset2.
336     // Found by adding negative string-end offset of current position (edi)
337     // to end of string.
338     __ add(edi, esi);
339     if (read_backward) {
340       __ sub(edi, ebx);  // Offset by length when matching backwards.
341     }
342     __ mov(Operand(esp, 1 * kSystemPointerSize), edi);
343     // Set byte_offset1.
344     // Start of capture, where edx already holds string-end negative offset.
345     __ add(edx, esi);
346     __ mov(Operand(esp, 0 * kSystemPointerSize), edx);
347 
348     {
349       AllowExternalCallThatCantCauseGC scope(masm_.get());
350       ExternalReference compare =
351           unicode
352               ? ExternalReference::re_case_insensitive_compare_unicode()
353               : ExternalReference::re_case_insensitive_compare_non_unicode();
354       __ CallCFunction(compare, argument_count);
355     }
356     // Pop original values before reacting on result value.
357     __ pop(ebx);
358     __ pop(backtrack_stackpointer());
359     __ pop(edi);
360     __ pop(esi);
361 
362     // Check if function returned non-zero for success or zero for failure.
363     __ or_(eax, eax);
364     BranchOrBacktrack(zero, on_no_match);
365     // On success, advance position by length of capture.
366     if (read_backward) {
367       __ sub(edi, ebx);
368     } else {
369       __ add(edi, ebx);
370     }
371   }
372   __ bind(&fallthrough);
373 }
374 
CheckNotBackReference(int start_reg, bool read_backward, Label* on_no_match)375 void RegExpMacroAssemblerIA32::CheckNotBackReference(int start_reg,
376                                                      bool read_backward,
377                                                      Label* on_no_match) {
378   Label fallthrough;
379   Label success;
380   Label fail;
381 
382   // Find length of back-referenced capture.
383   __ mov(edx, register_location(start_reg));
384   __ mov(eax, register_location(start_reg + 1));
385   __ sub(eax, edx);  // 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   __ j(equal, &fallthrough);
391 
392   // Check that there are sufficient characters left in the input.
393   if (read_backward) {
394     __ mov(ebx, Operand(ebp, kStringStartMinusOne));
395     __ add(ebx, eax);
396     __ cmp(edi, ebx);
397     BranchOrBacktrack(less_equal, on_no_match);
398   } else {
399     __ mov(ebx, edi);
400     __ add(ebx, eax);
401     BranchOrBacktrack(greater, on_no_match);
402   }
403 
404   // Save register to make it available below.
405   __ push(backtrack_stackpointer());
406 
407   // Compute pointers to match string and capture string
408   __ add(edx, esi);  // Start of capture.
409   __ lea(ebx, Operand(esi, edi, times_1, 0));  // Start of match.
410   if (read_backward) {
411     __ sub(ebx, eax);  // Offset by length when matching backwards.
412   }
413   __ lea(ecx, Operand(eax, ebx, times_1, 0));  // End of match
414 
415   Label loop;
416   __ bind(&loop);
417   if (mode_ == LATIN1) {
418     __ movzx_b(eax, Operand(edx, 0));
419     __ cmpb_al(Operand(ebx, 0));
420   } else {
421     DCHECK(mode_ == UC16);
422     __ movzx_w(eax, Operand(edx, 0));
423     __ cmpw_ax(Operand(ebx, 0));
424   }
425   __ j(not_equal, &fail);
426   // Increment pointers into capture and match string.
427   __ add(edx, Immediate(char_size()));
428   __ add(ebx, Immediate(char_size()));
429   // Check if we have reached end of match area.
430   __ cmp(ebx, ecx);
431   __ j(below, &loop);
432   __ jmp(&success);
433 
434   __ bind(&fail);
435   // Restore backtrack stackpointer.
436   __ pop(backtrack_stackpointer());
437   BranchOrBacktrack(no_condition, on_no_match);
438 
439   __ bind(&success);
440   // Move current character position to position after match.
441   __ mov(edi, ecx);
442   __ sub(edi, esi);
443   if (read_backward) {
444     // Subtract match length if we matched backward.
445     __ add(edi, register_location(start_reg));
446     __ sub(edi, register_location(start_reg + 1));
447   }
448   // Restore backtrack stackpointer.
449   __ pop(backtrack_stackpointer());
450 
451   __ bind(&fallthrough);
452 }
453 
454 
CheckNotCharacter(uint32_t c, Label* on_not_equal)455 void RegExpMacroAssemblerIA32::CheckNotCharacter(uint32_t c,
456                                                  Label* on_not_equal) {
457   __ cmp(current_character(), c);
458   BranchOrBacktrack(not_equal, on_not_equal);
459 }
460 
461 
CheckCharacterAfterAnd(uint32_t c, uint32_t mask, Label* on_equal)462 void RegExpMacroAssemblerIA32::CheckCharacterAfterAnd(uint32_t c,
463                                                       uint32_t mask,
464                                                       Label* on_equal) {
465   if (c == 0) {
466     __ test(current_character(), Immediate(mask));
467   } else {
468     __ mov(eax, mask);
469     __ and_(eax, current_character());
470     __ cmp(eax, c);
471   }
472   BranchOrBacktrack(equal, on_equal);
473 }
474 
475 
CheckNotCharacterAfterAnd(uint32_t c, uint32_t mask, Label* on_not_equal)476 void RegExpMacroAssemblerIA32::CheckNotCharacterAfterAnd(uint32_t c,
477                                                          uint32_t mask,
478                                                          Label* on_not_equal) {
479   if (c == 0) {
480     __ test(current_character(), Immediate(mask));
481   } else {
482     __ mov(eax, mask);
483     __ and_(eax, current_character());
484     __ cmp(eax, c);
485   }
486   BranchOrBacktrack(not_equal, on_not_equal);
487 }
488 
CheckNotCharacterAfterMinusAnd( base::uc16 c, base::uc16 minus, base::uc16 mask, Label* on_not_equal)489 void RegExpMacroAssemblerIA32::CheckNotCharacterAfterMinusAnd(
490     base::uc16 c, base::uc16 minus, base::uc16 mask, Label* on_not_equal) {
491   DCHECK_GT(String::kMaxUtf16CodeUnit, minus);
492   __ lea(eax, Operand(current_character(), -minus));
493   if (c == 0) {
494     __ test(eax, Immediate(mask));
495   } else {
496     __ and_(eax, mask);
497     __ cmp(eax, c);
498   }
499   BranchOrBacktrack(not_equal, on_not_equal);
500 }
501 
CheckCharacterInRange(base::uc16 from, base::uc16 to, Label* on_in_range)502 void RegExpMacroAssemblerIA32::CheckCharacterInRange(base::uc16 from,
503                                                      base::uc16 to,
504                                                      Label* on_in_range) {
505   __ lea(eax, Operand(current_character(), -from));
506   __ cmp(eax, to - from);
507   BranchOrBacktrack(below_equal, on_in_range);
508 }
509 
CheckCharacterNotInRange( base::uc16 from, base::uc16 to, Label* on_not_in_range)510 void RegExpMacroAssemblerIA32::CheckCharacterNotInRange(
511     base::uc16 from, base::uc16 to, Label* on_not_in_range) {
512   __ lea(eax, Operand(current_character(), -from));
513   __ cmp(eax, to - from);
514   BranchOrBacktrack(above, on_not_in_range);
515 }
516 
CallIsCharacterInRangeArray( const ZoneList<CharacterRange>* ranges)517 void RegExpMacroAssemblerIA32::CallIsCharacterInRangeArray(
518     const ZoneList<CharacterRange>* ranges) {
519   PushCallerSavedRegisters();
520 
521   static const int kNumArguments = 3;
522   __ PrepareCallCFunction(kNumArguments, ecx);
523 
524   __ mov(Operand(esp, 0 * kSystemPointerSize), current_character());
525   __ mov(Operand(esp, 1 * kSystemPointerSize), GetOrAddRangeArray(ranges));
526   __ mov(Operand(esp, 2 * kSystemPointerSize),
527          Immediate(ExternalReference::isolate_address(isolate())));
528 
529   {
530     // We have a frame (set up in GetCode), but the assembler doesn't know.
531     FrameScope scope(masm_.get(), StackFrame::MANUAL);
532     __ CallCFunction(ExternalReference::re_is_character_in_range_array(),
533                      kNumArguments);
534   }
535 
536   PopCallerSavedRegisters();
537 }
538 
CheckCharacterInRangeArray( const ZoneList<CharacterRange>* ranges, Label* on_in_range)539 bool RegExpMacroAssemblerIA32::CheckCharacterInRangeArray(
540     const ZoneList<CharacterRange>* ranges, Label* on_in_range) {
541   CallIsCharacterInRangeArray(ranges);
542   __ or_(eax, eax);
543   BranchOrBacktrack(not_zero, on_in_range);
544   return true;
545 }
546 
CheckCharacterNotInRangeArray( const ZoneList<CharacterRange>* ranges, Label* on_not_in_range)547 bool RegExpMacroAssemblerIA32::CheckCharacterNotInRangeArray(
548     const ZoneList<CharacterRange>* ranges, Label* on_not_in_range) {
549   CallIsCharacterInRangeArray(ranges);
550   __ or_(eax, eax);
551   BranchOrBacktrack(zero, on_not_in_range);
552   return true;
553 }
554 
CheckBitInTable( Handle<ByteArray> table, Label* on_bit_set)555 void RegExpMacroAssemblerIA32::CheckBitInTable(
556     Handle<ByteArray> table,
557     Label* on_bit_set) {
558   __ mov(eax, Immediate(table));
559   Register index = current_character();
560   if (mode_ != LATIN1 || kTableMask != String::kMaxOneByteCharCode) {
561     __ mov(ebx, kTableSize - 1);
562     __ and_(ebx, current_character());
563     index = ebx;
564   }
565   __ cmpb(FieldOperand(eax, index, times_1, ByteArray::kHeaderSize),
566           Immediate(0));
567   BranchOrBacktrack(not_equal, on_bit_set);
568 }
569 
CheckSpecialCharacterClass( StandardCharacterSet type, Label* on_no_match)570 bool RegExpMacroAssemblerIA32::CheckSpecialCharacterClass(
571     StandardCharacterSet type, Label* on_no_match) {
572   // Range checks (c in min..max) are generally implemented by an unsigned
573   // (c - min) <= (max - min) check
574   // TODO(jgruber): No custom implementation (yet): s(UC16), S(UC16).
575   switch (type) {
576     case StandardCharacterSet::kWhitespace:
577       // Match space-characters.
578       if (mode_ == LATIN1) {
579         // One byte space characters are '\t'..'\r', ' ' and \u00a0.
580         Label success;
581         __ cmp(current_character(), ' ');
582         __ j(equal, &success, Label::kNear);
583         // Check range 0x09..0x0D.
584         __ lea(eax, Operand(current_character(), -'\t'));
585         __ cmp(eax, '\r' - '\t');
586         __ j(below_equal, &success, Label::kNear);
587         // \u00a0 (NBSP).
588         __ cmp(eax, 0x00A0 - '\t');
589         BranchOrBacktrack(not_equal, on_no_match);
590         __ bind(&success);
591         return true;
592       }
593       return false;
594     case StandardCharacterSet::kNotWhitespace:
595       // The emitted code for generic character classes is good enough.
596       return false;
597     case StandardCharacterSet::kDigit:
598       // Match ASCII digits ('0'..'9').
599       __ lea(eax, Operand(current_character(), -'0'));
600       __ cmp(eax, '9' - '0');
601       BranchOrBacktrack(above, on_no_match);
602       return true;
603     case StandardCharacterSet::kNotDigit:
604       // Match non ASCII-digits.
605       __ lea(eax, Operand(current_character(), -'0'));
606       __ cmp(eax, '9' - '0');
607       BranchOrBacktrack(below_equal, on_no_match);
608       return true;
609     case StandardCharacterSet::kLineTerminator:
610       // Match newlines (0x0A('\n'), 0x0D('\r'), 0x2028 or 0x2029).
611       // The opposite of '.'.
612       __ mov(eax, current_character());
613       __ xor_(eax, Immediate(0x01));
614       // See if current character is '\n'^1 or '\r'^1, i.e., 0x0B or 0x0C.
615       __ sub(eax, Immediate(0x0B));
616       __ cmp(eax, 0x0C - 0x0B);
617       if (mode_ == LATIN1) {
618         BranchOrBacktrack(above, on_no_match);
619       } else {
620         Label done;
621         BranchOrBacktrack(below_equal, &done);
622         DCHECK_EQ(UC16, mode_);
623         // Compare original value to 0x2028 and 0x2029, using the already
624         // computed (current_char ^ 0x01 - 0x0B). I.e., check for
625         // 0x201D (0x2028 - 0x0B) or 0x201E.
626         __ sub(eax, Immediate(0x2028 - 0x0B));
627         __ cmp(eax, 1);
628         BranchOrBacktrack(above, on_no_match);
629         __ bind(&done);
630       }
631       return true;
632     case StandardCharacterSet::kNotLineTerminator: {
633       // Match non-newlines (not 0x0A('\n'), 0x0D('\r'), 0x2028 and 0x2029).
634       __ mov(eax, current_character());
635       __ xor_(eax, Immediate(0x01));
636       // See if current character is '\n'^1 or '\r'^1, i.e., 0x0B or 0x0C.
637       __ sub(eax, Immediate(0x0B));
638       __ cmp(eax, 0x0C - 0x0B);
639       BranchOrBacktrack(below_equal, on_no_match);
640       if (mode_ == UC16) {
641         // Compare original value to 0x2028 and 0x2029, using the already
642         // computed (current_char ^ 0x01 - 0x0B). I.e., check for
643         // 0x201D (0x2028 - 0x0B) or 0x201E.
644         __ sub(eax, Immediate(0x2028 - 0x0B));
645         __ cmp(eax, 0x2029 - 0x2028);
646         BranchOrBacktrack(below_equal, on_no_match);
647       }
648       return true;
649     }
650     case StandardCharacterSet::kWord: {
651       if (mode_ != LATIN1) {
652         // Table is 256 entries, so all Latin1 characters can be tested.
653         __ cmp(current_character(), Immediate('z'));
654         BranchOrBacktrack(above, on_no_match);
655       }
656       DCHECK_EQ(0,
657                 word_character_map[0]);  // Character '\0' is not a word char.
658       ExternalReference word_map = ExternalReference::re_word_character_map();
659       __ test_b(current_character(),
660                 Operand(current_character(), times_1, word_map.address(),
661                         RelocInfo::EXTERNAL_REFERENCE));
662       BranchOrBacktrack(zero, on_no_match);
663       return true;
664     }
665     case StandardCharacterSet::kNotWord: {
666       Label done;
667       if (mode_ != LATIN1) {
668         // Table is 256 entries, so all Latin1 characters can be tested.
669         __ cmp(current_character(), Immediate('z'));
670         __ j(above, &done);
671       }
672       DCHECK_EQ(0,
673                 word_character_map[0]);  // Character '\0' is not a word char.
674       ExternalReference word_map = ExternalReference::re_word_character_map();
675       __ test_b(current_character(),
676                 Operand(current_character(), times_1, word_map.address(),
677                         RelocInfo::EXTERNAL_REFERENCE));
678       BranchOrBacktrack(not_zero, on_no_match);
679       if (mode_ != LATIN1) {
680         __ bind(&done);
681       }
682       return true;
683     }
684   // Non-standard classes (with no syntactic shorthand) used internally.
685   case StandardCharacterSet::kEverything:
686     // Match any character.
687     return true;
688   }
689 }
690 
Fail()691 void RegExpMacroAssemblerIA32::Fail() {
692   STATIC_ASSERT(FAILURE == 0);  // Return value for failure is zero.
693   if (!global()) {
694     __ Move(eax, Immediate(FAILURE));
695   }
696   __ jmp(&exit_label_);
697 }
698 
LoadRegExpStackPointerFromMemory(Register dst)699 void RegExpMacroAssemblerIA32::LoadRegExpStackPointerFromMemory(Register dst) {
700   ExternalReference ref =
701       ExternalReference::address_of_regexp_stack_stack_pointer(isolate());
702   __ mov(dst, __ ExternalReferenceAsOperand(ref, dst));
703 }
704 
StoreRegExpStackPointerToMemory( Register src, Register scratch)705 void RegExpMacroAssemblerIA32::StoreRegExpStackPointerToMemory(
706     Register src, Register scratch) {
707   ExternalReference ref =
708       ExternalReference::address_of_regexp_stack_stack_pointer(isolate());
709   __ mov(__ ExternalReferenceAsOperand(ref, scratch), src);
710 }
711 
PushRegExpBasePointer(Register stack_pointer, Register scratch)712 void RegExpMacroAssemblerIA32::PushRegExpBasePointer(Register stack_pointer,
713                                                      Register scratch) {
714   ExternalReference ref =
715       ExternalReference::address_of_regexp_stack_memory_top_address(isolate());
716   __ mov(scratch, __ ExternalReferenceAsOperand(ref, scratch));
717   __ sub(scratch, stack_pointer);
718   __ mov(Operand(ebp, kRegExpStackBasePointer), scratch);
719 }
720 
PopRegExpBasePointer(Register stack_pointer_out, Register scratch)721 void RegExpMacroAssemblerIA32::PopRegExpBasePointer(Register stack_pointer_out,
722                                                     Register scratch) {
723   ExternalReference ref =
724       ExternalReference::address_of_regexp_stack_memory_top_address(isolate());
725   __ mov(scratch, Operand(ebp, kRegExpStackBasePointer));
726   __ mov(stack_pointer_out,
727          __ ExternalReferenceAsOperand(ref, stack_pointer_out));
728   __ sub(stack_pointer_out, scratch);
729   StoreRegExpStackPointerToMemory(stack_pointer_out, scratch);
730 }
731 
GetCode(Handle<String> source)732 Handle<HeapObject> RegExpMacroAssemblerIA32::GetCode(Handle<String> source) {
733   Label return_eax;
734   // Finalize code - write the entry point code now we know how many
735   // registers we need.
736 
737   // Entry code:
738   __ bind(&entry_label_);
739 
740   // Tell the system that we have a stack frame.  Because the type is MANUAL, no
741   // code is generated.
742   FrameScope scope(masm_.get(), StackFrame::MANUAL);
743 
744   // Actually emit code to start a new stack frame.
745   __ push(ebp);
746   __ mov(ebp, esp);
747   // Save callee-save registers. Order here should correspond to order of
748   // kBackup_ebx etc.
749   __ push(esi);
750   __ push(edi);
751   __ push(ebx);  // Callee-save on MacOS.
752   STATIC_ASSERT(kLastCalleeSaveRegister == kBackup_ebx);
753 
754   STATIC_ASSERT(kSuccessfulCaptures ==
755                 kLastCalleeSaveRegister - kSystemPointerSize);
756   __ push(Immediate(0));  // Number of successful matches in a global regexp.
757   STATIC_ASSERT(kStringStartMinusOne ==
758                 kSuccessfulCaptures - kSystemPointerSize);
759   __ push(Immediate(0));  // Make room for "string start - 1" constant.
760   STATIC_ASSERT(kBacktrackCount == kStringStartMinusOne - kSystemPointerSize);
761   __ push(Immediate(0));  // The backtrack counter.
762   STATIC_ASSERT(kRegExpStackBasePointer ==
763                 kBacktrackCount - kSystemPointerSize);
764   __ push(Immediate(0));  // The regexp stack base ptr.
765 
766   // Initialize backtrack stack pointer. It must not be clobbered from here on.
767   // Note the backtrack_stackpointer is *not* callee-saved.
768   STATIC_ASSERT(backtrack_stackpointer() == ecx);
769   LoadRegExpStackPointerFromMemory(backtrack_stackpointer());
770 
771   // Store the regexp base pointer - we'll later restore it / write it to
772   // memory when returning from this irregexp code object.
773   PushRegExpBasePointer(backtrack_stackpointer(), eax);
774 
775   {
776     // Check if we have space on the stack for registers.
777     Label stack_limit_hit, stack_ok;
778 
779     ExternalReference stack_limit =
780         ExternalReference::address_of_jslimit(isolate());
781     __ mov(eax, esp);
782     __ sub(eax, StaticVariable(stack_limit));
783     // Handle it if the stack pointer is already below the stack limit.
784     __ j(below_equal, &stack_limit_hit);
785     // Check if there is room for the variable number of registers above
786     // the stack limit.
787     __ cmp(eax, num_registers_ * kSystemPointerSize);
788     __ j(above_equal, &stack_ok);
789     // Exit with OutOfMemory exception. There is not enough space on the stack
790     // for our working registers.
791     __ mov(eax, EXCEPTION);
792     __ jmp(&return_eax);
793 
794     __ bind(&stack_limit_hit);
795     __ push(backtrack_stackpointer());
796     CallCheckStackGuardState(ebx);
797     __ pop(backtrack_stackpointer());
798     __ or_(eax, eax);
799     // If returned value is non-zero, we exit with the returned value as result.
800     __ j(not_zero, &return_eax);
801 
802     __ bind(&stack_ok);
803   }
804 
805   // Load start index for later use.
806   __ mov(ebx, Operand(ebp, kStartIndex));
807 
808   // Allocate space on stack for registers.
809   __ AllocateStackSpace(num_registers_ * kSystemPointerSize);
810   // Load string length.
811   __ mov(esi, Operand(ebp, kInputEnd));
812   // Load input position.
813   __ mov(edi, Operand(ebp, kInputStart));
814   // Set up edi to be negative offset from string end.
815   __ sub(edi, esi);
816 
817   // Set eax to address of char before start of the string.
818   // (effectively string position -1).
819   __ neg(ebx);
820   if (mode_ == UC16) {
821     __ lea(eax, Operand(edi, ebx, times_2, -char_size()));
822   } else {
823     __ lea(eax, Operand(edi, ebx, times_1, -char_size()));
824   }
825   // Store this value in a local variable, for use when clearing
826   // position registers.
827   __ mov(Operand(ebp, kStringStartMinusOne), eax);
828 
829   Label load_char_start_regexp;
830   {
831     Label start_regexp;
832 
833     // Load newline if index is at start, previous character otherwise.
834     __ cmp(Operand(ebp, kStartIndex), Immediate(0));
835     __ j(not_equal, &load_char_start_regexp, Label::kNear);
836     __ mov(current_character(), '\n');
837     __ jmp(&start_regexp, Label::kNear);
838 
839     // Global regexp restarts matching here.
840     __ bind(&load_char_start_regexp);
841     // Load previous char as initial value of current character register.
842     LoadCurrentCharacterUnchecked(-1, 1);
843     __ bind(&start_regexp);
844   }
845 
846   // Initialize on-stack registers.
847   if (num_saved_registers_ > 0) {  // Always is, if generated from a regexp.
848     // Fill saved registers with initial value = start offset - 1
849     // Fill in stack push order, to avoid accessing across an unwritten
850     // page (a problem on Windows).
851     if (num_saved_registers_ > 8) {
852       DCHECK_EQ(ecx, backtrack_stackpointer());
853       __ push(ecx);
854       __ mov(ecx, kRegisterZero);
855       Label init_loop;
856       __ bind(&init_loop);
857       __ mov(Operand(ebp, ecx, times_1, 0), eax);
858       __ sub(ecx, Immediate(kSystemPointerSize));
859       __ cmp(ecx, kRegisterZero - num_saved_registers_ * kSystemPointerSize);
860       __ j(greater, &init_loop);
861       __ pop(ecx);
862     } else {  // Unroll the loop.
863       for (int i = 0; i < num_saved_registers_; i++) {
864         __ mov(register_location(i), eax);
865       }
866     }
867   }
868 
869   __ jmp(&start_label_);
870 
871   // Exit code:
872   if (success_label_.is_linked()) {
873     // Save captures when successful.
874     __ bind(&success_label_);
875     if (num_saved_registers_ > 0) {
876       // copy captures to output
877       __ mov(ebx, Operand(ebp, kRegisterOutput));
878       __ mov(ecx, Operand(ebp, kInputEnd));
879       __ mov(edx, Operand(ebp, kStartIndex));
880       __ sub(ecx, Operand(ebp, kInputStart));
881       if (mode_ == UC16) {
882         __ lea(ecx, Operand(ecx, edx, times_2, 0));
883       } else {
884         __ add(ecx, edx);
885       }
886       for (int i = 0; i < num_saved_registers_; i++) {
887         __ mov(eax, register_location(i));
888         if (i == 0 && global_with_zero_length_check()) {
889           // Keep capture start in edx for the zero-length check later.
890           __ mov(edx, eax);
891         }
892         // Convert to index from start of string, not end.
893         __ add(eax, ecx);
894         if (mode_ == UC16) {
895           __ sar(eax, 1);  // Convert byte index to character index.
896         }
897         __ mov(Operand(ebx, i * kSystemPointerSize), eax);
898       }
899     }
900 
901     if (global()) {
902       // Restart matching if the regular expression is flagged as global.
903       // Increment success counter.
904       __ inc(Operand(ebp, kSuccessfulCaptures));
905       // Capture results have been stored, so the number of remaining global
906       // output registers is reduced by the number of stored captures.
907       __ mov(ecx, Operand(ebp, kNumOutputRegisters));
908       __ sub(ecx, Immediate(num_saved_registers_));
909       // Check whether we have enough room for another set of capture results.
910       __ cmp(ecx, Immediate(num_saved_registers_));
911       __ j(less, &exit_label_);
912 
913       __ mov(Operand(ebp, kNumOutputRegisters), ecx);
914       // Advance the location for output.
915       __ add(Operand(ebp, kRegisterOutput),
916              Immediate(num_saved_registers_ * kSystemPointerSize));
917 
918       // Prepare eax to initialize registers with its value in the next run.
919       __ mov(eax, Operand(ebp, kStringStartMinusOne));
920 
921       // Restore the original regexp stack pointer value (effectively, pop the
922       // stored base pointer).
923       PopRegExpBasePointer(backtrack_stackpointer(), ebx);
924 
925       if (global_with_zero_length_check()) {
926         // Special case for zero-length matches.
927         // edx: capture start index
928         __ cmp(edi, edx);
929         // Not a zero-length match, restart.
930         __ j(not_equal, &load_char_start_regexp);
931         // edi (offset from the end) is zero if we already reached the end.
932         __ test(edi, edi);
933         __ j(zero, &exit_label_, Label::kNear);
934         // Advance current position after a zero-length match.
935         Label advance;
936         __ bind(&advance);
937         if (mode_ == UC16) {
938           __ add(edi, Immediate(2));
939         } else {
940           __ inc(edi);
941         }
942         if (global_unicode()) CheckNotInSurrogatePair(0, &advance);
943       }
944       __ jmp(&load_char_start_regexp);
945     } else {
946       __ mov(eax, Immediate(SUCCESS));
947     }
948   }
949 
950   __ bind(&exit_label_);
951   if (global()) {
952     // Return the number of successful captures.
953     __ mov(eax, Operand(ebp, kSuccessfulCaptures));
954   }
955 
956   __ bind(&return_eax);
957   // Restore the original regexp stack pointer value (effectively, pop the
958   // stored base pointer).
959   PopRegExpBasePointer(backtrack_stackpointer(), ebx);
960 
961   // Skip esp past regexp registers.
962   __ lea(esp, Operand(ebp, kLastCalleeSaveRegister));
963   // Restore callee-save registers.
964   __ pop(ebx);
965   __ pop(edi);
966   __ pop(esi);
967   // Exit function frame, restore previous one.
968   __ pop(ebp);
969   __ ret(0);
970 
971   // Backtrack code (branch target for conditional backtracks).
972   if (backtrack_label_.is_linked()) {
973     __ bind(&backtrack_label_);
974     Backtrack();
975   }
976 
977   Label exit_with_exception;
978 
979   // Preempt-code
980   if (check_preempt_label_.is_linked()) {
981     SafeCallTarget(&check_preempt_label_);
982 
983     StoreRegExpStackPointerToMemory(backtrack_stackpointer(), edi);
984 
985     __ push(edi);
986 
987     CallCheckStackGuardState(ebx);
988     __ or_(eax, eax);
989     // If returning non-zero, we should end execution with the given
990     // result as return value.
991     __ j(not_zero, &return_eax);
992 
993     __ pop(edi);
994 
995     LoadRegExpStackPointerFromMemory(backtrack_stackpointer());
996 
997     // String might have moved: Reload esi from frame.
998     __ mov(esi, Operand(ebp, kInputEnd));
999     SafeReturn();
1000   }
1001 
1002   // Backtrack stack overflow code.
1003   if (stack_overflow_label_.is_linked()) {
1004     SafeCallTarget(&stack_overflow_label_);
1005     // Reached if the backtrack-stack limit has been hit.
1006 
1007     // Save registers before calling C function.
1008     __ push(esi);
1009     __ push(edi);
1010 
1011     StoreRegExpStackPointerToMemory(backtrack_stackpointer(), edi);
1012 
1013     // Call GrowStack(isolate).
1014     static const int kNumArguments = 1;
1015     __ PrepareCallCFunction(kNumArguments, ebx);
1016     __ mov(Operand(esp, 0 * kSystemPointerSize),
1017            Immediate(ExternalReference::isolate_address(isolate())));
1018     __ CallCFunction(ExternalReference::re_grow_stack(), kNumArguments);
1019     // If return nullptr, we have failed to grow the stack, and
1020     // must exit with a stack-overflow exception.
1021     __ or_(eax, eax);
1022     __ j(equal, &exit_with_exception);
1023     // Otherwise use return value as new stack pointer.
1024     __ mov(backtrack_stackpointer(), eax);
1025     // Restore saved registers and continue.
1026     __ pop(edi);
1027     __ pop(esi);
1028     SafeReturn();
1029   }
1030 
1031   if (exit_with_exception.is_linked()) {
1032     // If any of the code above needed to exit with an exception.
1033     __ bind(&exit_with_exception);
1034     // Exit with Result EXCEPTION(-1) to signal thrown exception.
1035     __ mov(eax, EXCEPTION);
1036     __ jmp(&return_eax);
1037   }
1038 
1039   if (fallback_label_.is_linked()) {
1040     __ bind(&fallback_label_);
1041     __ mov(eax, FALLBACK_TO_EXPERIMENTAL);
1042     __ jmp(&return_eax);
1043   }
1044 
1045   CodeDesc code_desc;
1046   masm_->GetCode(masm_->isolate(), &code_desc);
1047   Handle<Code> code =
1048       Factory::CodeBuilder(isolate(), code_desc, CodeKind::REGEXP)
1049           .set_self_reference(masm_->CodeObject())
1050           .Build();
1051   PROFILE(masm_->isolate(),
1052           RegExpCodeCreateEvent(Handle<AbstractCode>::cast(code), source));
1053   return Handle<HeapObject>::cast(code);
1054 }
1055 
1056 
GoTo(Label* to)1057 void RegExpMacroAssemblerIA32::GoTo(Label* to) {
1058   BranchOrBacktrack(no_condition, to);
1059 }
1060 
1061 
IfRegisterGE(int reg, int comparand, Label* if_ge)1062 void RegExpMacroAssemblerIA32::IfRegisterGE(int reg,
1063                                             int comparand,
1064                                             Label* if_ge) {
1065   __ cmp(register_location(reg), Immediate(comparand));
1066   BranchOrBacktrack(greater_equal, if_ge);
1067 }
1068 
1069 
IfRegisterLT(int reg, int comparand, Label* if_lt)1070 void RegExpMacroAssemblerIA32::IfRegisterLT(int reg,
1071                                             int comparand,
1072                                             Label* if_lt) {
1073   __ cmp(register_location(reg), Immediate(comparand));
1074   BranchOrBacktrack(less, if_lt);
1075 }
1076 
1077 
IfRegisterEqPos(int reg, Label* if_eq)1078 void RegExpMacroAssemblerIA32::IfRegisterEqPos(int reg,
1079                                                Label* if_eq) {
1080   __ cmp(edi, register_location(reg));
1081   BranchOrBacktrack(equal, if_eq);
1082 }
1083 
1084 
1085 RegExpMacroAssembler::IrregexpImplementation
Implementation()1086     RegExpMacroAssemblerIA32::Implementation() {
1087   return kIA32Implementation;
1088 }
1089 
1090 
PopCurrentPosition()1091 void RegExpMacroAssemblerIA32::PopCurrentPosition() {
1092   Pop(edi);
1093 }
1094 
1095 
PopRegister(int register_index)1096 void RegExpMacroAssemblerIA32::PopRegister(int register_index) {
1097   Pop(eax);
1098   __ mov(register_location(register_index), eax);
1099 }
1100 
1101 
PushBacktrack(Label* label)1102 void RegExpMacroAssemblerIA32::PushBacktrack(Label* label) {
1103   Push(Immediate::CodeRelativeOffset(label));
1104   CheckStackLimit();
1105 }
1106 
1107 
PushCurrentPosition()1108 void RegExpMacroAssemblerIA32::PushCurrentPosition() {
1109   Push(edi);
1110 }
1111 
1112 
PushRegister(int register_index, StackCheckFlag check_stack_limit)1113 void RegExpMacroAssemblerIA32::PushRegister(int register_index,
1114                                             StackCheckFlag check_stack_limit) {
1115   __ mov(eax, register_location(register_index));
1116   Push(eax);
1117   if (check_stack_limit) CheckStackLimit();
1118 }
1119 
1120 
ReadCurrentPositionFromRegister(int reg)1121 void RegExpMacroAssemblerIA32::ReadCurrentPositionFromRegister(int reg) {
1122   __ mov(edi, register_location(reg));
1123 }
1124 
WriteStackPointerToRegister(int reg)1125 void RegExpMacroAssemblerIA32::WriteStackPointerToRegister(int reg) {
1126   ExternalReference stack_top_address =
1127       ExternalReference::address_of_regexp_stack_memory_top_address(isolate());
1128   __ mov(eax, __ ExternalReferenceAsOperand(stack_top_address, eax));
1129   __ sub(eax, backtrack_stackpointer());
1130   __ mov(register_location(reg), eax);
1131 }
1132 
ReadStackPointerFromRegister(int reg)1133 void RegExpMacroAssemblerIA32::ReadStackPointerFromRegister(int reg) {
1134   ExternalReference stack_top_address =
1135       ExternalReference::address_of_regexp_stack_memory_top_address(isolate());
1136   __ mov(backtrack_stackpointer(),
1137          __ ExternalReferenceAsOperand(stack_top_address,
1138                                        backtrack_stackpointer()));
1139   __ sub(backtrack_stackpointer(), register_location(reg));
1140 }
1141 
SetCurrentPositionFromEnd(int by)1142 void RegExpMacroAssemblerIA32::SetCurrentPositionFromEnd(int by)  {
1143   Label after_position;
1144   __ cmp(edi, -by * char_size());
1145   __ j(greater_equal, &after_position, Label::kNear);
1146   __ mov(edi, -by * char_size());
1147   // On RegExp code entry (where this operation is used), the character before
1148   // the current position is expected to be already loaded.
1149   // We have advanced the position, so it's safe to read backwards.
1150   LoadCurrentCharacterUnchecked(-1, 1);
1151   __ bind(&after_position);
1152 }
1153 
1154 
SetRegister(int register_index, int to)1155 void RegExpMacroAssemblerIA32::SetRegister(int register_index, int to) {
1156   DCHECK(register_index >= num_saved_registers_);  // Reserved for positions!
1157   __ mov(register_location(register_index), Immediate(to));
1158 }
1159 
1160 
Succeed()1161 bool RegExpMacroAssemblerIA32::Succeed() {
1162   __ jmp(&success_label_);
1163   return global();
1164 }
1165 
1166 
WriteCurrentPositionToRegister(int reg, int cp_offset)1167 void RegExpMacroAssemblerIA32::WriteCurrentPositionToRegister(int reg,
1168                                                               int cp_offset) {
1169   if (cp_offset == 0) {
1170     __ mov(register_location(reg), edi);
1171   } else {
1172     __ lea(eax, Operand(edi, cp_offset * char_size()));
1173     __ mov(register_location(reg), eax);
1174   }
1175 }
1176 
1177 
ClearRegisters(int reg_from, int reg_to)1178 void RegExpMacroAssemblerIA32::ClearRegisters(int reg_from, int reg_to) {
1179   DCHECK(reg_from <= reg_to);
1180   __ mov(eax, Operand(ebp, kStringStartMinusOne));
1181   for (int reg = reg_from; reg <= reg_to; reg++) {
1182     __ mov(register_location(reg), eax);
1183   }
1184 }
1185 
1186 // Private methods:
1187 
CallCheckStackGuardState(Register scratch)1188 void RegExpMacroAssemblerIA32::CallCheckStackGuardState(Register scratch) {
1189   static const int num_arguments = 3;
1190   __ PrepareCallCFunction(num_arguments, scratch);
1191   // RegExp code frame pointer.
1192   __ mov(Operand(esp, 2 * kSystemPointerSize), ebp);
1193   // Code of self.
1194   __ mov(Operand(esp, 1 * kSystemPointerSize), Immediate(masm_->CodeObject()));
1195   // Next address on the stack (will be address of return address).
1196   __ lea(eax, Operand(esp, -kSystemPointerSize));
1197   __ mov(Operand(esp, 0 * kSystemPointerSize), eax);
1198   ExternalReference check_stack_guard =
1199       ExternalReference::re_check_stack_guard_state();
1200   __ CallCFunction(check_stack_guard, num_arguments);
1201 }
1202 
StaticVariable(const ExternalReference& ext)1203 Operand RegExpMacroAssemblerIA32::StaticVariable(const ExternalReference& ext) {
1204   return Operand(ext.address(), RelocInfo::EXTERNAL_REFERENCE);
1205 }
1206 
1207 // Helper function for reading a value out of a stack frame.
1208 template <typename T>
frame_entry(Address re_frame, int frame_offset)1209 static T& frame_entry(Address re_frame, int frame_offset) {
1210   return reinterpret_cast<T&>(Memory<int32_t>(re_frame + frame_offset));
1211 }
1212 
1213 
1214 template <typename T>
frame_entry_address(Address re_frame, int frame_offset)1215 static T* frame_entry_address(Address re_frame, int frame_offset) {
1216   return reinterpret_cast<T*>(re_frame + frame_offset);
1217 }
1218 
CheckStackGuardState(Address* return_address, Address raw_code, Address re_frame)1219 int RegExpMacroAssemblerIA32::CheckStackGuardState(Address* return_address,
1220                                                    Address raw_code,
1221                                                    Address re_frame) {
1222   Code re_code = Code::cast(Object(raw_code));
1223   return NativeRegExpMacroAssembler::CheckStackGuardState(
1224       frame_entry<Isolate*>(re_frame, kIsolate),
1225       frame_entry<int>(re_frame, kStartIndex),
1226       static_cast<RegExp::CallOrigin>(frame_entry<int>(re_frame, kDirectCall)),
1227       return_address, re_code,
1228       frame_entry_address<Address>(re_frame, kInputString),
1229       frame_entry_address<const byte*>(re_frame, kInputStart),
1230       frame_entry_address<const byte*>(re_frame, kInputEnd));
1231 }
1232 
1233 
register_location(int register_index)1234 Operand RegExpMacroAssemblerIA32::register_location(int register_index) {
1235   DCHECK(register_index < (1<<30));
1236   if (num_registers_ <= register_index) {
1237     num_registers_ = register_index + 1;
1238   }
1239   return Operand(ebp, kRegisterZero - register_index * kSystemPointerSize);
1240 }
1241 
1242 
1243 void RegExpMacroAssemblerIA32::CheckPosition(int cp_offset,
1244                                              Label* on_outside_input) {
1245   if (cp_offset >= 0) {
1246     __ cmp(edi, -cp_offset * char_size());
1247     BranchOrBacktrack(greater_equal, on_outside_input);
1248   } else {
1249     __ lea(eax, Operand(edi, cp_offset * char_size()));
1250     __ cmp(eax, Operand(ebp, kStringStartMinusOne));
1251     BranchOrBacktrack(less_equal, on_outside_input);
1252   }
1253 }
1254 
1255 
1256 void RegExpMacroAssemblerIA32::BranchOrBacktrack(Condition condition,
1257                                                  Label* to) {
1258   if (condition < 0) {  // No condition
1259     if (to == nullptr) {
1260       Backtrack();
1261       return;
1262     }
1263     __ jmp(to);
1264     return;
1265   }
1266   if (to == nullptr) {
1267     __ j(condition, &backtrack_label_);
1268     return;
1269   }
1270   __ j(condition, to);
1271 }
1272 
1273 
1274 void RegExpMacroAssemblerIA32::SafeCall(Label* to) {
1275   Label return_to;
1276   __ push(Immediate::CodeRelativeOffset(&return_to));
1277   __ jmp(to);
1278   __ bind(&return_to);
1279 }
1280 
1281 
1282 void RegExpMacroAssemblerIA32::SafeReturn() {
1283   __ pop(ebx);
1284   __ add(ebx, Immediate(masm_->CodeObject()));
1285   __ jmp(ebx);
1286 }
1287 
1288 
1289 void RegExpMacroAssemblerIA32::SafeCallTarget(Label* name) {
1290   __ bind(name);
1291 }
1292 
1293 
1294 void RegExpMacroAssemblerIA32::Push(Register source) {
1295   DCHECK(source != backtrack_stackpointer());
1296   // Notice: This updates flags, unlike normal Push.
1297   __ sub(backtrack_stackpointer(), Immediate(kSystemPointerSize));
1298   __ mov(Operand(backtrack_stackpointer(), 0), source);
1299 }
1300 
1301 
1302 void RegExpMacroAssemblerIA32::Push(Immediate value) {
1303   // Notice: This updates flags, unlike normal Push.
1304   __ sub(backtrack_stackpointer(), Immediate(kSystemPointerSize));
1305   __ mov(Operand(backtrack_stackpointer(), 0), value);
1306 }
1307 
1308 
1309 void RegExpMacroAssemblerIA32::Pop(Register target) {
1310   DCHECK(target != backtrack_stackpointer());
1311   __ mov(target, Operand(backtrack_stackpointer(), 0));
1312   // Notice: This updates flags, unlike normal Pop.
1313   __ add(backtrack_stackpointer(), Immediate(kSystemPointerSize));
1314 }
1315 
1316 
1317 void RegExpMacroAssemblerIA32::CheckPreemption() {
1318   // Check for preemption.
1319   Label no_preempt;
1320   ExternalReference stack_limit =
1321       ExternalReference::address_of_jslimit(isolate());
1322   __ cmp(esp, StaticVariable(stack_limit));
1323   __ j(above, &no_preempt);
1324 
1325   SafeCall(&check_preempt_label_);
1326 
1327   __ bind(&no_preempt);
1328 }
1329 
1330 
1331 void RegExpMacroAssemblerIA32::CheckStackLimit() {
1332   Label no_stack_overflow;
1333   ExternalReference stack_limit =
1334       ExternalReference::address_of_regexp_stack_limit_address(isolate());
1335   __ cmp(backtrack_stackpointer(), StaticVariable(stack_limit));
1336   __ j(above, &no_stack_overflow);
1337 
1338   SafeCall(&stack_overflow_label_);
1339 
1340   __ bind(&no_stack_overflow);
1341 }
1342 
1343 
1344 void RegExpMacroAssemblerIA32::LoadCurrentCharacterUnchecked(int cp_offset,
1345                                                              int characters) {
1346   if (mode_ == LATIN1) {
1347     if (characters == 4) {
1348       __ mov(current_character(), Operand(esi, edi, times_1, cp_offset));
1349     } else if (characters == 2) {
1350       __ movzx_w(current_character(), Operand(esi, edi, times_1, cp_offset));
1351     } else {
1352       DCHECK_EQ(1, characters);
1353       __ movzx_b(current_character(), Operand(esi, edi, times_1, cp_offset));
1354     }
1355   } else {
1356     DCHECK(mode_ == UC16);
1357     if (characters == 2) {
1358       __ mov(current_character(),
1359              Operand(esi, edi, times_1, cp_offset * sizeof(base::uc16)));
1360     } else {
1361       DCHECK_EQ(1, characters);
1362       __ movzx_w(current_character(),
1363                  Operand(esi, edi, times_1, cp_offset * sizeof(base::uc16)));
1364     }
1365   }
1366 }
1367 
1368 
1369 #undef __
1370 
1371 }  // namespace internal
1372 }  // namespace v8
1373 
1374 #endif  // V8_TARGET_ARCH_IA32
1375