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