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