v8  3.14.5(node0.10.28)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
regexp-macro-assembler-ia32.cc
Go to the documentation of this file.
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 #include "v8.h"
29 
30 #if defined(V8_TARGET_ARCH_IA32)
31 
32 #include "unicode.h"
33 #include "log.h"
34 #include "regexp-stack.h"
35 #include "macro-assembler.h"
36 #include "regexp-macro-assembler.h"
38 
39 namespace v8 {
40 namespace internal {
41 
42 #ifndef V8_INTERPRETED_REGEXP
43 /*
44  * This assembler uses the following register assignment convention
45  * - edx : Current character. Must be loaded using LoadCurrentCharacter
46  * before using any of the dispatch methods. Temporarily stores the
47  * index of capture start after a matching pass for a global regexp.
48  * - edi : Current position in input, as negative offset from end of string.
49  * Please notice that this is the byte offset, not the character offset!
50  * - esi : end of input (points to byte after last character in input).
51  * - ebp : Frame pointer. Used to access arguments, local variables and
52  * RegExp registers.
53  * - esp : Points to tip of C stack.
54  * - ecx : Points to tip of backtrack stack
55  *
56  * The registers eax and ebx are free to use for computations.
57  *
58  * Each call to a public method should retain this convention.
59  * The stack will have the following structure:
60  * - Isolate* isolate (address of the current isolate)
61  * - direct_call (if 1, direct call from JavaScript code, if 0
62  * call through the runtime system)
63  * - stack_area_base (high end of the memory area to use as
64  * backtracking stack)
65  * - capture array size (may fit multiple sets of matches)
66  * - int* capture_array (int[num_saved_registers_], for output).
67  * - end of input (address of end of string)
68  * - start of input (address of first character in string)
69  * - start index (character index of start)
70  * - String* input_string (location of a handle containing the string)
71  * --- frame alignment (if applicable) ---
72  * - return address
73  * ebp-> - old ebp
74  * - backup of caller esi
75  * - backup of caller edi
76  * - backup of caller ebx
77  * - success counter (only for global regexps to count matches).
78  * - Offset of location before start of input (effectively character
79  * position -1). Used to initialize capture registers to a non-position.
80  * - register 0 ebp[-4] (only positions must be stored in the first
81  * - register 1 ebp[-8] num_saved_registers_ registers)
82  * - ...
83  *
84  * The first num_saved_registers_ registers are initialized to point to
85  * "character -1" in the string (i.e., char_size() bytes before the first
86  * character of the string). The remaining registers starts out as garbage.
87  *
88  * The data up to the return address must be placed there by the calling
89  * code, by calling the code entry as cast to a function with the signature:
90  * int (*match)(String* input_string,
91  * int start_index,
92  * Address start,
93  * Address end,
94  * int* capture_output_array,
95  * bool at_start,
96  * byte* stack_area_base,
97  * bool direct_call)
98  */
99 
100 #define __ ACCESS_MASM(masm_)
101 
103  Mode mode,
104  int registers_to_save,
105  Zone* zone)
106  : NativeRegExpMacroAssembler(zone),
107  masm_(new MacroAssembler(Isolate::Current(), NULL, kRegExpCodeSize)),
108  mode_(mode),
109  num_registers_(registers_to_save),
110  num_saved_registers_(registers_to_save),
111  entry_label_(),
112  start_label_(),
113  success_label_(),
114  backtrack_label_(),
115  exit_label_() {
116  ASSERT_EQ(0, registers_to_save % 2);
117  __ jmp(&entry_label_); // We'll write the entry code later.
118  __ bind(&start_label_); // And then continue from here.
119 }
120 
121 
122 RegExpMacroAssemblerIA32::~RegExpMacroAssemblerIA32() {
123  delete masm_;
124  // Unuse labels in case we throw away the assembler without calling GetCode.
125  entry_label_.Unuse();
126  start_label_.Unuse();
127  success_label_.Unuse();
128  backtrack_label_.Unuse();
129  exit_label_.Unuse();
130  check_preempt_label_.Unuse();
131  stack_overflow_label_.Unuse();
132 }
133 
134 
135 int RegExpMacroAssemblerIA32::stack_limit_slack() {
136  return RegExpStack::kStackLimitSlack;
137 }
138 
139 
140 void RegExpMacroAssemblerIA32::AdvanceCurrentPosition(int by) {
141  if (by != 0) {
142  __ add(edi, Immediate(by * char_size()));
143  }
144 }
145 
146 
147 void RegExpMacroAssemblerIA32::AdvanceRegister(int reg, int by) {
148  ASSERT(reg >= 0);
149  ASSERT(reg < num_registers_);
150  if (by != 0) {
151  __ add(register_location(reg), Immediate(by));
152  }
153 }
154 
155 
156 void RegExpMacroAssemblerIA32::Backtrack() {
157  CheckPreemption();
158  // Pop Code* offset from backtrack stack, add Code* and jump to location.
159  Pop(ebx);
160  __ add(ebx, Immediate(masm_->CodeObject()));
161  __ jmp(ebx);
162 }
163 
164 
165 void RegExpMacroAssemblerIA32::Bind(Label* label) {
166  __ bind(label);
167 }
168 
169 
170 void RegExpMacroAssemblerIA32::CheckCharacter(uint32_t c, Label* on_equal) {
171  __ cmp(current_character(), c);
172  BranchOrBacktrack(equal, on_equal);
173 }
174 
175 
176 void RegExpMacroAssemblerIA32::CheckCharacterGT(uc16 limit, Label* on_greater) {
177  __ cmp(current_character(), limit);
178  BranchOrBacktrack(greater, on_greater);
179 }
180 
181 
182 void RegExpMacroAssemblerIA32::CheckAtStart(Label* on_at_start) {
183  Label not_at_start;
184  // Did we start the match at the start of the string at all?
185  __ cmp(Operand(ebp, kStartIndex), Immediate(0));
186  BranchOrBacktrack(not_equal, &not_at_start);
187  // If we did, are we still at the start of the input?
188  __ lea(eax, Operand(esi, edi, times_1, 0));
189  __ cmp(eax, Operand(ebp, kInputStart));
190  BranchOrBacktrack(equal, on_at_start);
191  __ bind(&not_at_start);
192 }
193 
194 
195 void RegExpMacroAssemblerIA32::CheckNotAtStart(Label* on_not_at_start) {
196  // Did we start the match at the start of the string at all?
197  __ cmp(Operand(ebp, kStartIndex), Immediate(0));
198  BranchOrBacktrack(not_equal, on_not_at_start);
199  // If we did, are we still at the start of the input?
200  __ lea(eax, Operand(esi, edi, times_1, 0));
201  __ cmp(eax, Operand(ebp, kInputStart));
202  BranchOrBacktrack(not_equal, on_not_at_start);
203 }
204 
205 
206 void RegExpMacroAssemblerIA32::CheckCharacterLT(uc16 limit, Label* on_less) {
207  __ cmp(current_character(), limit);
208  BranchOrBacktrack(less, on_less);
209 }
210 
211 
212 void RegExpMacroAssemblerIA32::CheckCharacters(Vector<const uc16> str,
213  int cp_offset,
214  Label* on_failure,
215  bool check_end_of_string) {
216 #ifdef DEBUG
217  // If input is ASCII, don't even bother calling here if the string to
218  // match contains a non-ASCII character.
219  if (mode_ == ASCII) {
220  ASSERT(String::IsAscii(str.start(), str.length()));
221  }
222 #endif
223  int byte_length = str.length() * char_size();
224  int byte_offset = cp_offset * char_size();
225  if (check_end_of_string) {
226  // Check that there are at least str.length() characters left in the input.
227  __ cmp(edi, Immediate(-(byte_offset + byte_length)));
228  BranchOrBacktrack(greater, on_failure);
229  }
230 
231  if (on_failure == NULL) {
232  // Instead of inlining a backtrack, (re)use the global backtrack target.
233  on_failure = &backtrack_label_;
234  }
235 
236  // Do one character test first to minimize loading for the case that
237  // we don't match at all (loading more than one character introduces that
238  // chance of reading unaligned and reading across cache boundaries).
239  // If the first character matches, expect a larger chance of matching the
240  // string, and start loading more characters at a time.
241  if (mode_ == ASCII) {
242  __ cmpb(Operand(esi, edi, times_1, byte_offset),
243  static_cast<int8_t>(str[0]));
244  } else {
245  // Don't use 16-bit immediate. The size changing prefix throws off
246  // pre-decoding.
247  __ movzx_w(eax,
248  Operand(esi, edi, times_1, byte_offset));
249  __ cmp(eax, static_cast<int32_t>(str[0]));
250  }
251  BranchOrBacktrack(not_equal, on_failure);
252 
253  __ lea(ebx, Operand(esi, edi, times_1, 0));
254  for (int i = 1, n = str.length(); i < n;) {
255  if (mode_ == ASCII) {
256  if (i <= n - 4) {
257  int combined_chars =
258  (static_cast<uint32_t>(str[i + 0]) << 0) |
259  (static_cast<uint32_t>(str[i + 1]) << 8) |
260  (static_cast<uint32_t>(str[i + 2]) << 16) |
261  (static_cast<uint32_t>(str[i + 3]) << 24);
262  __ cmp(Operand(ebx, byte_offset + i), Immediate(combined_chars));
263  i += 4;
264  } else {
265  __ cmpb(Operand(ebx, byte_offset + i),
266  static_cast<int8_t>(str[i]));
267  i += 1;
268  }
269  } else {
270  ASSERT(mode_ == UC16);
271  if (i <= n - 2) {
272  __ cmp(Operand(ebx, byte_offset + i * sizeof(uc16)),
273  Immediate(*reinterpret_cast<const int*>(&str[i])));
274  i += 2;
275  } else {
276  // Avoid a 16-bit immediate operation. It uses the length-changing
277  // 0x66 prefix which causes pre-decoder misprediction and pipeline
278  // stalls. See
279  // "Intel(R) 64 and IA-32 Architectures Optimization Reference Manual"
280  // (248966.pdf) section 3.4.2.3 "Length-Changing Prefixes (LCP)"
281  __ movzx_w(eax,
282  Operand(ebx, byte_offset + i * sizeof(uc16)));
283  __ cmp(eax, static_cast<int32_t>(str[i]));
284  i += 1;
285  }
286  }
287  BranchOrBacktrack(not_equal, on_failure);
288  }
289 }
290 
291 
292 void RegExpMacroAssemblerIA32::CheckGreedyLoop(Label* on_equal) {
293  Label fallthrough;
294  __ cmp(edi, Operand(backtrack_stackpointer(), 0));
295  __ j(not_equal, &fallthrough);
296  __ add(backtrack_stackpointer(), Immediate(kPointerSize)); // Pop.
297  BranchOrBacktrack(no_condition, on_equal);
298  __ bind(&fallthrough);
299 }
300 
301 
302 void RegExpMacroAssemblerIA32::CheckNotBackReferenceIgnoreCase(
303  int start_reg,
304  Label* on_no_match) {
305  Label fallthrough;
306  __ mov(edx, register_location(start_reg)); // Index of start of capture
307  __ mov(ebx, register_location(start_reg + 1)); // Index of end of capture
308  __ sub(ebx, edx); // Length of capture.
309 
310  // The length of a capture should not be negative. This can only happen
311  // if the end of the capture is unrecorded, or at a point earlier than
312  // the start of the capture.
313  BranchOrBacktrack(less, on_no_match);
314 
315  // If length is zero, either the capture is empty or it is completely
316  // uncaptured. In either case succeed immediately.
317  __ j(equal, &fallthrough);
318 
319  // Check that there are sufficient characters left in the input.
320  __ mov(eax, edi);
321  __ add(eax, ebx);
322  BranchOrBacktrack(greater, on_no_match);
323 
324  if (mode_ == ASCII) {
325  Label success;
326  Label fail;
327  Label loop_increment;
328  // Save register contents to make the registers available below.
329  __ push(edi);
330  __ push(backtrack_stackpointer());
331  // After this, the eax, ecx, and edi registers are available.
332 
333  __ add(edx, esi); // Start of capture
334  __ add(edi, esi); // Start of text to match against capture.
335  __ add(ebx, edi); // End of text to match against capture.
336 
337  Label loop;
338  __ bind(&loop);
339  __ movzx_b(eax, Operand(edi, 0));
340  __ cmpb_al(Operand(edx, 0));
341  __ j(equal, &loop_increment);
342 
343  // Mismatch, try case-insensitive match (converting letters to lower-case).
344  __ or_(eax, 0x20); // Convert match character to lower-case.
345  __ lea(ecx, Operand(eax, -'a'));
346  __ cmp(ecx, static_cast<int32_t>('z' - 'a')); // Is eax a lowercase letter?
347  __ j(above, &fail);
348  // Also convert capture character.
349  __ movzx_b(ecx, Operand(edx, 0));
350  __ or_(ecx, 0x20);
351 
352  __ cmp(eax, ecx);
353  __ j(not_equal, &fail);
354 
355  __ bind(&loop_increment);
356  // Increment pointers into match and capture strings.
357  __ add(edx, Immediate(1));
358  __ add(edi, Immediate(1));
359  // Compare to end of match, and loop if not done.
360  __ cmp(edi, ebx);
361  __ j(below, &loop);
362  __ jmp(&success);
363 
364  __ bind(&fail);
365  // Restore original values before failing.
366  __ pop(backtrack_stackpointer());
367  __ pop(edi);
368  BranchOrBacktrack(no_condition, on_no_match);
369 
370  __ bind(&success);
371  // Restore original value before continuing.
372  __ pop(backtrack_stackpointer());
373  // Drop original value of character position.
374  __ add(esp, Immediate(kPointerSize));
375  // Compute new value of character position after the matched part.
376  __ sub(edi, esi);
377  } else {
378  ASSERT(mode_ == UC16);
379  // Save registers before calling C function.
380  __ push(esi);
381  __ push(edi);
382  __ push(backtrack_stackpointer());
383  __ push(ebx);
384 
385  static const int argument_count = 4;
386  __ PrepareCallCFunction(argument_count, ecx);
387  // Put arguments into allocated stack area, last argument highest on stack.
388  // Parameters are
389  // Address byte_offset1 - Address captured substring's start.
390  // Address byte_offset2 - Address of current character position.
391  // size_t byte_length - length of capture in bytes(!)
392  // Isolate* isolate
393 
394  // Set isolate.
395  __ mov(Operand(esp, 3 * kPointerSize),
396  Immediate(ExternalReference::isolate_address()));
397  // Set byte_length.
398  __ mov(Operand(esp, 2 * kPointerSize), ebx);
399  // Set byte_offset2.
400  // Found by adding negative string-end offset of current position (edi)
401  // to end of string.
402  __ add(edi, esi);
403  __ mov(Operand(esp, 1 * kPointerSize), edi);
404  // Set byte_offset1.
405  // Start of capture, where edx already holds string-end negative offset.
406  __ add(edx, esi);
407  __ mov(Operand(esp, 0 * kPointerSize), edx);
408 
409  {
410  AllowExternalCallThatCantCauseGC scope(masm_);
411  ExternalReference compare =
412  ExternalReference::re_case_insensitive_compare_uc16(masm_->isolate());
413  __ CallCFunction(compare, argument_count);
414  }
415  // Pop original values before reacting on result value.
416  __ pop(ebx);
417  __ pop(backtrack_stackpointer());
418  __ pop(edi);
419  __ pop(esi);
420 
421  // Check if function returned non-zero for success or zero for failure.
422  __ or_(eax, eax);
423  BranchOrBacktrack(zero, on_no_match);
424  // On success, increment position by length of capture.
425  __ add(edi, ebx);
426  }
427  __ bind(&fallthrough);
428 }
429 
430 
431 void RegExpMacroAssemblerIA32::CheckNotBackReference(
432  int start_reg,
433  Label* on_no_match) {
434  Label fallthrough;
435  Label success;
436  Label fail;
437 
438  // Find length of back-referenced capture.
439  __ mov(edx, register_location(start_reg));
440  __ mov(eax, register_location(start_reg + 1));
441  __ sub(eax, edx); // Length to check.
442  // Fail on partial or illegal capture (start of capture after end of capture).
443  BranchOrBacktrack(less, on_no_match);
444  // Succeed on empty capture (including no capture)
445  __ j(equal, &fallthrough);
446 
447  // Check that there are sufficient characters left in the input.
448  __ mov(ebx, edi);
449  __ add(ebx, eax);
450  BranchOrBacktrack(greater, on_no_match);
451 
452  // Save register to make it available below.
453  __ push(backtrack_stackpointer());
454 
455  // Compute pointers to match string and capture string
456  __ lea(ebx, Operand(esi, edi, times_1, 0)); // Start of match.
457  __ add(edx, esi); // Start of capture.
458  __ lea(ecx, Operand(eax, ebx, times_1, 0)); // End of match
459 
460  Label loop;
461  __ bind(&loop);
462  if (mode_ == ASCII) {
463  __ movzx_b(eax, Operand(edx, 0));
464  __ cmpb_al(Operand(ebx, 0));
465  } else {
466  ASSERT(mode_ == UC16);
467  __ movzx_w(eax, Operand(edx, 0));
468  __ cmpw_ax(Operand(ebx, 0));
469  }
470  __ j(not_equal, &fail);
471  // Increment pointers into capture and match string.
472  __ add(edx, Immediate(char_size()));
473  __ add(ebx, Immediate(char_size()));
474  // Check if we have reached end of match area.
475  __ cmp(ebx, ecx);
476  __ j(below, &loop);
477  __ jmp(&success);
478 
479  __ bind(&fail);
480  // Restore backtrack stackpointer.
481  __ pop(backtrack_stackpointer());
482  BranchOrBacktrack(no_condition, on_no_match);
483 
484  __ bind(&success);
485  // Move current character position to position after match.
486  __ mov(edi, ecx);
487  __ sub(edi, esi);
488  // Restore backtrack stackpointer.
489  __ pop(backtrack_stackpointer());
490 
491  __ bind(&fallthrough);
492 }
493 
494 
495 void RegExpMacroAssemblerIA32::CheckNotCharacter(uint32_t c,
496  Label* on_not_equal) {
497  __ cmp(current_character(), c);
498  BranchOrBacktrack(not_equal, on_not_equal);
499 }
500 
501 
502 void RegExpMacroAssemblerIA32::CheckCharacterAfterAnd(uint32_t c,
503  uint32_t mask,
504  Label* on_equal) {
505  if (c == 0) {
506  __ test(current_character(), Immediate(mask));
507  } else {
508  __ mov(eax, mask);
509  __ and_(eax, current_character());
510  __ cmp(eax, c);
511  }
512  BranchOrBacktrack(equal, on_equal);
513 }
514 
515 
516 void RegExpMacroAssemblerIA32::CheckNotCharacterAfterAnd(uint32_t c,
517  uint32_t mask,
518  Label* on_not_equal) {
519  if (c == 0) {
520  __ test(current_character(), Immediate(mask));
521  } else {
522  __ mov(eax, mask);
523  __ and_(eax, current_character());
524  __ cmp(eax, c);
525  }
526  BranchOrBacktrack(not_equal, on_not_equal);
527 }
528 
529 
530 void RegExpMacroAssemblerIA32::CheckNotCharacterAfterMinusAnd(
531  uc16 c,
532  uc16 minus,
533  uc16 mask,
534  Label* on_not_equal) {
535  ASSERT(minus < String::kMaxUtf16CodeUnit);
536  __ lea(eax, Operand(current_character(), -minus));
537  if (c == 0) {
538  __ test(eax, Immediate(mask));
539  } else {
540  __ and_(eax, mask);
541  __ cmp(eax, c);
542  }
543  BranchOrBacktrack(not_equal, on_not_equal);
544 }
545 
546 
547 void RegExpMacroAssemblerIA32::CheckCharacterInRange(
548  uc16 from,
549  uc16 to,
550  Label* on_in_range) {
551  __ lea(eax, Operand(current_character(), -from));
552  __ cmp(eax, to - from);
553  BranchOrBacktrack(below_equal, on_in_range);
554 }
555 
556 
557 void RegExpMacroAssemblerIA32::CheckCharacterNotInRange(
558  uc16 from,
559  uc16 to,
560  Label* on_not_in_range) {
561  __ lea(eax, Operand(current_character(), -from));
562  __ cmp(eax, to - from);
563  BranchOrBacktrack(above, on_not_in_range);
564 }
565 
566 
567 void RegExpMacroAssemblerIA32::CheckBitInTable(
568  Handle<ByteArray> table,
569  Label* on_bit_set) {
570  __ mov(eax, Immediate(table));
571  Register index = current_character();
572  if (mode_ != ASCII || kTableMask != String::kMaxAsciiCharCode) {
573  __ mov(ebx, kTableSize - 1);
574  __ and_(ebx, current_character());
575  index = ebx;
576  }
577  __ cmpb(FieldOperand(eax, index, times_1, ByteArray::kHeaderSize), 0);
578  BranchOrBacktrack(not_equal, on_bit_set);
579 }
580 
581 
582 bool RegExpMacroAssemblerIA32::CheckSpecialCharacterClass(uc16 type,
583  Label* on_no_match) {
584  // Range checks (c in min..max) are generally implemented by an unsigned
585  // (c - min) <= (max - min) check
586  switch (type) {
587  case 's':
588  // Match space-characters
589  if (mode_ == ASCII) {
590  // ASCII space characters are '\t'..'\r' and ' '.
591  Label success;
592  __ cmp(current_character(), ' ');
593  __ j(equal, &success);
594  // Check range 0x09..0x0d
595  __ lea(eax, Operand(current_character(), -'\t'));
596  __ cmp(eax, '\r' - '\t');
597  BranchOrBacktrack(above, on_no_match);
598  __ bind(&success);
599  return true;
600  }
601  return false;
602  case 'S':
603  // Match non-space characters.
604  if (mode_ == ASCII) {
605  // ASCII space characters are '\t'..'\r' and ' '.
606  __ cmp(current_character(), ' ');
607  BranchOrBacktrack(equal, on_no_match);
608  __ lea(eax, Operand(current_character(), -'\t'));
609  __ cmp(eax, '\r' - '\t');
610  BranchOrBacktrack(below_equal, on_no_match);
611  return true;
612  }
613  return false;
614  case 'd':
615  // Match ASCII digits ('0'..'9')
616  __ lea(eax, Operand(current_character(), -'0'));
617  __ cmp(eax, '9' - '0');
618  BranchOrBacktrack(above, on_no_match);
619  return true;
620  case 'D':
621  // Match non ASCII-digits
622  __ lea(eax, Operand(current_character(), -'0'));
623  __ cmp(eax, '9' - '0');
624  BranchOrBacktrack(below_equal, on_no_match);
625  return true;
626  case '.': {
627  // Match non-newlines (not 0x0a('\n'), 0x0d('\r'), 0x2028 and 0x2029)
628  __ mov(eax, current_character());
629  __ xor_(eax, Immediate(0x01));
630  // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c
631  __ sub(eax, Immediate(0x0b));
632  __ cmp(eax, 0x0c - 0x0b);
633  BranchOrBacktrack(below_equal, on_no_match);
634  if (mode_ == UC16) {
635  // Compare original value to 0x2028 and 0x2029, using the already
636  // computed (current_char ^ 0x01 - 0x0b). I.e., check for
637  // 0x201d (0x2028 - 0x0b) or 0x201e.
638  __ sub(eax, Immediate(0x2028 - 0x0b));
639  __ cmp(eax, 0x2029 - 0x2028);
640  BranchOrBacktrack(below_equal, on_no_match);
641  }
642  return true;
643  }
644  case 'w': {
645  if (mode_ != ASCII) {
646  // Table is 128 entries, so all ASCII characters can be tested.
647  __ cmp(current_character(), Immediate('z'));
648  BranchOrBacktrack(above, on_no_match);
649  }
650  ASSERT_EQ(0, word_character_map[0]); // Character '\0' is not a word char.
651  ExternalReference word_map = ExternalReference::re_word_character_map();
652  __ test_b(current_character(),
653  Operand::StaticArray(current_character(), times_1, word_map));
654  BranchOrBacktrack(zero, on_no_match);
655  return true;
656  }
657  case 'W': {
658  Label done;
659  if (mode_ != ASCII) {
660  // Table is 128 entries, so all ASCII characters can be tested.
661  __ cmp(current_character(), Immediate('z'));
662  __ j(above, &done);
663  }
664  ASSERT_EQ(0, word_character_map[0]); // Character '\0' is not a word char.
665  ExternalReference word_map = ExternalReference::re_word_character_map();
666  __ test_b(current_character(),
667  Operand::StaticArray(current_character(), times_1, word_map));
668  BranchOrBacktrack(not_zero, on_no_match);
669  if (mode_ != ASCII) {
670  __ bind(&done);
671  }
672  return true;
673  }
674  // Non-standard classes (with no syntactic shorthand) used internally.
675  case '*':
676  // Match any character.
677  return true;
678  case 'n': {
679  // Match newlines (0x0a('\n'), 0x0d('\r'), 0x2028 or 0x2029).
680  // The opposite of '.'.
681  __ mov(eax, current_character());
682  __ xor_(eax, Immediate(0x01));
683  // See if current character is '\n'^1 or '\r'^1, i.e., 0x0b or 0x0c
684  __ sub(eax, Immediate(0x0b));
685  __ cmp(eax, 0x0c - 0x0b);
686  if (mode_ == ASCII) {
687  BranchOrBacktrack(above, on_no_match);
688  } else {
689  Label done;
690  BranchOrBacktrack(below_equal, &done);
691  ASSERT_EQ(UC16, mode_);
692  // Compare original value to 0x2028 and 0x2029, using the already
693  // computed (current_char ^ 0x01 - 0x0b). I.e., check for
694  // 0x201d (0x2028 - 0x0b) or 0x201e.
695  __ sub(eax, Immediate(0x2028 - 0x0b));
696  __ cmp(eax, 1);
697  BranchOrBacktrack(above, on_no_match);
698  __ bind(&done);
699  }
700  return true;
701  }
702  // No custom implementation (yet): s(UC16), S(UC16).
703  default:
704  return false;
705  }
706 }
707 
708 
710  STATIC_ASSERT(FAILURE == 0); // Return value for failure is zero.
711  if (!global()) {
712  __ Set(eax, Immediate(FAILURE));
713  }
714  __ jmp(&exit_label_);
715 }
716 
717 
718 Handle<HeapObject> RegExpMacroAssemblerIA32::GetCode(Handle<String> source) {
719  Label return_eax;
720  // Finalize code - write the entry point code now we know how many
721  // registers we need.
722 
723  // Entry code:
724  __ bind(&entry_label_);
725 
726  // Tell the system that we have a stack frame. Because the type is MANUAL, no
727  // code is generated.
728  FrameScope scope(masm_, StackFrame::MANUAL);
729 
730  // Actually emit code to start a new stack frame.
731  __ push(ebp);
732  __ mov(ebp, esp);
733  // Save callee-save registers. Order here should correspond to order of
734  // kBackup_ebx etc.
735  __ push(esi);
736  __ push(edi);
737  __ push(ebx); // Callee-save on MacOS.
738  __ push(Immediate(0)); // Number of successful matches in a global regexp.
739  __ push(Immediate(0)); // Make room for "input start - 1" constant.
740 
741  // Check if we have space on the stack for registers.
742  Label stack_limit_hit;
743  Label stack_ok;
744 
745  ExternalReference stack_limit =
746  ExternalReference::address_of_stack_limit(masm_->isolate());
747  __ mov(ecx, esp);
748  __ sub(ecx, Operand::StaticVariable(stack_limit));
749  // Handle it if the stack pointer is already below the stack limit.
750  __ j(below_equal, &stack_limit_hit);
751  // Check if there is room for the variable number of registers above
752  // the stack limit.
753  __ cmp(ecx, num_registers_ * kPointerSize);
754  __ j(above_equal, &stack_ok);
755  // Exit with OutOfMemory exception. There is not enough space on the stack
756  // for our working registers.
757  __ mov(eax, EXCEPTION);
758  __ jmp(&return_eax);
759 
760  __ bind(&stack_limit_hit);
761  CallCheckStackGuardState(ebx);
762  __ or_(eax, eax);
763  // If returned value is non-zero, we exit with the returned value as result.
764  __ j(not_zero, &return_eax);
765 
766  __ bind(&stack_ok);
767  // Load start index for later use.
768  __ mov(ebx, Operand(ebp, kStartIndex));
769 
770  // Allocate space on stack for registers.
771  __ sub(esp, Immediate(num_registers_ * kPointerSize));
772  // Load string length.
773  __ mov(esi, Operand(ebp, kInputEnd));
774  // Load input position.
775  __ mov(edi, Operand(ebp, kInputStart));
776  // Set up edi to be negative offset from string end.
777  __ sub(edi, esi);
778 
779  // Set eax to address of char before start of the string.
780  // (effectively string position -1).
781  __ neg(ebx);
782  if (mode_ == UC16) {
783  __ lea(eax, Operand(edi, ebx, times_2, -char_size()));
784  } else {
785  __ lea(eax, Operand(edi, ebx, times_1, -char_size()));
786  }
787  // Store this value in a local variable, for use when clearing
788  // position registers.
789  __ mov(Operand(ebp, kInputStartMinusOne), eax);
790 
791 #ifdef WIN32
792  // Ensure that we write to each stack page, in order. Skipping a page
793  // on Windows can cause segmentation faults. Assuming page size is 4k.
794  const int kPageSize = 4096;
795  const int kRegistersPerPage = kPageSize / kPointerSize;
796  for (int i = num_saved_registers_ + kRegistersPerPage - 1;
797  i < num_registers_;
798  i += kRegistersPerPage) {
799  __ mov(register_location(i), eax); // One write every page.
800  }
801 #endif // WIN32
802 
803  Label load_char_start_regexp, start_regexp;
804  // Load newline if index is at start, previous character otherwise.
805  __ cmp(Operand(ebp, kStartIndex), Immediate(0));
806  __ j(not_equal, &load_char_start_regexp, Label::kNear);
807  __ mov(current_character(), '\n');
808  __ jmp(&start_regexp, Label::kNear);
809 
810  // Global regexp restarts matching here.
811  __ bind(&load_char_start_regexp);
812  // Load previous char as initial value of current character register.
813  LoadCurrentCharacterUnchecked(-1, 1);
814  __ bind(&start_regexp);
815 
816  // Initialize on-stack registers.
817  if (num_saved_registers_ > 0) { // Always is, if generated from a regexp.
818  // Fill saved registers with initial value = start offset - 1
819  // Fill in stack push order, to avoid accessing across an unwritten
820  // page (a problem on Windows).
821  if (num_saved_registers_ > 8) {
822  __ mov(ecx, kRegisterZero);
823  Label init_loop;
824  __ bind(&init_loop);
825  __ mov(Operand(ebp, ecx, times_1, 0), eax);
826  __ sub(ecx, Immediate(kPointerSize));
827  __ cmp(ecx, kRegisterZero - num_saved_registers_ * kPointerSize);
828  __ j(greater, &init_loop);
829  } else { // Unroll the loop.
830  for (int i = 0; i < num_saved_registers_; i++) {
831  __ mov(register_location(i), eax);
832  }
833  }
834  }
835 
836  // Initialize backtrack stack pointer.
837  __ mov(backtrack_stackpointer(), Operand(ebp, kStackHighEnd));
838 
839  __ jmp(&start_label_);
840 
841  // Exit code:
842  if (success_label_.is_linked()) {
843  // Save captures when successful.
844  __ bind(&success_label_);
845  if (num_saved_registers_ > 0) {
846  // copy captures to output
847  __ mov(ebx, Operand(ebp, kRegisterOutput));
848  __ mov(ecx, Operand(ebp, kInputEnd));
849  __ mov(edx, Operand(ebp, kStartIndex));
850  __ sub(ecx, Operand(ebp, kInputStart));
851  if (mode_ == UC16) {
852  __ lea(ecx, Operand(ecx, edx, times_2, 0));
853  } else {
854  __ add(ecx, edx);
855  }
856  for (int i = 0; i < num_saved_registers_; i++) {
857  __ mov(eax, register_location(i));
858  if (i == 0 && global_with_zero_length_check()) {
859  // Keep capture start in edx for the zero-length check later.
860  __ mov(edx, eax);
861  }
862  // Convert to index from start of string, not end.
863  __ add(eax, ecx);
864  if (mode_ == UC16) {
865  __ sar(eax, 1); // Convert byte index to character index.
866  }
867  __ mov(Operand(ebx, i * kPointerSize), eax);
868  }
869  }
870 
871  if (global()) {
872  // Restart matching if the regular expression is flagged as global.
873  // Increment success counter.
874  __ inc(Operand(ebp, kSuccessfulCaptures));
875  // Capture results have been stored, so the number of remaining global
876  // output registers is reduced by the number of stored captures.
877  __ mov(ecx, Operand(ebp, kNumOutputRegisters));
878  __ sub(ecx, Immediate(num_saved_registers_));
879  // Check whether we have enough room for another set of capture results.
880  __ cmp(ecx, Immediate(num_saved_registers_));
881  __ j(less, &exit_label_);
882 
883  __ mov(Operand(ebp, kNumOutputRegisters), ecx);
884  // Advance the location for output.
885  __ add(Operand(ebp, kRegisterOutput),
886  Immediate(num_saved_registers_ * kPointerSize));
887 
888  // Prepare eax to initialize registers with its value in the next run.
889  __ mov(eax, Operand(ebp, kInputStartMinusOne));
890 
891  if (global_with_zero_length_check()) {
892  // Special case for zero-length matches.
893  // edx: capture start index
894  __ cmp(edi, edx);
895  // Not a zero-length match, restart.
896  __ j(not_equal, &load_char_start_regexp);
897  // edi (offset from the end) is zero if we already reached the end.
898  __ test(edi, edi);
899  __ j(zero, &exit_label_, Label::kNear);
900  // Advance current position after a zero-length match.
901  if (mode_ == UC16) {
902  __ add(edi, Immediate(2));
903  } else {
904  __ inc(edi);
905  }
906  }
907 
908  __ jmp(&load_char_start_regexp);
909  } else {
910  __ mov(eax, Immediate(SUCCESS));
911  }
912  }
913 
914  __ bind(&exit_label_);
915  if (global()) {
916  // Return the number of successful captures.
917  __ mov(eax, Operand(ebp, kSuccessfulCaptures));
918  }
919 
920  __ bind(&return_eax);
921  // Skip esp past regexp registers.
922  __ lea(esp, Operand(ebp, kBackup_ebx));
923  // Restore callee-save registers.
924  __ pop(ebx);
925  __ pop(edi);
926  __ pop(esi);
927  // Exit function frame, restore previous one.
928  __ pop(ebp);
929  __ ret(0);
930 
931  // Backtrack code (branch target for conditional backtracks).
932  if (backtrack_label_.is_linked()) {
933  __ bind(&backtrack_label_);
934  Backtrack();
935  }
936 
937  Label exit_with_exception;
938 
939  // Preempt-code
940  if (check_preempt_label_.is_linked()) {
941  SafeCallTarget(&check_preempt_label_);
942 
943  __ push(backtrack_stackpointer());
944  __ push(edi);
945 
946  CallCheckStackGuardState(ebx);
947  __ or_(eax, eax);
948  // If returning non-zero, we should end execution with the given
949  // result as return value.
950  __ j(not_zero, &return_eax);
951 
952  __ pop(edi);
953  __ pop(backtrack_stackpointer());
954  // String might have moved: Reload esi from frame.
955  __ mov(esi, Operand(ebp, kInputEnd));
956  SafeReturn();
957  }
958 
959  // Backtrack stack overflow code.
960  if (stack_overflow_label_.is_linked()) {
961  SafeCallTarget(&stack_overflow_label_);
962  // Reached if the backtrack-stack limit has been hit.
963 
964  Label grow_failed;
965  // Save registers before calling C function
966  __ push(esi);
967  __ push(edi);
968 
969  // Call GrowStack(backtrack_stackpointer())
970  static const int num_arguments = 3;
971  __ PrepareCallCFunction(num_arguments, ebx);
972  __ mov(Operand(esp, 2 * kPointerSize),
973  Immediate(ExternalReference::isolate_address()));
974  __ lea(eax, Operand(ebp, kStackHighEnd));
975  __ mov(Operand(esp, 1 * kPointerSize), eax);
976  __ mov(Operand(esp, 0 * kPointerSize), backtrack_stackpointer());
977  ExternalReference grow_stack =
978  ExternalReference::re_grow_stack(masm_->isolate());
979  __ CallCFunction(grow_stack, num_arguments);
980  // If return NULL, we have failed to grow the stack, and
981  // must exit with a stack-overflow exception.
982  __ or_(eax, eax);
983  __ j(equal, &exit_with_exception);
984  // Otherwise use return value as new stack pointer.
985  __ mov(backtrack_stackpointer(), eax);
986  // Restore saved registers and continue.
987  __ pop(edi);
988  __ pop(esi);
989  SafeReturn();
990  }
991 
992  if (exit_with_exception.is_linked()) {
993  // If any of the code above needed to exit with an exception.
994  __ bind(&exit_with_exception);
995  // Exit with Result EXCEPTION(-1) to signal thrown exception.
996  __ mov(eax, EXCEPTION);
997  __ jmp(&return_eax);
998  }
999 
1000  CodeDesc code_desc;
1001  masm_->GetCode(&code_desc);
1002  Handle<Code> code =
1003  masm_->isolate()->factory()->NewCode(code_desc,
1004  Code::ComputeFlags(Code::REGEXP),
1005  masm_->CodeObject());
1006  PROFILE(masm_->isolate(), RegExpCodeCreateEvent(*code, *source));
1007  return Handle<HeapObject>::cast(code);
1008 }
1009 
1010 
1011 void RegExpMacroAssemblerIA32::GoTo(Label* to) {
1012  BranchOrBacktrack(no_condition, to);
1013 }
1014 
1015 
1016 void RegExpMacroAssemblerIA32::IfRegisterGE(int reg,
1017  int comparand,
1018  Label* if_ge) {
1019  __ cmp(register_location(reg), Immediate(comparand));
1020  BranchOrBacktrack(greater_equal, if_ge);
1021 }
1022 
1023 
1024 void RegExpMacroAssemblerIA32::IfRegisterLT(int reg,
1025  int comparand,
1026  Label* if_lt) {
1027  __ cmp(register_location(reg), Immediate(comparand));
1028  BranchOrBacktrack(less, if_lt);
1029 }
1030 
1031 
1032 void RegExpMacroAssemblerIA32::IfRegisterEqPos(int reg,
1033  Label* if_eq) {
1034  __ cmp(edi, register_location(reg));
1035  BranchOrBacktrack(equal, if_eq);
1036 }
1037 
1038 
1039 RegExpMacroAssembler::IrregexpImplementation
1040  RegExpMacroAssemblerIA32::Implementation() {
1041  return kIA32Implementation;
1042 }
1043 
1044 
1045 void RegExpMacroAssemblerIA32::LoadCurrentCharacter(int cp_offset,
1046  Label* on_end_of_input,
1047  bool check_bounds,
1048  int characters) {
1049  ASSERT(cp_offset >= -1); // ^ and \b can look behind one character.
1050  ASSERT(cp_offset < (1<<30)); // Be sane! (And ensure negation works)
1051  if (check_bounds) {
1052  CheckPosition(cp_offset + characters - 1, on_end_of_input);
1053  }
1054  LoadCurrentCharacterUnchecked(cp_offset, characters);
1055 }
1056 
1057 
1058 void RegExpMacroAssemblerIA32::PopCurrentPosition() {
1059  Pop(edi);
1060 }
1061 
1062 
1063 void RegExpMacroAssemblerIA32::PopRegister(int register_index) {
1064  Pop(eax);
1065  __ mov(register_location(register_index), eax);
1066 }
1067 
1068 
1069 void RegExpMacroAssemblerIA32::PushBacktrack(Label* label) {
1070  Push(Immediate::CodeRelativeOffset(label));
1071  CheckStackLimit();
1072 }
1073 
1074 
1075 void RegExpMacroAssemblerIA32::PushCurrentPosition() {
1076  Push(edi);
1077 }
1078 
1079 
1080 void RegExpMacroAssemblerIA32::PushRegister(int register_index,
1081  StackCheckFlag check_stack_limit) {
1082  __ mov(eax, register_location(register_index));
1083  Push(eax);
1084  if (check_stack_limit) CheckStackLimit();
1085 }
1086 
1087 
1088 void RegExpMacroAssemblerIA32::ReadCurrentPositionFromRegister(int reg) {
1089  __ mov(edi, register_location(reg));
1090 }
1091 
1092 
1093 void RegExpMacroAssemblerIA32::ReadStackPointerFromRegister(int reg) {
1094  __ mov(backtrack_stackpointer(), register_location(reg));
1095  __ add(backtrack_stackpointer(), Operand(ebp, kStackHighEnd));
1096 }
1097 
1098 void RegExpMacroAssemblerIA32::SetCurrentPositionFromEnd(int by) {
1099  Label after_position;
1100  __ cmp(edi, -by * char_size());
1101  __ j(greater_equal, &after_position, Label::kNear);
1102  __ mov(edi, -by * char_size());
1103  // On RegExp code entry (where this operation is used), the character before
1104  // the current position is expected to be already loaded.
1105  // We have advanced the position, so it's safe to read backwards.
1106  LoadCurrentCharacterUnchecked(-1, 1);
1107  __ bind(&after_position);
1108 }
1109 
1110 void RegExpMacroAssemblerIA32::SetRegister(int register_index, int to) {
1111  ASSERT(register_index >= num_saved_registers_); // Reserved for positions!
1112  __ mov(register_location(register_index), Immediate(to));
1113 }
1114 
1115 
1116 bool RegExpMacroAssemblerIA32::Succeed() {
1117  __ jmp(&success_label_);
1118  return global();
1119 }
1120 
1121 
1122 void RegExpMacroAssemblerIA32::WriteCurrentPositionToRegister(int reg,
1123  int cp_offset) {
1124  if (cp_offset == 0) {
1125  __ mov(register_location(reg), edi);
1126  } else {
1127  __ lea(eax, Operand(edi, cp_offset * char_size()));
1128  __ mov(register_location(reg), eax);
1129  }
1130 }
1131 
1132 
1133 void RegExpMacroAssemblerIA32::ClearRegisters(int reg_from, int reg_to) {
1134  ASSERT(reg_from <= reg_to);
1135  __ mov(eax, Operand(ebp, kInputStartMinusOne));
1136  for (int reg = reg_from; reg <= reg_to; reg++) {
1137  __ mov(register_location(reg), eax);
1138  }
1139 }
1140 
1141 
1142 void RegExpMacroAssemblerIA32::WriteStackPointerToRegister(int reg) {
1143  __ mov(eax, backtrack_stackpointer());
1144  __ sub(eax, Operand(ebp, kStackHighEnd));
1145  __ mov(register_location(reg), eax);
1146 }
1147 
1148 
1149 // Private methods:
1150 
1151 void RegExpMacroAssemblerIA32::CallCheckStackGuardState(Register scratch) {
1152  static const int num_arguments = 3;
1153  __ PrepareCallCFunction(num_arguments, scratch);
1154  // RegExp code frame pointer.
1155  __ mov(Operand(esp, 2 * kPointerSize), ebp);
1156  // Code* of self.
1157  __ mov(Operand(esp, 1 * kPointerSize), Immediate(masm_->CodeObject()));
1158  // Next address on the stack (will be address of return address).
1159  __ lea(eax, Operand(esp, -kPointerSize));
1160  __ mov(Operand(esp, 0 * kPointerSize), eax);
1161  ExternalReference check_stack_guard =
1162  ExternalReference::re_check_stack_guard_state(masm_->isolate());
1163  __ CallCFunction(check_stack_guard, num_arguments);
1164 }
1165 
1166 
1167 // Helper function for reading a value out of a stack frame.
1168 template <typename T>
1169 static T& frame_entry(Address re_frame, int frame_offset) {
1170  return reinterpret_cast<T&>(Memory::int32_at(re_frame + frame_offset));
1171 }
1172 
1173 
1174 int RegExpMacroAssemblerIA32::CheckStackGuardState(Address* return_address,
1175  Code* re_code,
1176  Address re_frame) {
1177  Isolate* isolate = frame_entry<Isolate*>(re_frame, kIsolate);
1178  ASSERT(isolate == Isolate::Current());
1179  if (isolate->stack_guard()->IsStackOverflow()) {
1180  isolate->StackOverflow();
1181  return EXCEPTION;
1182  }
1183 
1184  // If not real stack overflow the stack guard was used to interrupt
1185  // execution for another purpose.
1186 
1187  // If this is a direct call from JavaScript retry the RegExp forcing the call
1188  // through the runtime system. Currently the direct call cannot handle a GC.
1189  if (frame_entry<int>(re_frame, kDirectCall) == 1) {
1190  return RETRY;
1191  }
1192 
1193  // Prepare for possible GC.
1194  HandleScope handles(isolate);
1195  Handle<Code> code_handle(re_code);
1196 
1197  Handle<String> subject(frame_entry<String*>(re_frame, kInputString));
1198 
1199  // Current string.
1200  bool is_ascii = subject->IsAsciiRepresentationUnderneath();
1201 
1202  ASSERT(re_code->instruction_start() <= *return_address);
1203  ASSERT(*return_address <=
1204  re_code->instruction_start() + re_code->instruction_size());
1205 
1206  MaybeObject* result = Execution::HandleStackGuardInterrupt(isolate);
1207 
1208  if (*code_handle != re_code) { // Return address no longer valid
1209  int delta = code_handle->address() - re_code->address();
1210  // Overwrite the return address on the stack.
1211  *return_address += delta;
1212  }
1213 
1214  if (result->IsException()) {
1215  return EXCEPTION;
1216  }
1217 
1218  Handle<String> subject_tmp = subject;
1219  int slice_offset = 0;
1220 
1221  // Extract the underlying string and the slice offset.
1222  if (StringShape(*subject_tmp).IsCons()) {
1223  subject_tmp = Handle<String>(ConsString::cast(*subject_tmp)->first());
1224  } else if (StringShape(*subject_tmp).IsSliced()) {
1225  SlicedString* slice = SlicedString::cast(*subject_tmp);
1226  subject_tmp = Handle<String>(slice->parent());
1227  slice_offset = slice->offset();
1228  }
1229 
1230  // String might have changed.
1231  if (subject_tmp->IsAsciiRepresentation() != is_ascii) {
1232  // If we changed between an ASCII and an UC16 string, the specialized
1233  // code cannot be used, and we need to restart regexp matching from
1234  // scratch (including, potentially, compiling a new version of the code).
1235  return RETRY;
1236  }
1237 
1238  // Otherwise, the content of the string might have moved. It must still
1239  // be a sequential or external string with the same content.
1240  // Update the start and end pointers in the stack frame to the current
1241  // location (whether it has actually moved or not).
1242  ASSERT(StringShape(*subject_tmp).IsSequential() ||
1243  StringShape(*subject_tmp).IsExternal());
1244 
1245  // The original start address of the characters to match.
1246  const byte* start_address = frame_entry<const byte*>(re_frame, kInputStart);
1247 
1248  // Find the current start address of the same character at the current string
1249  // position.
1250  int start_index = frame_entry<int>(re_frame, kStartIndex);
1251  const byte* new_address = StringCharacterPosition(*subject_tmp,
1252  start_index + slice_offset);
1253 
1254  if (start_address != new_address) {
1255  // If there is a difference, update the object pointer and start and end
1256  // addresses in the RegExp stack frame to match the new value.
1257  const byte* end_address = frame_entry<const byte* >(re_frame, kInputEnd);
1258  int byte_length = static_cast<int>(end_address - start_address);
1259  frame_entry<const String*>(re_frame, kInputString) = *subject;
1260  frame_entry<const byte*>(re_frame, kInputStart) = new_address;
1261  frame_entry<const byte*>(re_frame, kInputEnd) = new_address + byte_length;
1262  } else if (frame_entry<const String*>(re_frame, kInputString) != *subject) {
1263  // Subject string might have been a ConsString that underwent
1264  // short-circuiting during GC. That will not change start_address but
1265  // will change pointer inside the subject handle.
1266  frame_entry<const String*>(re_frame, kInputString) = *subject;
1267  }
1268 
1269  return 0;
1270 }
1271 
1272 
1273 Operand RegExpMacroAssemblerIA32::register_location(int register_index) {
1274  ASSERT(register_index < (1<<30));
1275  if (num_registers_ <= register_index) {
1276  num_registers_ = register_index + 1;
1277  }
1278  return Operand(ebp, kRegisterZero - register_index * kPointerSize);
1279 }
1280 
1281 
1282 void RegExpMacroAssemblerIA32::CheckPosition(int cp_offset,
1283  Label* on_outside_input) {
1284  __ cmp(edi, -cp_offset * char_size());
1285  BranchOrBacktrack(greater_equal, on_outside_input);
1286 }
1287 
1288 
1289 void RegExpMacroAssemblerIA32::BranchOrBacktrack(Condition condition,
1290  Label* to) {
1291  if (condition < 0) { // No condition
1292  if (to == NULL) {
1293  Backtrack();
1294  return;
1295  }
1296  __ jmp(to);
1297  return;
1298  }
1299  if (to == NULL) {
1300  __ j(condition, &backtrack_label_);
1301  return;
1302  }
1303  __ j(condition, to);
1304 }
1305 
1306 
1307 void RegExpMacroAssemblerIA32::SafeCall(Label* to) {
1308  Label return_to;
1309  __ push(Immediate::CodeRelativeOffset(&return_to));
1310  __ jmp(to);
1311  __ bind(&return_to);
1312 }
1313 
1314 
1315 void RegExpMacroAssemblerIA32::SafeReturn() {
1316  __ pop(ebx);
1317  __ add(ebx, Immediate(masm_->CodeObject()));
1318  __ jmp(ebx);
1319 }
1320 
1321 
1322 void RegExpMacroAssemblerIA32::SafeCallTarget(Label* name) {
1323  __ bind(name);
1324 }
1325 
1326 
1327 void RegExpMacroAssemblerIA32::Push(Register source) {
1328  ASSERT(!source.is(backtrack_stackpointer()));
1329  // Notice: This updates flags, unlike normal Push.
1330  __ sub(backtrack_stackpointer(), Immediate(kPointerSize));
1331  __ mov(Operand(backtrack_stackpointer(), 0), source);
1332 }
1333 
1334 
1335 void RegExpMacroAssemblerIA32::Push(Immediate value) {
1336  // Notice: This updates flags, unlike normal Push.
1337  __ sub(backtrack_stackpointer(), Immediate(kPointerSize));
1338  __ mov(Operand(backtrack_stackpointer(), 0), value);
1339 }
1340 
1341 
1342 void RegExpMacroAssemblerIA32::Pop(Register target) {
1343  ASSERT(!target.is(backtrack_stackpointer()));
1344  __ mov(target, Operand(backtrack_stackpointer(), 0));
1345  // Notice: This updates flags, unlike normal Pop.
1346  __ add(backtrack_stackpointer(), Immediate(kPointerSize));
1347 }
1348 
1349 
1350 void RegExpMacroAssemblerIA32::CheckPreemption() {
1351  // Check for preemption.
1352  Label no_preempt;
1353  ExternalReference stack_limit =
1354  ExternalReference::address_of_stack_limit(masm_->isolate());
1355  __ cmp(esp, Operand::StaticVariable(stack_limit));
1356  __ j(above, &no_preempt);
1357 
1358  SafeCall(&check_preempt_label_);
1359 
1360  __ bind(&no_preempt);
1361 }
1362 
1363 
1364 void RegExpMacroAssemblerIA32::CheckStackLimit() {
1365  Label no_stack_overflow;
1366  ExternalReference stack_limit =
1367  ExternalReference::address_of_regexp_stack_limit(masm_->isolate());
1368  __ cmp(backtrack_stackpointer(), Operand::StaticVariable(stack_limit));
1369  __ j(above, &no_stack_overflow);
1370 
1371  SafeCall(&stack_overflow_label_);
1372 
1373  __ bind(&no_stack_overflow);
1374 }
1375 
1376 
1377 void RegExpMacroAssemblerIA32::LoadCurrentCharacterUnchecked(int cp_offset,
1378  int characters) {
1379  if (mode_ == ASCII) {
1380  if (characters == 4) {
1381  __ mov(current_character(), Operand(esi, edi, times_1, cp_offset));
1382  } else if (characters == 2) {
1383  __ movzx_w(current_character(), Operand(esi, edi, times_1, cp_offset));
1384  } else {
1385  ASSERT(characters == 1);
1386  __ movzx_b(current_character(), Operand(esi, edi, times_1, cp_offset));
1387  }
1388  } else {
1389  ASSERT(mode_ == UC16);
1390  if (characters == 2) {
1391  __ mov(current_character(),
1392  Operand(esi, edi, times_1, cp_offset * sizeof(uc16)));
1393  } else {
1394  ASSERT(characters == 1);
1395  __ movzx_w(current_character(),
1396  Operand(esi, edi, times_1, cp_offset * sizeof(uc16)));
1397  }
1398  }
1399 }
1400 
1401 
1402 #undef __
1403 
1404 #endif // V8_INTERPRETED_REGEXP
1405 
1406 }} // namespace v8::internal
1407 
1408 #endif // V8_TARGET_ARCH_IA32
byte * Address
Definition: globals.h:157
unsigned char byte
Definition: disasm.h:33
v8::Handle< v8::Value > Fail(const v8::Arguments &args)
const Register esp
#define ASSERT(condition)
Definition: checks.h:270
#define PROFILE(isolate, Call)
Definition: cpu-profiler.h:190
const Register edi
const Register ebp
RegExpMacroAssemblerIA32(Mode mode, int registers_to_save, Zone *zone)
const Register eax
const int kPointerSize
Definition: globals.h:220
Operand FieldOperand(Register object, int offset)
const Register ecx
#define __
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra code(assertions) for debugging") DEFINE_bool(code_comments
#define T(name, string, precedence)
Definition: token.cc:48
const Register ebx
uint16_t uc16
Definition: globals.h:259
#define ASSERT_EQ(v1, v2)
Definition: checks.h:271
const Register esi
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 and VFP2 enable use of VFP2 instructions if available enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of MIPS FPU instructions if NULL
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 and VFP2 enable use of VFP2 instructions if available enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of MIPS FPU instructions if NULL
Definition: flags.cc:301
#define STATIC_ASSERT(test)
Definition: checks.h:283
const Register edx
const uc32 kMaxAsciiCharCode
Definition: globals.h:263