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