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