46 #ifndef V8_INTERPRETED_REGEXP
47 #if V8_TARGET_ARCH_IA32
49 #elif V8_TARGET_ARCH_X64
51 #elif V8_TARGET_ARCH_ARM
53 #elif V8_TARGET_ARCH_MIPS
56 #error Unsupported target architecture.
69 bool* has_pending_exception) {
73 has_pending_exception);
79 for (
int i = 0; i < str->length(); i++) {
80 switch (str->Get(i)) {
92 return JSRegExp::Flags(flags);
96 static inline void ThrowRegExpException(Handle<JSRegExp> re,
97 Handle<String> pattern,
98 Handle<String> error_text,
99 const char* message) {
100 Isolate* isolate = re->GetIsolate();
101 Factory* factory = isolate->factory();
102 Handle<FixedArray> elements = factory->NewFixedArray(2);
103 elements->set(0, *pattern);
104 elements->set(1, *error_text);
105 Handle<JSArray> array = factory->NewJSArrayWithElements(elements);
106 Handle<Object> regexp_err = factory->NewSyntaxError(message, array);
107 isolate->Throw(*regexp_err);
115 ASSERT((ranges_length & 1) == 1);
120 for (
int i = 0; i < ranges_length; inside = !inside, last = ranges[i], i++) {
123 if (ranges[i] <= new_range.
from())
continue;
126 if (last <= new_range.
from() && new_range.
to() < ranges[i]) {
147 const int kMod = 128;
148 bool character_found[kMod];
150 memset(&character_found[0], 0,
sizeof(character_found));
151 for (
int i = 0; i < length; i++) {
152 int ch = (pattern->Get(i) & (kMod - 1));
153 if (!character_found[ch]) {
154 character_found[ch] =
true;
158 if (different * 3 > length)
return false;
171 Isolate* isolate = re->GetIsolate();
175 bool in_cache = !cached.
is_null();
176 LOG(isolate, RegExpCompileEvent(re, in_cache));
180 re->set_data(*cached);
185 PostponeInterruptsScope postpone(isolate);
191 ThrowRegExpException(re,
198 bool has_been_compiled =
false;
200 if (parse_result.
simple &&
202 !HasFewDifferentCharacters(pattern)) {
205 has_been_compiled =
true;
206 }
else if (parse_result.
tree->IsAtom() &&
213 if (!HasFewDifferentCharacters(atom_string)) {
215 has_been_compiled =
true;
218 if (!has_been_compiled) {
221 ASSERT(re->data()->IsFixedArray());
225 compilation_cache->
PutRegExp(pattern, flags, data);
236 switch (regexp->TypeTag()) {
238 return AtomExec(regexp, subject, index, last_match_info);
241 IrregexpExec(regexp, subject, index, last_match_info, zone);
243 regexp->GetIsolate()->has_pending_exception());
260 re->GetIsolate()->factory()->SetRegExpAtomData(re,
268 static void SetAtomLastCapture(
FixedArray* array,
272 NoHandleAllocation no_handles;
285 Isolate* isolate = re->GetIsolate();
288 ASSERT(index <= subject->length());
294 int needle_len = needle->
length();
297 if (needle_len != 0) {
298 if (index + needle_len > subject->length()) {
299 return isolate->
factory()->null_value();
307 index = (needle_content.
IsAscii()
326 if (index == -1)
return isolate->
factory()->null_value();
328 ASSERT(last_match_info->HasFastObjectElements());
331 NoHandleAllocation no_handles;
333 SetAtomLastCapture(array, *subject, index, index + needle_len);
335 return last_match_info;
347 bool RegExpImpl::EnsureCompiledIrregexp(
351 #ifdef V8_INTERPRETED_REGEXP
352 if (compiled_code->IsByteArray())
return true;
353 #else // V8_INTERPRETED_REGEXP (RegExp native code)
354 if (compiled_code->IsCode())
return true;
359 if (saved_code->IsCode()) {
362 ASSERT(compiled_code->IsSmi());
365 return CompileIrregexp(re, sample_subject, is_ascii, zone);
369 static bool CreateRegExpErrorObjectAndThrow(Handle<JSRegExp> re,
371 Handle<String> error_message,
373 Factory* factory = isolate->factory();
374 Handle<FixedArray> elements = factory->NewFixedArray(2);
375 elements->set(0, re->Pattern());
376 elements->set(1, *error_message);
377 Handle<JSArray> array = factory->NewJSArrayWithElements(elements);
378 Handle<Object> regexp_err =
379 factory->NewSyntaxError(
"malformed_regexp", array);
380 isolate->Throw(*regexp_err);
385 bool RegExpImpl::CompileIrregexp(Handle<JSRegExp> re,
386 Handle<String> sample_subject,
390 Isolate* isolate = re->GetIsolate();
392 PostponeInterruptsScope postpone(isolate);
403 (entry_value < JSRegExp::kCodeAgeMask && entry_value >= 0));
410 ASSERT(error_string->IsString());
411 Handle<String> error_message(
String::cast(error_string));
412 CreateRegExpErrorObjectAndThrow(re, is_ascii, error_message, isolate);
416 JSRegExp::Flags flags = re->GetFlags();
418 Handle<String> pattern(re->Pattern());
420 RegExpCompileData compile_data;
421 FlatStringReader reader(isolate, pattern);
426 ThrowRegExpException(re,
432 RegExpEngine::CompilationResult result =
434 flags.is_ignore_case(),
436 flags.is_multiline(),
441 if (result.error_message !=
NULL) {
443 Handle<String> error_message =
444 isolate->factory()->NewStringFromUtf8(
CStrVector(result.error_message));
445 CreateRegExpErrorObjectAndThrow(re, is_ascii, error_message, isolate);
452 if (result.num_registers > register_max) {
496 re->GetIsolate()->factory()->SetRegExpIrregexpData(re,
510 bool is_ascii = subject->IsAsciiRepresentationUnderneath();
511 if (!EnsureCompiledIrregexp(regexp, subject, is_ascii, zone))
return -1;
513 #ifdef V8_INTERPRETED_REGEXP
516 #else // V8_INTERPRETED_REGEXP
520 #endif // V8_INTERPRETED_REGEXP
525 int registers_per_match,
527 #ifdef V8_INTERPRETED_REGEXP
531 return registers_per_match;
532 #else // V8_INTERPRETED_REGEXP
534 *max_matches = size / registers_per_match;
536 #endif // V8_INTERPRETED_REGEXP
546 Isolate* isolate = regexp->GetIsolate();
551 ASSERT(index <= subject->length());
552 ASSERT(subject->IsFlat());
554 bool is_ascii = subject->IsAsciiRepresentationUnderneath();
556 #ifndef V8_INTERPRETED_REGEXP
559 EnsureCompiledIrregexp(regexp, subject, is_ascii, zone);
586 is_ascii = subject->IsAsciiRepresentationUnderneath();
590 #else // V8_INTERPRETED_REGEXP
595 int* register_vector = output.
start();
596 int number_of_capture_registers =
598 for (
int i = number_of_capture_registers - 1; i >= 0; i--) {
599 register_vector[i] = -1;
613 #endif // V8_INTERPRETED_REGEXP
622 Isolate* isolate = jsregexp->GetIsolate();
626 #ifdef V8_INTERPRETED_REGEXP
628 if (FLAG_trace_regexp_bytecodes) {
629 String* pattern = jsregexp->Pattern();
631 PrintF(
"\n\nSubject string: '%s'\n\n", *(subject->ToCString()));
636 if (required_registers < 0) {
649 int capture_register_count =
653 int* register_vector = registers.
vector();
655 for (
int i = 0; i < capture_register_count; i += 2) {
657 SetCapture(array, i + 1, register_vector[i + 1]);
662 return last_match_info;
669 return isolate->
factory()->null_value();
839 for (
int i = 0; i <
elements()->length(); i++)
861 return data.u_atom->length();
870 if (table_ ==
NULL) {
883 frequencies_[i] = CharacterFrequency(i);
889 frequencies_[index].Increment();
897 if (total_samples_ < 1)
return 1;
899 (frequencies_[in_character].counter() * 128) / total_samples_;
900 return freq_in_per128;
904 class CharacterFrequency {
906 CharacterFrequency() : counter_(0), character_(-1) { }
907 explicit CharacterFrequency(
int character)
908 : counter_(0), character_(character) { }
910 void Increment() { counter_++; }
911 int counter() {
return counter_; }
912 int character() {
return character_; }
933 reg_exp_too_big_ =
true;
934 return next_register_;
936 return next_register_++;
961 inline bool ascii() {
return ascii_; }
966 current_expansion_factor_ = value;
977 int recursion_depth_;
981 bool reg_exp_too_big_;
982 int current_expansion_factor_;
999 static RegExpEngine::CompilationResult IrregexpRegExpTooBig() {
1000 return RegExpEngine::CompilationResult(
"RegExp too big");
1008 : next_register_(2 * (capture_count + 1)),
1010 recursion_depth_(0),
1011 ignore_case_(ignore_case),
1013 reg_exp_too_big_(
false),
1014 current_expansion_factor_(1),
1015 frequency_collator_(),
1027 Heap* heap = pattern->GetHeap();
1029 bool use_slow_safe_regexp_compiler =
false;
1034 use_slow_safe_regexp_compiler =
true;
1037 macro_assembler->
set_slow_safe(use_slow_safe_regexp_compiler);
1040 if (FLAG_trace_regexp_assembler)
1047 work_list_ = &work_list;
1051 start->
Emit(
this, &new_trace);
1052 macro_assembler_->
Bind(&fail);
1053 macro_assembler_->
Fail();
1054 while (!work_list.is_empty()) {
1055 work_list.RemoveLast()->Emit(
this, &new_trace);
1057 if (reg_exp_too_big_)
return IrregexpRegExpTooBig();
1063 if (FLAG_print_code) {
1066 if (FLAG_trace_regexp_assembler) {
1067 delete macro_assembler_;
1079 return reg() == that;
1087 action = action->next()) {
1088 if (action->Mentions(reg))
1099 action = action->next()) {
1100 if (action->Mentions(reg)) {
1113 int Trace::FindAffectedRegisters(
OutSet* affected_registers,
1116 for (DeferredAction* action = actions_;
1118 action = action->next()) {
1120 Interval range =
static_cast<DeferredClearCaptures*
>(action)->range();
1121 for (
int i = range.
from(); i <= range.
to(); i++)
1122 affected_registers->Set(i, zone);
1123 if (range.
to() > max_register) max_register = range.
to();
1125 affected_registers->Set(action->reg(), zone);
1126 if (action->reg() > max_register) max_register = action->reg();
1129 return max_register;
1133 void Trace::RestoreAffectedRegisters(RegExpMacroAssembler* assembler,
1135 OutSet& registers_to_pop,
1136 OutSet& registers_to_clear) {
1137 for (
int reg = max_register; reg >= 0; reg--) {
1138 if (registers_to_pop.Get(reg)) assembler->PopRegister(reg);
1139 else if (registers_to_clear.Get(reg)) {
1141 while (reg > 0 && registers_to_clear.Get(reg - 1)) {
1144 assembler->ClearRegisters(reg, clear_to);
1150 void Trace::PerformDeferredActions(RegExpMacroAssembler* assembler,
1152 OutSet& affected_registers,
1153 OutSet* registers_to_pop,
1154 OutSet* registers_to_clear,
1157 const int push_limit = (assembler->stack_limit_slack() + 1) / 2;
1162 for (
int reg = 0; reg <= max_register; reg++) {
1163 if (!affected_registers.Get(reg)) {
1170 enum DeferredActionUndoType { IGNORE, RESTORE, CLEAR };
1171 DeferredActionUndoType undo_action = IGNORE;
1174 bool absolute =
false;
1176 int store_position = -1;
1179 for (DeferredAction* action = actions_;
1181 action = action->next()) {
1182 if (action->Mentions(reg)) {
1183 switch (action->type()) {
1185 Trace::DeferredSetRegister* psr =
1186 static_cast<Trace::DeferredSetRegister*
>(action);
1188 value += psr->value();
1196 undo_action = RESTORE;
1207 undo_action = RESTORE;
1210 Trace::DeferredCapture*
pc =
1211 static_cast<Trace::DeferredCapture*
>(action);
1212 if (!clear && store_position == -1) {
1213 store_position = pc->cp_offset();
1224 undo_action = IGNORE;
1226 undo_action = pc->is_capture() ? CLEAR : RESTORE;
1236 if (store_position == -1) {
1239 undo_action = RESTORE;
1251 if (undo_action == RESTORE) {
1255 if (pushes == push_limit) {
1260 assembler->PushRegister(reg, stack_check);
1261 registers_to_pop->Set(reg, zone);
1262 }
else if (undo_action == CLEAR) {
1263 registers_to_clear->Set(reg, zone);
1267 if (store_position != -1) {
1268 assembler->WriteCurrentPositionToRegister(reg, store_position);
1270 assembler->ClearRegisters(reg, reg);
1271 }
else if (absolute) {
1272 assembler->SetRegister(reg, value);
1273 }
else if (value != 0) {
1274 assembler->AdvanceRegister(reg, value);
1295 successor->
Emit(compiler, &new_state);
1300 OutSet affected_registers;
1309 int max_register = FindAffectedRegisters(&affected_registers,
1312 OutSet registers_to_clear;
1313 PerformDeferredActions(assembler,
1317 ®isters_to_clear,
1319 if (cp_offset_ != 0) {
1327 successor->
Emit(compiler, &new_state);
1330 assembler->
Bind(&undo);
1331 RestoreAffectedRegisters(assembler,
1334 registers_to_clear);
1349 if (!label()->is_bound()) {
1352 assembler->
Bind(label());
1359 if (clear_capture_count_ > 0) {
1362 int clear_capture_end = clear_capture_start_ + clear_capture_count_ - 1;
1363 assembler->
ClearRegisters(clear_capture_start_, clear_capture_end);
1373 trace->
Flush(compiler,
this);
1377 if (!label()->is_bound()) {
1378 assembler->
Bind(label());
1387 case NEGATIVE_SUBMATCH_SUCCESS:
1396 if (guards_ ==
NULL)
1398 guards_->
Add(guard, zone);
1415 new(on_success->
zone())
ActionNode(INCREMENT_REGISTER, on_success);
1447 result->data_.
u_submatch.stack_pointer_register = stack_reg;
1448 result->data_.
u_submatch.current_position_register = position_reg;
1455 int clear_register_count,
1456 int clear_register_from,
1459 new(on_success->
zone())
ActionNode(POSITIVE_SUBMATCH_SUCCESS, on_success);
1460 result->data_.
u_submatch.stack_pointer_register = stack_reg;
1461 result->data_.
u_submatch.current_position_register = position_reg;
1462 result->data_.
u_submatch.clear_register_count = clear_register_count;
1463 result->data_.
u_submatch.clear_register_from = clear_register_from;
1469 int repetition_register,
1470 int repetition_limit,
1473 new(on_success->
zone())
ActionNode(EMPTY_MATCH_CHECK, on_success);
1481 #define DEFINE_ACCEPT(Type) \
1482 void Type##Node::Accept(NodeVisitor* visitor) { \
1483 visitor->Visit##Type(this); \
1486 #undef DEFINE_ACCEPT
1501 switch (guard->
op()) {
1520 static int GetCaseIndependentLetters(Isolate* isolate,
1525 isolate->jsregexp_uncanonicalize()->get(character,
'\0', letters);
1529 letters[0] = character;
1541 static inline bool EmitSimpleCharacter(Isolate* isolate,
1542 RegExpCompiler* compiler,
1548 RegExpMacroAssembler* assembler = compiler->macro_assembler();
1549 bool bound_checked =
false;
1551 assembler->LoadCurrentCharacter(
1555 bound_checked =
true;
1557 assembler->CheckNotCharacter(c, on_failure);
1558 return bound_checked;
1564 static inline bool EmitAtomNonLetter(Isolate* isolate,
1565 RegExpCompiler* compiler,
1571 RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
1572 bool ascii = compiler->ascii();
1574 int length = GetCaseIndependentLetters(isolate, c, ascii, chars);
1580 bool checked =
false;
1588 macro_assembler->LoadCurrentCharacter(cp_offset, on_failure, check);
1591 macro_assembler->CheckNotCharacter(c, on_failure);
1597 static bool ShortCutEmitCharacterPair(RegExpMacroAssembler* macro_assembler,
1601 Label* on_failure) {
1608 uc16 exor = c1 ^ c2;
1610 if (((exor - 1) & exor) == 0) {
1614 uc16 mask = char_mask ^ exor;
1615 macro_assembler->CheckNotCharacterAfterAnd(c1, mask, on_failure);
1619 uc16 diff = c2 - c1;
1620 if (((diff - 1) & diff) == 0 && c1 >= diff) {
1625 uc16 mask = char_mask ^ diff;
1626 macro_assembler->CheckNotCharacterAfterMinusAnd(c1 - diff,
1646 static inline bool EmitAtomLetter(
Isolate* isolate,
1654 bool ascii = compiler->
ascii();
1656 int length = GetCaseIndependentLetters(isolate, c, ascii, chars);
1657 if (length <= 1)
return false;
1667 if (ShortCutEmitCharacterPair(macro_assembler,
1675 macro_assembler->
Bind(&ok);
1686 macro_assembler->
Bind(&ok);
1696 static void EmitBoundaryTest(RegExpMacroAssembler* masm,
1698 Label* fall_through,
1699 Label* above_or_equal,
1701 if (below != fall_through) {
1702 masm->CheckCharacterLT(border, below);
1703 if (above_or_equal != fall_through) masm->GoTo(above_or_equal);
1705 masm->CheckCharacterGT(border - 1, above_or_equal);
1710 static void EmitDoubleBoundaryTest(RegExpMacroAssembler* masm,
1713 Label* fall_through,
1715 Label* out_of_range) {
1716 if (in_range == fall_through) {
1717 if (first == last) {
1718 masm->CheckNotCharacter(first, out_of_range);
1720 masm->CheckCharacterNotInRange(first, last, out_of_range);
1723 if (first == last) {
1724 masm->CheckCharacter(first, in_range);
1726 masm->CheckCharacterInRange(first, last, in_range);
1728 if (out_of_range != fall_through) masm->GoTo(out_of_range);
1735 static void EmitUseLookupTable(
1736 RegExpMacroAssembler* masm,
1737 ZoneList<int>* ranges,
1741 Label* fall_through,
1747 int base = (min_char & ~kMask);
1751 for (
int i = start_index; i <= end_index; i++) {
1752 ASSERT_EQ(ranges->at(i) & ~kMask, base);
1754 ASSERT(start_index == 0 || (ranges->at(start_index - 1) & ~kMask) <= base);
1758 Label* on_bit_clear;
1760 if (even_label == fall_through) {
1761 on_bit_set = odd_label;
1762 on_bit_clear = even_label;
1765 on_bit_set = even_label;
1766 on_bit_clear = odd_label;
1769 for (
int i = 0; i < (ranges->at(start_index) & kMask) && i < kSize; i++) {
1774 for (
int i = start_index; i < end_index; i++) {
1775 for (j = (ranges->at(i) & kMask); j < (ranges->at(i + 1) & kMask); j++) {
1780 for (
int i = j; i < kSize; i++) {
1785 for (
int i = 0; i < kSize; i++) {
1786 ba->set(i, templ[i]);
1788 masm->CheckBitInTable(ba, on_bit_set);
1789 if (on_bit_clear != fall_through) masm->GoTo(on_bit_clear);
1793 static void CutOutRange(RegExpMacroAssembler* masm,
1794 ZoneList<int>* ranges,
1800 bool odd = (((cut_index - start_index) & 1) == 1);
1801 Label* in_range_label = odd ? odd_label : even_label;
1803 EmitDoubleBoundaryTest(masm,
1804 ranges->at(cut_index),
1805 ranges->at(cut_index + 1) - 1,
1809 ASSERT(!dummy.is_linked());
1813 for (
int j = cut_index; j > start_index; j--) {
1814 ranges->at(j) = ranges->at(j - 1);
1816 for (
int j = cut_index + 1; j < end_index; j++) {
1817 ranges->at(j) = ranges->at(j + 1);
1824 static void SplitSearchSpace(ZoneList<int>* ranges,
1827 int* new_start_index,
1833 int first = ranges->at(start_index);
1834 int last = ranges->at(end_index) - 1;
1836 *new_start_index = start_index;
1837 *border = (ranges->at(start_index) & ~kMask) + kSize;
1838 while (*new_start_index < end_index) {
1839 if (ranges->at(*new_start_index) > *border)
break;
1840 (*new_start_index)++;
1853 int binary_chop_index = (end_index + start_index) / 2;
1859 end_index - start_index > (*new_start_index - start_index) * 2 &&
1860 last - first > kSize * 2 &&
1861 binary_chop_index > *new_start_index &&
1862 ranges->at(binary_chop_index) >= first + 2 * kSize) {
1863 int scan_forward_for_section_border = binary_chop_index;;
1864 int new_border = (ranges->at(binary_chop_index) | kMask) + 1;
1866 while (scan_forward_for_section_border < end_index) {
1867 if (ranges->at(scan_forward_for_section_border) > new_border) {
1868 *new_start_index = scan_forward_for_section_border;
1869 *border = new_border;
1872 scan_forward_for_section_border++;
1876 ASSERT(*new_start_index > start_index);
1877 *new_end_index = *new_start_index - 1;
1878 if (ranges->at(*new_end_index) == *border) {
1881 if (*border >= ranges->at(end_index)) {
1882 *border = ranges->at(end_index);
1883 *new_start_index = end_index;
1884 *new_end_index = end_index - 1;
1895 static void GenerateBranches(RegExpMacroAssembler* masm,
1896 ZoneList<int>* ranges,
1901 Label* fall_through,
1904 int first = ranges->at(start_index);
1905 int last = ranges->at(end_index) - 1;
1911 if (start_index == end_index) {
1912 EmitBoundaryTest(masm, first, fall_through, even_label, odd_label);
1918 if (start_index + 1 == end_index) {
1919 EmitDoubleBoundaryTest(
1920 masm, first, last, fall_through, even_label, odd_label);
1926 if (end_index - start_index <= 6) {
1929 static int kNoCutIndex = -1;
1930 int cut = kNoCutIndex;
1931 for (
int i = start_index; i < end_index; i++) {
1932 if (ranges->at(i) == ranges->at(i + 1) - 1) {
1937 if (cut == kNoCutIndex) cut = start_index;
1939 masm, ranges, start_index, end_index, cut, even_label, odd_label);
1941 GenerateBranches(masm,
1957 if ((max_char >> kBits) == (min_char >> kBits)) {
1958 EmitUseLookupTable(masm,
1969 if ((min_char >> kBits) != (first >> kBits)) {
1970 masm->CheckCharacterLT(first, odd_label);
1971 GenerateBranches(masm,
1983 int new_start_index = 0;
1984 int new_end_index = 0;
1987 SplitSearchSpace(ranges,
1995 Label*
above = &handle_rest;
1996 if (border == last + 1) {
1999 above = (end_index & 1) != (start_index & 1) ? odd_label : even_label;
2000 ASSERT(new_end_index == end_index - 1);
2005 ASSERT_LT(start_index, new_start_index);
2007 ASSERT(new_end_index + 1 == new_start_index ||
2008 (new_end_index + 2 == new_start_index &&
2009 border == ranges->at(new_end_index + 1)));
2012 ASSERT_LT(ranges->at(new_end_index), border);
2013 ASSERT(border < ranges->at(new_start_index) ||
2014 (border == ranges->at(new_start_index) &&
2015 new_start_index == end_index &&
2016 new_end_index == end_index - 1 &&
2017 border == last + 1));
2018 ASSERT(new_start_index == 0 || border >= ranges->at(new_start_index - 1));
2020 masm->CheckCharacterGT(border - 1, above);
2022 GenerateBranches(masm,
2031 if (handle_rest.is_linked()) {
2032 masm->Bind(&handle_rest);
2033 bool flip = (new_start_index & 1) != (start_index & 1);
2034 GenerateBranches(masm,
2041 flip ? odd_label : even_label,
2042 flip ? even_label : odd_label);
2047 static void EmitCharClass(RegExpMacroAssembler* macro_assembler,
2048 RegExpCharacterClass*
cc,
2055 ZoneList<CharacterRange>* ranges = cc->ranges(zone);
2067 int range_count = ranges->length();
2069 int last_valid_range = range_count - 1;
2070 while (last_valid_range >= 0) {
2071 CharacterRange& range = ranges->at(last_valid_range);
2072 if (range.from() <= max_char) {
2078 if (last_valid_range < 0) {
2079 if (!cc->is_negated()) {
2080 macro_assembler->GoTo(on_failure);
2083 macro_assembler->CheckPosition(cp_offset, on_failure);
2088 if (last_valid_range == 0 &&
2089 ranges->at(0).IsEverything(max_char)) {
2090 if (cc->is_negated()) {
2091 macro_assembler->GoTo(on_failure);
2095 macro_assembler->CheckPosition(cp_offset, on_failure);
2100 if (last_valid_range == 0 &&
2101 !cc->is_negated() &&
2102 ranges->at(0).IsEverything(max_char)) {
2105 macro_assembler->CheckPosition(cp_offset, on_failure);
2111 macro_assembler->LoadCurrentCharacter(cp_offset, on_failure, check_offset);
2114 if (cc->is_standard(zone) &&
2115 macro_assembler->CheckSpecialCharacterClass(cc->standard_type(),
2127 ZoneList<int>* range_boundaries =
2128 new(zone) ZoneList<int>(last_valid_range, zone);
2130 bool zeroth_entry_is_failure = !cc->is_negated();
2132 for (
int i = 0; i <= last_valid_range; i++) {
2133 CharacterRange& range = ranges->at(i);
2134 if (range.from() == 0) {
2136 zeroth_entry_is_failure = !zeroth_entry_is_failure;
2138 range_boundaries->Add(range.from(), zone);
2140 range_boundaries->Add(range.to() + 1, zone);
2142 int end_index = range_boundaries->length() - 1;
2143 if (range_boundaries->at(end_index) > max_char) {
2148 GenerateBranches(macro_assembler,
2155 zeroth_entry_is_failure ? &fall_through : on_failure,
2156 zeroth_entry_is_failure ? on_failure : &fall_through);
2157 macro_assembler->Bind(&fall_through);
2174 if (label_.is_bound()) {
2177 macro_assembler->
GoTo(&label_);
2184 macro_assembler->
GoTo(&label_);
2188 macro_assembler->
Bind(&label_);
2195 if (FLAG_regexp_optimization &&
2196 trace_count_ < kMaxCopiesCodeGenerated &&
2204 trace->
Flush(compiler,
this);
2210 int recursion_depth,
2211 bool not_at_start) {
2213 if (
type_ == POSITIVE_SUBMATCH_SUCCESS)
return 0;
2214 return on_success()->EatsAtLeast(still_to_find,
2215 recursion_depth + 1,
2221 int recursion_depth,
2224 bool not_at_start) {
2225 if (
type_ == BEGIN_SUBMATCH) {
2227 }
else if (
type_ != POSITIVE_SUBMATCH_SUCCESS) {
2228 on_success()->FillInBMInfo(
2229 offset, recursion_depth + 1, budget - 1, bm, not_at_start);
2231 SaveBMInfo(bm, not_at_start, offset);
2236 int recursion_depth,
2237 bool not_at_start) {
2244 if (
type() == AT_START && not_at_start)
return still_to_find;
2245 return on_success()->EatsAtLeast(still_to_find,
2246 recursion_depth + 1,
2252 int recursion_depth,
2255 bool not_at_start) {
2257 if (
type() == AT_START && not_at_start)
return;
2258 on_success()->FillInBMInfo(
2259 offset, recursion_depth + 1, budget - 1, bm, not_at_start);
2260 SaveBMInfo(bm, not_at_start, offset);
2265 int recursion_depth,
2266 bool not_at_start) {
2268 return on_success()->EatsAtLeast(still_to_find,
2269 recursion_depth + 1,
2275 int recursion_depth,
2276 bool not_at_start) {
2277 int answer = Length();
2278 if (answer >= still_to_find)
return answer;
2281 return answer + on_success()->EatsAtLeast(still_to_find - answer,
2282 recursion_depth + 1,
2288 int recursion_depth,
2289 bool not_at_start) {
2293 RegExpNode* node = alternatives_->at(1).node();
2294 return node->
EatsAtLeast(still_to_find, recursion_depth + 1, not_at_start);
2302 bool not_at_start) {
2305 RegExpNode* node = alternatives_->at(1).node();
2311 int recursion_depth,
2313 bool not_at_start) {
2316 int choice_count = alternatives_->length();
2317 for (
int i = 0; i < choice_count; i++) {
2318 RegExpNode* node = alternatives_->at(i).node();
2319 if (node == ignore_this_node)
continue;
2320 int node_eats_at_least = node->
EatsAtLeast(still_to_find,
2321 recursion_depth + 1,
2323 if (node_eats_at_least < min) min = node_eats_at_least;
2330 int recursion_depth,
2331 bool not_at_start) {
2332 return EatsAtLeastHelper(still_to_find,
2340 int recursion_depth,
2341 bool not_at_start) {
2342 return EatsAtLeastHelper(still_to_find,
2350 static inline uint32_t SmearBitsRight(uint32_t v) {
2361 bool found_useful_op =
false;
2371 for (
int i = 0; i < characters_; i++) {
2374 found_useful_op =
true;
2376 mask_ |= (pos->
mask & char_mask) << char_shift;
2377 value_ |= (pos->
value & char_mask) << char_shift;
2378 char_shift += asc ? 8 : 16;
2380 return found_useful_op;
2386 bool preload_has_checked_bounds,
2387 Label* on_possible_success,
2389 bool fall_through_on_failure) {
2390 if (details->
characters() == 0)
return false;
2396 uint32_t mask = details->
mask();
2397 uint32_t value = details->
value();
2404 !preload_has_checked_bounds,
2409 bool need_mask =
true;
2415 if (compiler->
ascii()) {
2420 if ((mask & char_mask) == char_mask) need_mask =
false;
2426 if ((mask & 0x7f7f) == 0x7f7f) need_mask =
false;
2428 if ((mask & 0xffff) == 0xffff) need_mask =
false;
2430 if (mask == 0xffffffff) need_mask =
false;
2434 if (fall_through_on_failure) {
2461 int characters_filled_in,
2462 bool not_at_start) {
2463 Isolate* isolate = Isolate::Current();
2464 ASSERT(characters_filled_in < details->characters());
2467 if (compiler->
ascii()) {
2472 for (
int k = 0; k < elms_->length(); k++) {
2476 for (
int i = 0; i < characters && i < quarks.
length(); i++) {
2478 details->
positions(characters_filled_in);
2480 if (c > char_mask) {
2491 int length = GetCaseIndependentLetters(isolate, c, compiler->
ascii(),
2498 pos->
mask = char_mask;
2502 uint32_t common_bits = char_mask;
2503 uint32_t bits = chars[0];
2504 for (
int j = 1; j < length; j++) {
2505 uint32_t differing_bits = ((chars[j] & common_bits) ^ bits);
2506 common_bits ^= differing_bits;
2507 bits &= common_bits;
2513 uint32_t one_zero = (common_bits | ~char_mask);
2514 if (length == 2 && ((~one_zero) & ((~one_zero) - 1)) == 0) {
2517 pos->
mask = common_bits;
2524 pos->
mask = char_mask;
2528 characters_filled_in++;
2529 ASSERT(characters_filled_in <= details->characters());
2530 if (characters_filled_in == details->
characters()) {
2536 details->
positions(characters_filled_in);
2547 int first_range = 0;
2548 while (ranges->
at(first_range).from() > char_mask) {
2550 if (first_range == ranges->length()) {
2559 if (to > char_mask) {
2562 uint32_t differing_bits = (from ^ to);
2565 if ((differing_bits & (differing_bits + 1)) == 0 &&
2566 from + differing_bits == to) {
2569 uint32_t common_bits = ~SmearBitsRight(differing_bits);
2570 uint32_t bits = (from & common_bits);
2571 for (
int i = first_range + 1; i < ranges->length(); i++) {
2575 if (from > char_mask)
continue;
2576 if (to > char_mask) to = char_mask;
2583 uint32_t new_common_bits = (from ^ to);
2584 new_common_bits = ~SmearBitsRight(new_common_bits);
2585 common_bits &= new_common_bits;
2586 bits &= new_common_bits;
2587 uint32_t differing_bits = (from & common_bits) ^ bits;
2588 common_bits ^= differing_bits;
2589 bits &= common_bits;
2591 pos->
mask = common_bits;
2594 characters_filled_in++;
2595 ASSERT(characters_filled_in <= details->characters());
2596 if (characters_filled_in == details->
characters()) {
2603 on_success()-> GetQuickCheckDetails(details,
2605 characters_filled_in,
2612 for (
int i = 0; i < characters_; i++) {
2613 positions_[i].mask = 0;
2614 positions_[i].value = 0;
2615 positions_[i].determines_perfectly =
false;
2623 if (by >= characters_) {
2627 for (
int i = 0; i < characters_ - by; i++) {
2628 positions_[i] = positions_[by + i];
2630 for (
int i = characters_ - by; i < characters_; i++) {
2631 positions_[i].mask = 0;
2632 positions_[i].value = 0;
2633 positions_[i].determines_perfectly =
false;
2643 ASSERT(characters_ == other->characters_);
2644 if (other->cannot_match_) {
2647 if (cannot_match_) {
2651 for (
int i = from_index; i < characters_; i++) {
2654 if (pos->
mask != other_pos->
mask ||
2665 pos->
mask &= ~differing_bits;
2678 info_->visited =
false;
2686 if (info()->replacement_calculated)
return replacement();
2687 if (depth < 0)
return this;
2688 ASSERT(!info()->visited);
2690 return FilterSuccessor(depth - 1);
2696 if (next ==
NULL)
return set_replacement(
NULL);
2698 return set_replacement(
this);
2703 if (info()->replacement_calculated)
return replacement();
2704 if (depth < 0)
return this;
2705 ASSERT(!info()->visited);
2707 int element_count = elms_->length();
2708 for (
int i = 0; i < element_count; i++) {
2712 for (
int j = 0; j < quarks.
length(); j++) {
2717 return set_replacement(
NULL);
2728 int range_count = ranges->length();
2730 if (range_count != 0 &&
2731 ranges->
at(0).from() == 0 &&
2733 return set_replacement(
NULL);
2736 if (range_count == 0 ||
2738 return set_replacement(
NULL);
2743 return FilterSuccessor(depth - 1);
2748 if (info()->replacement_calculated)
return replacement();
2749 if (depth < 0)
return this;
2750 if (info()->visited)
return this;
2757 if (continue_replacement ==
NULL)
return set_replacement(
NULL);
2765 if (info()->replacement_calculated)
return replacement();
2766 if (depth < 0)
return this;
2767 if (info()->visited)
return this;
2769 int choice_count = alternatives_->length();
2771 for (
int i = 0; i < choice_count; i++) {
2774 set_replacement(
this);
2781 for (
int i = 0; i < choice_count; i++) {
2784 ASSERT(replacement !=
this);
2785 if (replacement !=
NULL) {
2786 alternatives_->at(i).set_node(replacement);
2788 survivor = replacement;
2791 if (surviving < 2)
return set_replacement(survivor);
2793 set_replacement(
this);
2794 if (surviving == choice_count) {
2801 for (
int i = 0; i < choice_count; i++) {
2803 alternatives_->at(i).node()->
FilterASCII(depth - 1);
2804 if (replacement !=
NULL) {
2805 alternatives_->at(i).set_node(replacement);
2806 new_alternatives->
Add(alternatives_->at(i), zone());
2809 alternatives_ = new_alternatives;
2815 if (info()->replacement_calculated)
return replacement();
2816 if (depth < 0)
return this;
2817 if (info()->visited)
return this;
2821 RegExpNode* node = alternatives_->at(1).node();
2823 if (replacement ==
NULL)
return set_replacement(
NULL);
2824 alternatives_->at(1).set_node(replacement);
2826 RegExpNode* neg_node = alternatives_->at(0).node();
2830 if (neg_replacement ==
NULL)
return set_replacement(replacement);
2831 alternatives_->at(0).set_node(neg_replacement);
2832 return set_replacement(
this);
2838 int characters_filled_in,
2839 bool not_at_start) {
2840 if (body_can_be_zero_length_ || info()->visited)
return;
2844 characters_filled_in,
2850 int recursion_depth,
2853 bool not_at_start) {
2854 if (body_can_be_zero_length_ ||
2858 SaveBMInfo(bm, not_at_start, offset);
2862 offset, recursion_depth + 1, budget - 1, bm, not_at_start);
2863 SaveBMInfo(bm, not_at_start, offset);
2869 int characters_filled_in,
2870 bool not_at_start) {
2871 not_at_start = (not_at_start || not_at_start_);
2872 int choice_count = alternatives_->length();
2873 ASSERT(choice_count > 0);
2874 alternatives_->at(0).node()->GetQuickCheckDetails(details,
2876 characters_filled_in,
2878 for (
int i = 1; i < choice_count; i++) {
2880 RegExpNode* node = alternatives_->at(i).node();
2882 characters_filled_in,
2885 details->
Merge(&new_details, characters_filled_in);
2894 bool fall_through_on_word) {
2896 fall_through_on_word ?
'w' :
'W',
2897 fall_through_on_word ? non_word : word)) {
2907 if (fall_through_on_word) {
2917 static void EmitHat(RegExpCompiler* compiler,
2918 RegExpNode* on_success,
2920 RegExpMacroAssembler* assembler = compiler->macro_assembler();
2923 Trace new_trace(*trace);
2924 new_trace.InvalidateCurrentCharacter();
2927 if (new_trace.cp_offset() == 0) {
2930 assembler->CheckAtStart(&ok);
2934 assembler->LoadCurrentCharacter(new_trace.cp_offset() -1,
2935 new_trace.backtrack(),
2937 if (!assembler->CheckSpecialCharacterClass(
'n',
2938 new_trace.backtrack())) {
2940 if (!compiler->ascii()) {
2941 assembler->CheckCharacterAfterAnd(0x2028, 0xfffe, &ok);
2943 assembler->CheckCharacter(
'\n', &ok);
2944 assembler->CheckNotCharacter(
'\r', new_trace.backtrack());
2946 assembler->Bind(&ok);
2947 on_success->Emit(compiler, &new_trace);
2952 void AssertionNode::EmitBoundaryCheck(RegExpCompiler* compiler,
Trace* trace) {
2953 RegExpMacroAssembler* assembler = compiler->macro_assembler();
2955 bool not_at_start = (trace->at_start() ==
Trace::FALSE);
2956 BoyerMooreLookahead* lookahead = bm_info(not_at_start);
2957 if (lookahead ==
NULL) {
2961 if (eats_at_least >= 1) {
2962 BoyerMooreLookahead* bm =
2963 new(zone()) BoyerMooreLookahead(eats_at_least, compiler, zone());
2964 FillInBMInfo(0, 0, kFillInBMBudget, bm, not_at_start);
2965 if (bm->at(0)->is_non_word()) next_is_word_character =
Trace::FALSE;
2966 if (bm->at(0)->is_word()) next_is_word_character =
Trace::TRUE;
2969 if (lookahead->at(0)->is_non_word()) next_is_word_character =
Trace::FALSE;
2970 if (lookahead->at(0)->is_word()) next_is_word_character =
Trace::TRUE;
2974 Label before_non_word;
2976 if (trace->characters_preloaded() != 1) {
2977 assembler->LoadCurrentCharacter(trace->cp_offset(), &before_non_word);
2980 EmitWordCheck(assembler, &before_word, &before_non_word,
false);
2982 assembler->Bind(&before_non_word);
2984 BacktrackIfPrevious(compiler, trace, at_boundary ? kIsNonWord : kIsWord);
2985 assembler->GoTo(&ok);
2987 assembler->Bind(&before_word);
2988 BacktrackIfPrevious(compiler, trace, at_boundary ? kIsWord : kIsNonWord);
2989 assembler->Bind(&ok);
2990 }
else if (next_is_word_character ==
Trace::TRUE) {
2991 BacktrackIfPrevious(compiler, trace, at_boundary ? kIsWord : kIsNonWord);
2994 BacktrackIfPrevious(compiler, trace, at_boundary ? kIsNonWord : kIsWord);
2999 void AssertionNode::BacktrackIfPrevious(
3000 RegExpCompiler* compiler,
3002 AssertionNode::IfPrevious backtrack_if_previous) {
3003 RegExpMacroAssembler* assembler = compiler->macro_assembler();
3004 Trace new_trace(*trace);
3005 new_trace.InvalidateCurrentCharacter();
3007 Label fall_through, dummy;
3009 Label* non_word = backtrack_if_previous == kIsNonWord ?
3010 new_trace.backtrack() :
3012 Label* word = backtrack_if_previous == kIsNonWord ?
3014 new_trace.backtrack();
3016 if (new_trace.cp_offset() == 0) {
3019 assembler->CheckAtStart(non_word);
3023 assembler->LoadCurrentCharacter(new_trace.cp_offset() - 1, &dummy,
false);
3024 EmitWordCheck(assembler, word, non_word, backtrack_if_previous == kIsNonWord);
3026 assembler->Bind(&fall_through);
3027 on_success()->Emit(compiler, &new_trace);
3034 bool not_at_start) {
3035 if (
type_ == AT_START && not_at_start) {
3039 return on_success()->GetQuickCheckDetails(details,
3053 assembler->
Bind(&ok);
3063 Trace at_start_trace = *trace;
3065 on_success()->Emit(compiler, &at_start_trace);
3071 EmitHat(compiler, on_success(), trace);
3074 case AT_NON_BOUNDARY: {
3075 EmitBoundaryCheck(compiler, trace);
3079 on_success()->Emit(compiler, trace);
3084 if (quick_check ==
NULL)
return false;
3085 if (offset >= quick_check->
characters())
return false;
3090 static void UpdateBoundsCheck(
int index,
int* checked_up_to) {
3091 if (index > *checked_up_to) {
3092 *checked_up_to = index;
3126 void TextNode::TextEmitPass(RegExpCompiler* compiler,
3127 TextEmitPassType pass,
3130 bool first_element_checked,
3131 int* checked_up_to) {
3132 Isolate* isolate = Isolate::Current();
3133 RegExpMacroAssembler* assembler = compiler->macro_assembler();
3134 bool ascii = compiler->ascii();
3136 QuickCheckDetails* quick_check = trace->quick_check_performed();
3137 int element_count = elms_->length();
3138 for (
int i = preloaded ? 0 : element_count - 1; i >= 0; i--) {
3139 TextElement elm = elms_->at(i);
3140 int cp_offset = trace->cp_offset() + elm.cp_offset;
3142 Vector<const uc16> quarks = elm.data.u_atom->data();
3143 for (
int j = preloaded ? 0 : quarks.length() - 1; j >= 0; j--) {
3144 if (first_element_checked && i == 0 && j == 0)
continue;
3145 if (DeterminedAlready(quick_check, elm.cp_offset + j))
continue;
3148 case NON_ASCII_MATCH:
3151 assembler->GoTo(backtrack);
3155 case NON_LETTER_CHARACTER_MATCH:
3156 emit_function = &EmitAtomNonLetter;
3158 case SIMPLE_CHARACTER_MATCH:
3159 emit_function = &EmitSimpleCharacter;
3161 case CASE_CHARACTER_MATCH:
3162 emit_function = &EmitAtomLetter;
3167 if (emit_function !=
NULL) {
3168 bool bound_checked = emit_function(isolate,
3173 *checked_up_to < cp_offset + j,
3175 if (bound_checked) UpdateBoundsCheck(cp_offset + j, checked_up_to);
3180 if (pass == CHARACTER_CLASS_MATCH) {
3181 if (first_element_checked && i == 0)
continue;
3182 if (DeterminedAlready(quick_check, elm.cp_offset))
continue;
3183 RegExpCharacterClass* cc = elm.data.u_char_class;
3184 EmitCharClass(assembler,
3189 *checked_up_to < cp_offset,
3192 UpdateBoundsCheck(cp_offset, checked_up_to);
3199 int TextNode::Length() {
3200 TextElement elm = elms_->last();
3201 ASSERT(elm.cp_offset >= 0);
3203 return elm.cp_offset + elm.data.u_atom->data().length();
3205 return elm.cp_offset + 1;
3210 bool TextNode::SkipPass(
int int_pass,
bool ignore_case) {
3211 TextEmitPassType pass =
static_cast<TextEmitPassType
>(int_pass);
3213 return pass == SIMPLE_CHARACTER_MATCH;
3215 return pass == NON_LETTER_CHARACTER_MATCH || pass == CASE_CHARACTER_MATCH;
3227 LimitResult limit_result = LimitVersions(compiler, trace);
3228 if (limit_result ==
DONE)
return;
3229 ASSERT(limit_result == CONTINUE);
3236 if (compiler->
ascii()) {
3238 TextEmitPass(compiler, NON_ASCII_MATCH,
false, trace,
false, &dummy);
3241 bool first_elt_done =
false;
3242 int bound_checked_to = trace->
cp_offset() - 1;
3248 for (
int pass = kFirstRealPass; pass <= kLastPass; pass++) {
3250 TextEmitPass(compiler,
3251 static_cast<TextEmitPassType>(pass),
3258 first_elt_done =
true;
3261 for (
int pass = kFirstRealPass; pass <= kLastPass; pass++) {
3263 TextEmitPass(compiler,
3264 static_cast<TextEmitPassType>(pass),
3272 Trace successor_trace(*trace);
3276 on_success()->Emit(compiler, &successor_trace);
3281 characters_preloaded_ = 0;
3290 characters_preloaded_ = 0;
3300 bound_checked_up_to_ =
Max(0, bound_checked_up_to_ - by);
3305 int element_count = elms_->length();
3306 for (
int i = 0; i < element_count; i++) {
3314 int range_count = ranges->length();
3315 for (
int j = 0; j < range_count; j++) {
3316 ranges->
at(j).AddCaseEquivalents(ranges, is_ascii, zone());
3335 if (elms_->length() != 1)
return NULL;
3344 return ranges->length() == 0 ? on_success() :
NULL;
3346 if (ranges->length() != 1)
return NULL;
3348 if (compiler->
ascii()) {
3353 return ranges->
at(0).IsEverything(max_char) ? on_success() :
NULL;
3367 int recursion_depth = 0;
3368 while (node !=
this) {
3370 return kNodeIsTooComplexForGreedyLoops;
3373 if (node_length == kNodeIsTooComplexForGreedyLoops) {
3374 return kNodeIsTooComplexForGreedyLoops;
3376 length += node_length;
3386 AddAlternative(alt);
3387 loop_node_ = alt.
node();
3393 AddAlternative(alt);
3394 continue_node_ = alt.
node();
3402 GreedyLoopTextLengthForAlternative(&(alternatives_->at(0)));
3403 ASSERT(text_length != kNodeIsTooComplexForGreedyLoops);
3413 trace->
Flush(compiler,
this);
3420 int ChoiceNode::CalculatePreloadCharacters(
RegExpCompiler* compiler,
3421 int eats_at_least) {
3422 int preload_characters =
Min(4, eats_at_least);
3424 bool ascii = compiler->
ascii();
3426 if (preload_characters > 4) preload_characters = 4;
3430 if (preload_characters == 3) preload_characters = 2;
3432 if (preload_characters > 2) preload_characters = 2;
3435 if (preload_characters > 1) preload_characters = 1;
3437 return preload_characters;
3446 : possible_success(),
3447 expects_preload(
false),
3449 quick_check_details() { }
3462 : alt_gens_(count, zone) {
3463 for (
int i = 0; i < count && i < kAFew; i++) {
3464 alt_gens_.Add(a_few_alt_gens_ + i, zone);
3466 for (
int i = kAFew; i < count; i++) {
3471 for (
int i = kAFew; i < alt_gens_.length(); i++) {
3472 delete alt_gens_[i];
3473 alt_gens_[i] =
NULL;
3478 return alt_gens_[i];
3482 static const int kAFew = 10;
3489 static const int kSpaceRanges[] = {
'\t',
'\r' + 1,
' ',
' ' + 1, 0x00A0,
3490 0x00A1, 0x1680, 0x1681, 0x180E, 0x180F, 0x2000, 0x200B, 0x2028, 0x202A,
3491 0x202F, 0x2030, 0x205F, 0x2060, 0x3000, 0x3001, 0xFEFF, 0xFF00, 0x10000 };
3492 static const int kSpaceRangeCount =
ARRAY_SIZE(kSpaceRanges);
3494 static const int kWordRanges[] = {
3495 '0',
'9' + 1,
'A',
'Z' + 1,
'_',
'_' + 1,
'a',
'z' + 1, 0x10000 };
3496 static const int kWordRangeCount =
ARRAY_SIZE(kWordRanges);
3497 static const int kDigitRanges[] = {
'0',
'9' + 1, 0x10000 };
3498 static const int kDigitRangeCount =
ARRAY_SIZE(kDigitRanges);
3499 static const int kSurrogateRanges[] = { 0xd800, 0xe000, 0x10000 };
3500 static const int kSurrogateRangeCount =
ARRAY_SIZE(kSurrogateRanges);
3501 static const int kLineTerminatorRanges[] = { 0x000A, 0x000B, 0x000D, 0x000E,
3502 0x2028, 0x202A, 0x10000 };
3503 static const int kLineTerminatorRangeCount =
ARRAY_SIZE(kLineTerminatorRanges);
3507 SetInterval(
Interval(character, character));
3512 s_ =
AddRange(s_, kSpaceRanges, kSpaceRangeCount, interval);
3513 w_ =
AddRange(w_, kWordRanges, kWordRangeCount, interval);
3514 d_ =
AddRange(d_, kDigitRanges, kDigitRangeCount, interval);
3516 AddRange(surrogate_, kSurrogateRanges, kSurrogateRangeCount, interval);
3517 if (interval.
to() - interval.
from() >= kMapSize - 1) {
3518 if (map_count_ != kMapSize) {
3519 map_count_ = kMapSize;
3520 for (
int i = 0; i < kMapSize; i++) map_->at(i) =
true;
3524 for (
int i = interval.
from(); i <= interval.
to(); i++) {
3525 int mod_character = (i & kMask);
3526 if (!map_->at(mod_character)) {
3528 map_->at(mod_character) =
true;
3530 if (map_count_ == kMapSize)
return;
3537 if (map_count_ != kMapSize) {
3538 map_count_ = kMapSize;
3539 for (
int i = 0; i < kMapSize; i++) map_->at(i) =
true;
3547 compiler_(compiler) {
3548 if (compiler->
ascii()) {
3554 for (
int i = 0; i <
length; i++) {
3563 bool BoyerMooreLookahead::FindWorthwhileInterval(
int* from,
int* to) {
3564 int biggest_points = 0;
3567 const int kMaxMax = 32;
3568 for (
int max_number_of_chars = 4;
3569 max_number_of_chars < kMaxMax;
3570 max_number_of_chars *= 2) {
3572 FindBestInterval(max_number_of_chars, biggest_points, from, to);
3574 if (biggest_points == 0)
return false;
3585 int BoyerMooreLookahead::FindBestInterval(
3586 int max_number_of_chars,
int old_biggest_points,
int* from,
int* to) {
3587 int biggest_points = old_biggest_points;
3589 for (
int i = 0; i < length_; ) {
3590 while (i < length_ &&
Count(i) > max_number_of_chars) i++;
3591 if (i == length_)
break;
3592 int remembered_from = i;
3593 bool union_map[kSize];
3594 for (
int j = 0; j < kSize; j++) union_map[j] =
false;
3595 while (i < length_ &&
Count(i) <= max_number_of_chars) {
3596 BoyerMoorePositionInfo* map = bitmaps_->at(i);
3597 for (
int j = 0; j < kSize; j++) union_map[j] |= map->at(j);
3601 for (
int j = 0; j < kSize; j++) {
3616 bool in_quickcheck_range = ((i - remembered_from < 4) ||
3617 (compiler_->
ascii() ? remembered_from <= 4 : remembered_from <= 2));
3620 int probability = (in_quickcheck_range ? kSize / 2 : kSize) - frequency;
3621 int points = (i - remembered_from) * probability;
3622 if (points > biggest_points) {
3623 *from = remembered_from;
3625 biggest_points = points;
3628 return biggest_points;
3637 int BoyerMooreLookahead::GetSkipTable(
int min_lookahead,
3639 Handle<ByteArray> boolean_skip_table) {
3642 const int kSkipArrayEntry = 0;
3643 const int kDontSkipArrayEntry = 1;
3645 for (
int i = 0; i < kSize; i++) {
3646 boolean_skip_table->set(i, kSkipArrayEntry);
3648 int skip = max_lookahead + 1 - min_lookahead;
3650 for (
int i = max_lookahead; i >= min_lookahead; i--) {
3651 BoyerMoorePositionInfo* map = bitmaps_->at(i);
3652 for (
int j = 0; j < kSize; j++) {
3654 boolean_skip_table->set(j, kDontSkipArrayEntry);
3667 int min_lookahead = 0;
3668 int max_lookahead = 0;
3670 if (!FindWorthwhileInterval(&min_lookahead, &max_lookahead))
return false;
3672 bool found_single_character =
false;
3673 int single_character = 0;
3674 for (
int i = max_lookahead; i >= min_lookahead; i--) {
3677 (found_single_character && map->
map_count() != 0)) {
3678 found_single_character =
false;
3681 for (
int j = 0; j < kSize; j++) {
3683 found_single_character =
true;
3684 single_character = j;
3690 int lookahead_width = max_lookahead + 1 - min_lookahead;
3692 if (found_single_character && lookahead_width == 1 && max_lookahead < 3) {
3697 if (found_single_character) {
3701 if (max_char_ > kSize) {
3716 int skip_distance = GetSkipTable(
3717 min_lookahead, max_lookahead, boolean_skip_table);
3718 ASSERT(skip_distance != 0);
3814 for (
int i = 0; i < choice_count - 1; i++) {
3817 int guard_count = (guards ==
NULL) ? 0 : guards->length();
3818 for (
int j = 0; j < guard_count; j++) {
3825 if (limit_result ==
DONE)
return;
3828 int new_flush_budget = trace->
flush_budget() / choice_count;
3830 trace->
Flush(compiler,
this);
3836 Trace* current_trace = trace;
3839 bool greedy_loop =
false;
3840 Label greedy_loop_label;
3841 Trace counter_backtrack_trace;
3856 current_trace = &counter_backtrack_trace;
3857 Label greedy_match_failed;
3858 Trace greedy_match_trace;
3862 macro_assembler->
Bind(&loop_label);
3865 alternatives_->at(0).node()->Emit(compiler, &greedy_match_trace);
3866 macro_assembler->
Bind(&greedy_match_failed);
3869 Label second_choice;
3870 macro_assembler->
Bind(&second_choice);
3872 int first_normal_choice = greedy_loop ? 1 : 0;
3875 const int kEatsAtLeastNotYetInitialized = -1;
3876 int eats_at_least = kEatsAtLeastNotYetInitialized;
3878 bool skip_was_emitted =
false;
3880 if (!greedy_loop && choice_count == 2) {
3895 if (lookahead ==
NULL) {
3899 if (eats_at_least >= 1) {
3909 skip_was_emitted = lookahead->EmitSkipInstructions(macro_assembler);
3915 if (eats_at_least == kEatsAtLeastNotYetInitialized) {
3919 int preload_characters = CalculatePreloadCharacters(compiler, eats_at_least);
3921 bool preload_is_current = !skip_was_emitted &&
3923 bool preload_has_checked_bounds = preload_is_current;
3929 for (
int i = first_normal_choice; i < choice_count; i++) {
3934 int guard_count = (guards ==
NULL) ? 0 : guards->length();
3935 Trace new_trace(*current_trace);
3937 preload_characters :
3939 if (preload_has_checked_bounds) {
3945 bool generate_full_check_inline =
false;
3946 if (FLAG_regexp_optimization &&
3950 preload_has_checked_bounds,
3953 i < choice_count - 1)) {
3955 preload_is_current =
true;
3956 preload_has_checked_bounds =
true;
3960 if (i == choice_count - 1) {
3965 generate_full_check_inline =
true;
3968 if (i == choice_count - 1 && !greedy_loop) {
3978 if (i != first_normal_choice) {
3982 if (i < choice_count - 1) {
3985 generate_full_check_inline =
true;
3987 if (generate_full_check_inline) {
3991 for (
int j = 0; j < guard_count; j++) {
3992 GenerateGuard(macro_assembler, guards->
at(j), &new_trace);
3994 alternative.
node()->
Emit(compiler, &new_trace);
3995 preload_is_current =
false;
4000 macro_assembler->
Bind(&greedy_loop_label);
4005 macro_assembler->
GoTo(&second_choice);
4011 for (
int i = first_normal_choice; i < choice_count - 1; i++) {
4013 Trace new_trace(*current_trace);
4020 EmitOutOfLineContinuation(compiler,
4030 void ChoiceNode::EmitOutOfLineContinuation(
RegExpCompiler* compiler,
4034 int preload_characters,
4035 bool next_expects_preload) {
4040 Trace out_of_line_trace(*trace);
4041 out_of_line_trace.set_characters_preloaded(preload_characters);
4043 if (not_at_start_) out_of_line_trace.set_at_start(
Trace::FALSE);
4045 int guard_count = (guards ==
NULL) ? 0 : guards->length();
4046 if (next_expects_preload) {
4047 Label reload_current_char;
4048 out_of_line_trace.set_backtrack(&reload_current_char);
4049 for (
int j = 0; j < guard_count; j++) {
4050 GenerateGuard(macro_assembler, guards->
at(j), &out_of_line_trace);
4052 alternative.
node()->
Emit(compiler, &out_of_line_trace);
4053 macro_assembler->
Bind(&reload_current_char);
4060 preload_characters);
4061 macro_assembler->
GoTo(&(alt_gen->
after));
4063 out_of_line_trace.set_backtrack(&(alt_gen->
after));
4064 for (
int j = 0; j < guard_count; j++) {
4065 GenerateGuard(macro_assembler, guards->
at(j), &out_of_line_trace);
4067 alternative.
node()->
Emit(compiler, &out_of_line_trace);
4075 if (limit_result ==
DONE)
return;
4083 new_capture(data_.u_position_register.reg,
4084 data_.u_position_register.is_capture,
4086 Trace new_trace = *trace;
4093 new_increment(data_.u_increment_register.reg);
4094 Trace new_trace = *trace;
4101 new_set(data_.u_store_register.reg, data_.u_store_register.value);
4102 Trace new_trace = *trace;
4109 new_capture(
Interval(data_.u_clear_captures.range_from,
4110 data_.u_clear_captures.range_to));
4111 Trace new_trace = *trace;
4118 trace->
Flush(compiler,
this);
4121 data_.u_submatch.current_position_register, 0);
4123 data_.u_submatch.stack_pointer_register);
4128 int start_pos_reg = data_.u_empty_match_check.start_register;
4130 int rep_reg = data_.u_empty_match_check.repetition_register;
4133 if (know_dist && !has_minimum && stored_pos == trace->
cp_offset()) {
4137 }
else if (know_dist && stored_pos < trace->cp_offset()) {
4142 trace->
Flush(compiler,
this);
4144 Label skip_empty_check;
4148 int limit = data_.u_empty_match_check.repetition_limit;
4149 assembler->
IfRegisterLT(rep_reg, limit, &skip_empty_check);
4155 assembler->
Bind(&skip_empty_check);
4162 trace->
Flush(compiler,
this);
4166 data_.u_submatch.current_position_register);
4168 data_.u_submatch.stack_pointer_register);
4170 if (clear_register_count == 0) {
4174 int clear_registers_from = data_.u_submatch.clear_register_from;
4175 Label clear_registers_backtrack;
4176 Trace new_trace = *trace;
4180 assembler->
Bind(&clear_registers_backtrack);
4181 int clear_registers_to = clear_registers_from + clear_register_count - 1;
4182 assembler->
ClearRegisters(clear_registers_from, clear_registers_to);
4197 trace->
Flush(compiler,
this);
4202 if (limit_result ==
DONE)
return;
4227 explicit DotPrinter(
bool ignore_case)
4228 : ignore_case_(ignore_case),
4229 stream_(&alloc_) { }
4230 void PrintNode(
const char* label, RegExpNode* node);
4231 void Visit(RegExpNode* node);
4232 void PrintAttributes(RegExpNode* from);
4233 StringStream* stream() {
return &stream_; }
4234 void PrintOnFailure(RegExpNode* from, RegExpNode* to);
4235 #define DECLARE_VISIT(Type) \
4236 virtual void Visit##Type(Type##Node* that);
4238 #undef DECLARE_VISIT
4241 HeapStringAllocator alloc_;
4242 StringStream stream_;
4246 void DotPrinter::PrintNode(
const char* label, RegExpNode* node) {
4247 stream()->Add(
"digraph G {\n graph [label=\"");
4248 for (
int i = 0; label[i]; i++) {
4251 stream()->Add(
"\\\\");
4254 stream()->Add(
"\"");
4257 stream()->Put(label[i]);
4261 stream()->Add(
"\"];\n");
4263 stream()->Add(
"}\n");
4268 void DotPrinter::Visit(RegExpNode* node) {
4269 if (node->info()->visited)
return;
4270 node->info()->visited =
true;
4275 void DotPrinter::PrintOnFailure(RegExpNode* from, RegExpNode* on_failure) {
4276 stream()->Add(
" n%p -> n%p [style=dotted];\n", from, on_failure);
4281 class TableEntryBodyPrinter {
4283 TableEntryBodyPrinter(StringStream* stream, ChoiceNode* choice)
4284 : stream_(stream), choice_(choice) { }
4285 void Call(
uc16 from, DispatchTable::Entry entry) {
4286 OutSet* out_set = entry.out_set();
4288 if (out_set->Get(i)) {
4289 stream()->Add(
" n%p:s%io%i -> n%p;\n",
4293 choice()->alternatives()->at(i).node());
4298 StringStream* stream() {
return stream_; }
4299 ChoiceNode* choice() {
return choice_; }
4300 StringStream* stream_;
4301 ChoiceNode* choice_;
4305 class TableEntryHeaderPrinter {
4307 explicit TableEntryHeaderPrinter(StringStream* stream)
4308 : first_(
true), stream_(stream) { }
4309 void Call(
uc16 from, DispatchTable::Entry entry) {
4315 stream()->Add(
"{\\%k-\\%k|{", from, entry.to());
4316 OutSet* out_set = entry.out_set();
4319 if (out_set->Get(i)) {
4320 if (priority > 0) stream()->Add(
"|");
4321 stream()->Add(
"<s%io%i> %i", from, i, priority);
4325 stream()->Add(
"}}");
4330 StringStream* stream() {
return stream_; }
4331 StringStream* stream_;
4335 class AttributePrinter {
4337 explicit AttributePrinter(DotPrinter* out)
4338 : out_(out), first_(
true) { }
4339 void PrintSeparator() {
4343 out_->stream()->Add(
"|");
4346 void PrintBit(
const char*
name,
bool value) {
4349 out_->stream()->Add(
"{%s}", name);
4351 void PrintPositive(
const char* name,
int value) {
4352 if (value < 0)
return;
4354 out_->stream()->Add(
"{%s|%x}", name, value);
4362 void DotPrinter::PrintAttributes(RegExpNode* that) {
4363 stream()->Add(
" a%p [shape=Mrecord, color=grey, fontcolor=grey, "
4364 "margin=0.1, fontsize=10, label=\"{",
4366 AttributePrinter printer(
this);
4367 NodeInfo* info = that->info();
4368 printer.PrintBit(
"NI", info->follows_newline_interest);
4369 printer.PrintBit(
"WI", info->follows_word_interest);
4370 printer.PrintBit(
"SI", info->follows_start_interest);
4371 Label* label = that->label();
4372 if (label->is_bound())
4373 printer.PrintPositive(
"@", label->pos());
4374 stream()->Add(
"}\"];\n");
4375 stream()->Add(
" a%p -> n%p [style=dashed, color=grey, "
4376 "arrowhead=none];\n", that, that);
4380 static const bool kPrintDispatchTable =
false;
4381 void DotPrinter::VisitChoice(ChoiceNode* that) {
4382 if (kPrintDispatchTable) {
4383 stream()->Add(
" n%p [shape=Mrecord, label=\"", that);
4384 TableEntryHeaderPrinter header_printer(stream());
4385 that->GetTable(ignore_case_)->ForEach(&header_printer);
4386 stream()->Add(
"\"]\n", that);
4387 PrintAttributes(that);
4388 TableEntryBodyPrinter body_printer(stream(), that);
4389 that->GetTable(ignore_case_)->ForEach(&body_printer);
4391 stream()->Add(
" n%p [shape=Mrecord, label=\"?\"];\n", that);
4392 for (
int i = 0; i < that->alternatives()->length(); i++) {
4393 GuardedAlternative alt = that->alternatives()->at(i);
4394 stream()->Add(
" n%p -> n%p;\n", that, alt.node());
4397 for (
int i = 0; i < that->alternatives()->length(); i++) {
4398 GuardedAlternative alt = that->alternatives()->at(i);
4399 alt.node()->Accept(
this);
4404 void DotPrinter::VisitText(TextNode* that) {
4405 Zone* zone = that->zone();
4406 stream()->Add(
" n%p [label=\"", that);
4407 for (
int i = 0; i < that->elements()->length(); i++) {
4408 if (i > 0) stream()->Add(
" ");
4409 TextElement elm = that->elements()->at(i);
4412 stream()->Add(
"'%w'", elm.data.u_atom->data());
4416 RegExpCharacterClass* node = elm.data.u_char_class;
4418 if (node->is_negated())
4420 for (
int j = 0; j < node->ranges(zone)->length(); j++) {
4421 CharacterRange range = node->ranges(zone)->at(j);
4422 stream()->Add(
"%k-%k", range.from(), range.to());
4431 stream()->Add(
"\", shape=box, peripheries=2];\n");
4432 PrintAttributes(that);
4433 stream()->Add(
" n%p -> n%p;\n", that, that->on_success());
4434 Visit(that->on_success());
4438 void DotPrinter::VisitBackReference(BackReferenceNode* that) {
4439 stream()->Add(
" n%p [label=\"$%i..$%i\", shape=doubleoctagon];\n",
4441 that->start_register(),
4442 that->end_register());
4443 PrintAttributes(that);
4444 stream()->Add(
" n%p -> n%p;\n", that, that->on_success());
4445 Visit(that->on_success());
4449 void DotPrinter::VisitEnd(EndNode* that) {
4450 stream()->Add(
" n%p [style=bold, shape=point];\n", that);
4451 PrintAttributes(that);
4455 void DotPrinter::VisitAssertion(AssertionNode* that) {
4456 stream()->Add(
" n%p [", that);
4457 switch (that->type()) {
4459 stream()->Add(
"label=\"$\", shape=septagon");
4462 stream()->Add(
"label=\"^\", shape=septagon");
4465 stream()->Add(
"label=\"\\b\", shape=septagon");
4468 stream()->Add(
"label=\"\\B\", shape=septagon");
4471 stream()->Add(
"label=\"(?<=\\n)\", shape=septagon");
4474 stream()->Add(
"];\n");
4475 PrintAttributes(that);
4476 RegExpNode* successor = that->on_success();
4477 stream()->Add(
" n%p -> n%p;\n", that, successor);
4482 void DotPrinter::VisitAction(ActionNode* that) {
4483 stream()->Add(
" n%p [", that);
4484 switch (that->type_) {
4486 stream()->Add(
"label=\"$%i:=%i\", shape=octagon",
4487 that->data_.u_store_register.reg,
4488 that->data_.u_store_register.value);
4491 stream()->Add(
"label=\"$%i++\", shape=octagon",
4492 that->data_.u_increment_register.reg);
4495 stream()->Add(
"label=\"$%i:=$pos\", shape=octagon",
4496 that->data_.u_position_register.reg);
4499 stream()->Add(
"label=\"$%i:=$pos,begin\", shape=septagon",
4500 that->data_.u_submatch.current_position_register);
4503 stream()->Add(
"label=\"escape\", shape=septagon");
4506 stream()->Add(
"label=\"$%i=$pos?,$%i<%i?\", shape=septagon",
4507 that->data_.u_empty_match_check.start_register,
4508 that->data_.u_empty_match_check.repetition_register,
4509 that->data_.u_empty_match_check.repetition_limit);
4512 stream()->Add(
"label=\"clear $%i to $%i\", shape=septagon",
4513 that->data_.u_clear_captures.range_from,
4514 that->data_.u_clear_captures.range_to);
4518 stream()->Add(
"];\n");
4519 PrintAttributes(that);
4520 RegExpNode* successor = that->on_success();
4521 stream()->Add(
" n%p -> n%p;\n", that, successor);
4526 class DispatchTableDumper {
4528 explicit DispatchTableDumper(StringStream* stream) : stream_(stream) { }
4529 void Call(
uc16 key, DispatchTable::Entry entry);
4530 StringStream* stream() {
return stream_; }
4532 StringStream* stream_;
4536 void DispatchTableDumper::Call(
uc16 key, DispatchTable::Entry entry) {
4537 stream()->Add(
"[%k-%k]: {", key, entry.to());
4538 OutSet* set = entry.out_set();
4545 stream()->Add(
", ");
4547 stream()->Add(
"%i", i);
4550 stream()->Add(
"}\n");
4555 HeapStringAllocator alloc;
4556 StringStream stream(&alloc);
4557 DispatchTableDumper dumper(&stream);
4558 tree()->ForEach(&dumper);
4566 DotPrinter printer(ignore_case);
4567 printer.PrintNode(label, node);
4582 return new(compiler->
zone())
TextNode(elms, on_success);
4593 const int* special_class,
4596 ASSERT(special_class[length] == 0x10000);
4597 ASSERT(ranges->length() != 0);
4599 ASSERT(special_class[0] != 0);
4600 if (ranges->length() != (length >> 1) + 1) {
4603 CharacterRange range = ranges->
at(0);
4604 if (range.from() != 0) {
4607 for (
int i = 0; i < length; i += 2) {
4608 if (special_class[i] != (range.to() + 1)) {
4611 range = ranges->
at((i >> 1) + 1);
4612 if (special_class[i+1] != range.from()) {
4616 if (range.to() != 0xffff) {
4623 static bool CompareRanges(ZoneList<CharacterRange>* ranges,
4624 const int* special_class,
4627 ASSERT(special_class[length] == 0x10000);
4628 if (ranges->length() * 2 != length) {
4631 for (
int i = 0; i < length; i += 2) {
4632 CharacterRange range = ranges->at(i >> 1);
4633 if (range.from() != special_class[i] ||
4634 range.to() != special_class[i + 1] - 1) {
4648 if (set_.is_standard()) {
4651 if (CompareRanges(set_.ranges(zone), kSpaceRanges, kSpaceRangeCount)) {
4652 set_.set_standard_set_type(
's');
4655 if (CompareInverseRanges(set_.ranges(zone), kSpaceRanges, kSpaceRangeCount)) {
4656 set_.set_standard_set_type(
'S');
4659 if (CompareInverseRanges(set_.ranges(zone),
4660 kLineTerminatorRanges,
4661 kLineTerminatorRangeCount)) {
4662 set_.set_standard_set_type(
'.');
4665 if (CompareRanges(set_.ranges(zone),
4666 kLineTerminatorRanges,
4667 kLineTerminatorRangeCount)) {
4668 set_.set_standard_set_type(
'n');
4671 if (CompareRanges(set_.ranges(zone), kWordRanges, kWordRangeCount)) {
4672 set_.set_standard_set_type(
'w');
4675 if (CompareInverseRanges(set_.ranges(zone), kWordRanges, kWordRangeCount)) {
4676 set_.set_standard_set_type(
'W');
4685 return new(compiler->
zone())
TextNode(
this, on_success);
4692 int length = alternatives->length();
4695 for (
int i = 0; i < length; i++) {
4721 : compiler_(compiler),
4722 saved_expansion_factor_(compiler->current_expansion_factor()),
4725 if (ok_to_expand_) {
4728 ok_to_expand_ =
false;
4731 int new_factor = saved_expansion_factor_ * factor;
4746 int saved_expansion_factor_;
4759 bool not_at_start) {
4780 static const int kMaxUnrolledMinMatches = 3;
4781 static const int kMaxUnrolledMaxMatches = 3;
4782 if (max == 0)
return on_success;
4783 bool body_can_be_empty = (body->
min_match() == 0);
4786 bool needs_capture_clearing = !capture_registers.
is_empty();
4789 if (body_can_be_empty) {
4791 }
else if (FLAG_regexp_optimization && !needs_capture_clearing) {
4796 compiler, min + ((max != min) ? 1 : 0));
4797 if (min > 0 && min <= kMaxUnrolledMinMatches && limiter.
ok_to_expand()) {
4798 int new_max = (max ==
kInfinity) ? max : max - min;
4802 0, new_max, is_greedy, body, compiler, on_success,
true);
4806 for (
int i = 0; i <
min; i++) {
4807 answer = body->
ToNode(compiler, answer);
4812 if (max <= kMaxUnrolledMaxMatches && min == 0) {
4818 for (
int i = 0; i <
max; i++) {
4829 answer = alternation;
4836 bool has_min = min > 0;
4838 bool needs_counter = has_min || has_max;
4839 int reg_ctr = needs_counter
4847 : static_cast<RegExpNode*>(center);
4848 if (body_can_be_empty) {
4857 if (body_can_be_empty) {
4862 if (needs_capture_clearing) {
4870 body_alt.
AddGuard(body_guard, zone);
4875 rest_alt.
AddGuard(rest_guard, zone);
4884 if (needs_counter) {
4930 stack_pointer_register,
4949 return new(compiler->
zone())
4967 const int registers_per_capture = 2;
4968 const int register_of_first_capture = 2;
4969 int register_count = capture_count_ * registers_per_capture;
4970 int register_start =
4971 register_of_first_capture + capture_from_ * registers_per_capture;
4976 stack_pointer_register,
5040 for (
int i = children->length() - 1; i >= 0; i--) {
5041 current = children->
at(i)->ToNode(compiler, current);
5047 static void AddClass(
const int* elmv,
5052 ASSERT(elmv[elmc] == 0x10000);
5053 for (
int i = 0; i < elmc; i += 2) {
5054 ASSERT(elmv[i] < elmv[i + 1]);
5060 static void AddClassNegated(
const int *elmv,
5062 ZoneList<CharacterRange>* ranges,
5065 ASSERT(elmv[elmc] == 0x10000);
5066 ASSERT(elmv[0] != 0x0000);
5069 for (
int i = 0; i < elmc; i += 2) {
5070 ASSERT(last <= elmv[i] - 1);
5071 ASSERT(elmv[i] < elmv[i + 1]);
5072 ranges->Add(CharacterRange(last, elmv[i] - 1), zone);
5084 AddClass(kSpaceRanges, kSpaceRangeCount, ranges, zone);
5087 AddClassNegated(kSpaceRanges, kSpaceRangeCount, ranges, zone);
5090 AddClass(kWordRanges, kWordRangeCount, ranges, zone);
5093 AddClassNegated(kWordRanges, kWordRangeCount, ranges, zone);
5096 AddClass(kDigitRanges, kDigitRangeCount, ranges, zone);
5099 AddClassNegated(kDigitRanges, kDigitRangeCount, ranges, zone);
5102 AddClassNegated(kLineTerminatorRanges,
5103 kLineTerminatorRangeCount,
5116 AddClass(kLineTerminatorRanges,
5117 kLineTerminatorRangeCount,
5137 : included_(included),
5138 excluded_(excluded),
5170 for (
int i = 0; i < base->length(); i++)
5172 for (
int i = 0; i < overlay.
length(); i += 2) {
5184 Isolate* isolate = Isolate::Current();
5192 if (top == bottom) {
5195 for (
int i = 0; i < length; i++) {
5196 uc32 chr = chars[i];
5197 if (chr != bottom) {
5222 while (pos <= top) {
5229 block_end = range[0];
5231 int end = (block_end > top) ? top : block_end;
5233 for (
int i = 0; i < length; i++) {
5235 uc16 range_from = c - (block_end - pos);
5236 uc16 range_to = c - (block_end - end);
5237 if (!(bottom <= range_from && range_to <= top)) {
5249 int n = ranges->length();
5250 if (n <= 1)
return true;
5251 int max = ranges->
at(0).to();
5252 for (
int i = 1; i < n; i++) {
5254 if (next_range.
from() <= max + 1)
return false;
5255 max = next_range.
to();
5262 if (ranges_ ==
NULL) {
5272 static void MoveRanges(ZoneList<CharacterRange>* list,
5278 for (
int i = count - 1; i >= 0; i--) {
5279 list->at(to + i) = list->at(from + i);
5282 for (
int i = 0; i < count; i++) {
5283 list->at(to + i) = list->at(from + i);
5289 static int InsertRangeInCanonicalList(ZoneList<CharacterRange>* list,
5291 CharacterRange insert) {
5297 uc16 from = insert.from();
5298 uc16 to = insert.to();
5300 int end_pos = count;
5301 for (
int i = count - 1; i >= 0; i--) {
5302 CharacterRange current = list->at(i);
5303 if (current.from() > to + 1) {
5305 }
else if (current.to() + 1 < from) {
5318 if (start_pos == end_pos) {
5320 if (start_pos < count) {
5321 MoveRanges(list, start_pos, start_pos + 1, count - start_pos);
5323 list->at(start_pos) = insert;
5326 if (start_pos + 1 == end_pos) {
5328 CharacterRange to_replace = list->at(start_pos);
5329 int new_from =
Min(to_replace.from(), from);
5330 int new_to =
Max(to_replace.to(), to);
5331 list->at(start_pos) = CharacterRange(new_from, new_to);
5337 int new_from =
Min(list->at(start_pos).from(), from);
5338 int new_to =
Max(list->at(end_pos - 1).to(), to);
5339 if (end_pos < count) {
5340 MoveRanges(list, end_pos, start_pos + 1, count - end_pos);
5342 list->at(start_pos) = CharacterRange(new_from, new_to);
5343 return count - (end_pos - start_pos) + 1;
5350 if (ranges_ ==
NULL)
return;
5356 if (character_ranges->length() <= 1)
return;
5359 int n = character_ranges->length();
5360 int max = character_ranges->
at(0).to();
5364 if (current.
from() <= max + 1) {
5379 int num_canonical = i;
5381 num_canonical = InsertRangeInCanonicalList(character_ranges,
5383 character_ranges->
at(read));
5386 character_ranges->Rewind(num_canonical);
5397 int range_count = ranges->length();
5400 if (range_count > 0 && ranges->
at(0).from() == 0) {
5401 from = ranges->
at(0).to();
5404 while (i < range_count) {
5424 if (successors(zone) !=
NULL) {
5425 for (
int i = 0; i < successors(zone)->length(); i++) {
5426 OutSet* successor = successors(zone)->at(i);
5427 if (successor->
Get(value))
5434 result->Set(value, zone);
5435 successors(zone)->Add(result, zone);
5440 void OutSet::Set(
unsigned value,
Zone *zone) {
5442 first_ |= (1 << value);
5444 if (remaining_ ==
NULL)
5445 remaining_ =
new(zone) ZoneList<unsigned>(1, zone);
5446 if (remaining_->is_empty() || !remaining_->
Contains(value))
5447 remaining_->
Add(value, zone);
5454 return (first_ & (1 << value)) != 0;
5455 }
else if (remaining_ ==
NULL) {
5458 return remaining_->
Contains(value);
5469 if (tree()->is_empty()) {
5474 empty()->
Extend(value, zone)));
5480 if (tree()->FindGreatestLessThan(current.
from(), &loc)) {
5481 Entry* entry = &loc.value();
5486 if (entry->
from() < current.
from() && entry->
to() >= current.
from()) {
5493 entry->
set_to(left.to());
5499 loc.set_value(
Entry(right.from(),
5505 if (tree()->FindLeastGreaterThan(current.
from(), &loc) &&
5506 (loc.value().from() <= current.
to()) &&
5507 (loc.value().to() >= current.
from())) {
5508 Entry* entry = &loc.value();
5512 if (current.
from() < entry->
from()) {
5517 empty()->
Extend(value, zone)));
5523 if (entry->
to() > current.
to()) {
5526 ins.set_value(
Entry(current.
to() + 1,
5548 empty()->
Extend(value, zone)));
5557 if (!tree()->FindGreatestLessThan(value, &loc))
5559 Entry* entry = &loc.value();
5560 if (value <= entry->to())
5572 StackLimitCheck
check(Isolate::Current());
5573 if (check.HasOverflowed()) {
5574 fail(
"Stack overflow");
5586 void Analysis::VisitEnd(
EndNode* that) {
5592 int element_count =
elements()->length();
5596 for (
int i = 0; i < element_count; i++) {
5608 void Analysis::VisitText(
TextNode* that) {
5619 void Analysis::VisitAction(ActionNode* that) {
5620 RegExpNode* target = that->on_success();
5625 that->info()->AddFromFollowing(target->info());
5630 void Analysis::VisitChoice(ChoiceNode* that) {
5631 NodeInfo* info = that->info();
5632 for (
int i = 0; i < that->alternatives()->length(); i++) {
5633 RegExpNode* node = that->alternatives()->at(i).node();
5638 info->AddFromFollowing(node->info());
5645 for (
int i = 0; i < that->
alternatives()->length(); i++) {
5667 void Analysis::VisitAssertion(AssertionNode* that) {
5673 int recursion_depth,
5676 bool not_at_start) {
5689 int recursion_depth,
5692 bool not_at_start) {
5694 budget = (budget - 1) / alts->length();
5695 for (
int i = 0; i < alts->length(); i++) {
5703 offset, recursion_depth + 1, budget, bm, not_at_start);
5710 int recursion_depth,
5713 bool not_at_start) {
5714 if (initial_offset >= bm->
length())
return;
5715 int offset = initial_offset;
5717 for (
int i = 0; i <
elements()->length(); i++) {
5718 if (offset >= bm->
length()) {
5719 if (initial_offset == 0)
set_bm_info(not_at_start, bm);
5725 for (
int j = 0; j < atom->
length(); j++, offset++) {
5726 if (offset >= bm->
length()) {
5727 if (initial_offset == 0)
set_bm_info(not_at_start, bm);
5733 int length = GetCaseIndependentLetters(
5738 for (
int j = 0; j < length; j++) {
5739 bm->
Set(offset, chars[j]);
5742 if (character <= max_char) bm->
Set(offset, character);
5752 for (
int k = 0; k < ranges->length(); k++) {
5754 if (range.
from() > max_char)
continue;
5755 int to =
Min(max_char, static_cast<int>(range.
to()));
5762 if (offset >= bm->
length()) {
5763 if (initial_offset == 0)
set_bm_info(not_at_start, bm);
5767 recursion_depth + 1,
5771 if (initial_offset == 0)
set_bm_info(not_at_start, bm);
5779 void DispatchTableConstructor::VisitEnd(
EndNode* that) {
5787 for (
int i = 0; i < alternatives->length(); i++) {
5789 alternatives->
at(i).node()->Accept(
this);
5798 : constructor_(constructor) { }
5811 void DispatchTableConstructor::VisitChoice(
ChoiceNode* node) {
5820 void DispatchTableConstructor::VisitBackReference(BackReferenceNode* that) {
5827 void DispatchTableConstructor::VisitAssertion(AssertionNode* that) {
5828 RegExpNode* target = that->on_success();
5829 target->Accept(
this);
5833 static int CompareRangeByFrom(
const CharacterRange* a,
5834 const CharacterRange* b) {
5835 return Compare<uc16>(a->from(), b->from());
5840 ranges->
Sort(CompareRangeByFrom);
5842 for (
int i = 0; i < ranges->length(); i++) {
5844 if (last < range.
from())
5846 if (range.
to() >= last) {
5850 last = range.
to() + 1;
5858 void DispatchTableConstructor::VisitText(
TextNode* that) {
5868 ZoneList<CharacterRange>* ranges = tree->
ranges(that->
zone());
5869 if (tree->is_negated()) {
5872 for (
int i = 0; i < ranges->length(); i++)
5884 void DispatchTableConstructor::VisitAction(ActionNode* that) {
5885 RegExpNode* target = that->on_success();
5886 target->Accept(
this);
5900 return IrregexpRegExpTooBig();
5908 int chars_sampled = 0;
5909 int half_way = (sample_subject->length() -
kSampleSize) / 2;
5910 for (
int i =
Max(0, half_way);
5911 i < sample_subject->length() && chars_sampled <
kSampleSize;
5912 i++, chars_sampled++) {
5925 if (!is_start_anchored) {
5944 node = first_step_node;
5958 Analysis analysis(ignore_case, is_ascii);
5966 #ifndef V8_INTERPRETED_REGEXP
5973 #if V8_TARGET_ARCH_IA32
5976 #elif V8_TARGET_ARCH_X64
5979 #elif V8_TARGET_ARCH_ARM
5982 #elif V8_TARGET_ARCH_MIPS
5987 #else // V8_INTERPRETED_REGEXP
5990 RegExpMacroAssemblerIrregexp macro_assembler(codes);
5991 #endif // V8_INTERPRETED_REGEXP
5995 static const int kMaxBacksearchLimit = 1024;
5996 if (is_end_anchored &&
5997 !is_start_anchored &&
5998 max_length < kMaxBacksearchLimit) {
5999 macro_assembler.SetCurrentPositionFromEnd(max_length);
6003 macro_assembler.set_global_mode(
6009 return compiler.
Assemble(¯o_assembler,
void SetInterval(const Interval &interval)
ZoneList< TextElement > * elements()
AlternativeGenerationList(int count, Zone *zone)
static bool ParseRegExp(FlatStringReader *input, bool multiline, RegExpCompileData *result)
virtual void WriteStackPointerToRegister(int reg)=0
static Handle< Object > New(Handle< JSFunction > func, int argc, Handle< Object > argv[], bool *pending_exception)
bool EmitCharacterFunction(Isolate *isolate, RegExpCompiler *compiler, uc16 c, Label *on_failure, int cp_offset, bool check, bool preloaded)
Failure * StackOverflow()
virtual void FillInBMInfo(int offset, int recursion_depth, int budget, BoyerMooreLookahead *bm, bool not_at_start)
void FlattenString(Handle< String > string)
static const int kNumberOfRegistersOffset
int GreedyLoopTextLengthForAlternative(GuardedAlternative *alternative)
bool is_standard(Zone *zone)
static const int kIrregexpMaxRegisterCountIndex
double total_regexp_code_generated()
static const int kMaxAsciiCharCode
bool Contains(const T &elm) const
#define DECLARE_VISIT(type)
static Vector< const int > GetWordBounds()
#define ASSERT_RESULT(expr)
virtual void GoTo(Label *label)=0
static AssertionNode * AtStart(RegExpNode *on_success)
const char * ToCString(const v8::String::Utf8Value &value)
void SetInterval(int map_number, const Interval &interval)
static ActionNode * SetRegister(int reg, int val, RegExpNode *on_success)
RegExpEngine::CompilationResult Assemble(RegExpMacroAssembler *assembler, RegExpNode *start, int capture_count, Handle< String > pattern)
static Code * IrregexpNativeCode(FixedArray *re, bool is_ascii)
void set(int index, Object *value)
CompilationCache * compilation_cache()
CharacterRangeSplitter(ZoneList< CharacterRange > **included, ZoneList< CharacterRange > **excluded, Zone *zone)
static const int kStaticOffsetsVectorSize
void PrintF(const char *format,...)
virtual void Emit(RegExpCompiler *compiler, Trace *trace)
static String * cast(Object *obj)
static ActionNode * BeginSubmatch(int stack_pointer_reg, int position_reg, RegExpNode *on_success)
virtual int EatsAtLeast(int still_to_find, int recursion_depth, bool not_at_start)
virtual void Emit(RegExpCompiler *compiler, Trace *trace)
static const int kMaxUtf16CodeUnit
void set_characters(int characters)
virtual int EatsAtLeast(int still_to_find, int recursion_depth, bool not_at_start)
unibrow::Mapping< unibrow::Ecma262UnCanonicalize > * jsregexp_uncanonicalize()
VisitMarker(NodeInfo *info)
virtual RegExpNode * ToNode(RegExpCompiler *compiler, RegExpNode *on_success)
virtual void AppendToText(RegExpText *text, Zone *zone)
virtual RegExpNode * GetSuccessorOfOmnivorousTextNode(RegExpCompiler *compiler)
static Smi * FromInt(int value)
#define LOG(isolate, Call)
ZoneList< CharacterRange > * ranges(Zone *zone)
void set_at_start(bool at_start)
virtual void CheckNotBackReference(int start_reg, Label *on_no_match)=0
#define ASSERT_NOT_NULL(p)
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
bool EmitQuickCheck(RegExpCompiler *compiler, Trace *trace, bool preload_has_checked_bounds, Label *on_possible_success, QuickCheckDetails *details_return, bool fall_through_on_failure)
void set_loop_label(Label *label)
static Handle< T > cast(Handle< S > that)
static ActionNode * EmptyMatchCheck(int start_register, int repetition_register, int repetition_limit, RegExpNode *on_success)
virtual void ClearRegisters(int reg_from, int reg_to)=0
Position * positions(int index)
virtual RegExpNode * ToNode(RegExpCompiler *compiler, RegExpNode *on_success)
virtual RegExpNode * GetSuccessorOfOmnivorousTextNode(RegExpCompiler *compiler)
LimitResult LimitVersions(RegExpCompiler *compiler, Trace *trace)
virtual void Emit(RegExpCompiler *compiler, Trace *trace)
static Handle< Object > CreateRegExpLiteral(Handle< JSFunction > constructor, Handle< String > pattern, Handle< String > flags, bool *has_pending_exception)
Vector< const char > ToAsciiVector()
static TextElement CharClass(RegExpCharacterClass *char_class)
virtual RegExpNode * FilterASCII(int depth)
void AddFromFollowing(NodeInfo *that)
static int IrregexpPrepare(Handle< JSRegExp > regexp, Handle< String > subject, Zone *zone)
void AddRange(CharacterRange range, int value, Zone *zone)
static ActionNode * IncrementRegister(int reg, RegExpNode *on_success)
virtual RegExpNode * ToNode(RegExpCompiler *compiler, RegExpNode *on_success)=0
static ByteArray * cast(Object *obj)
static int IrregexpExecRaw(Handle< JSRegExp > regexp, Handle< String > subject, int index, Vector< int > registers, Zone *zone)
static int IrregexpNumberOfCaptures(FixedArray *re)
virtual RegExpNode * ToNode(RegExpCompiler *compiler, RegExpNode *on_success)
virtual void LoadCurrentCharacter(int cp_offset, Label *on_end_of_input, bool check_bounds=true, int characters=1)=0
static void Canonicalize(ZoneList< CharacterRange > *ranges)
virtual void GetQuickCheckDetails(QuickCheckDetails *details, RegExpCompiler *compiler, int characters_filled_in, bool not_at_start)
Handle< FixedArray > LookupRegExp(Handle< String > source, JSRegExp::Flags flags)
void EnsureAnalyzed(RegExpNode *node)
virtual int EatsAtLeast(int still_to_find, int recursion_depth, bool not_at_start)
void set_flush_budget(int to)
static CharacterRange Everything()
virtual bool IsAnchoredAtEnd()
RegExpCompiler(int capture_count, bool ignore_case, bool is_ascii, Zone *zone)
virtual bool try_to_emit_quick_check_for_alternative(int i)
void AddValue(int value, Zone *zone)
unibrow::Mapping< unibrow::Ecma262Canonicalize > Canonicalize
static int GlobalOffsetsVectorSize(Handle< JSRegExp > regexp, int registers_per_match, int *max_matches)
#define ASSERT(condition)
static ActionNode * StorePosition(int reg, bool is_capture, RegExpNode *on_success)
int current_expansion_factor()
#define ASSERT_GE(v1, v2)
void set_characters_preloaded(int count)
const int kPatternTooShortForBoyerMoore
virtual int EatsAtLeast(int still_to_find, int recursion_depth, bool not_at_start)
struct v8::internal::ActionNode::@6::@8 u_increment_register
void AdvanceCurrentPositionInTrace(int by, RegExpCompiler *compiler)
const char * error_message()
RegExpCompiler * compiler()
void BuildTable(ChoiceNode *node)
virtual void ReadCurrentPositionFromRegister(int reg)=0
virtual int EatsAtLeast(int still_to_find, int recursion_depth, bool not_at_start)
bool EmitSkipInstructions(RegExpMacroAssembler *masm)
#define DEFINE_ACCEPT(Type)
ZoneList< TextElement > * elements()
void SetAll(int map_number)
virtual void PopCurrentPosition()=0
struct v8::internal::ActionNode::@6::@12 u_clear_captures
static Code * cast(Object *obj)
static void SetLastSubject(FixedArray *array, String *to)
static void Negate(ZoneList< CharacterRange > *src, ZoneList< CharacterRange > *dst, Zone *zone)
static Handle< Object > AtomExec(Handle< JSRegExp > regexp, Handle< String > subject, int index, Handle< JSArray > lastMatchInfo)
static Smi * cast(Object *object)
Handle< String > FlattenGetString(Handle< String > string)
static const int kRegExpExecutableMemoryLimit
virtual void Emit(RegExpCompiler *compiler, Trace *trace)=0
static ActionNode * PositiveSubmatchSuccess(int stack_pointer_reg, int restore_reg, int clear_capture_count, int clear_capture_from, RegExpNode *on_success)
static const int kNoRegister
static const int kMaxExpansionFactor
virtual void AdvanceCurrentPosition(int by)=0
int get(uchar c, uchar n, uchar *result)
RegExpMacroAssembler * macro_assembler()
static void Split(ZoneList< CharacterRange > *base, Vector< const int > overlay, ZoneList< CharacterRange > **included, ZoneList< CharacterRange > **excluded, Zone *zone)
virtual RegExpNode * ToNode(RegExpCompiler *compiler, RegExpNode *on_success)
RegExpCharacterClass * u_char_class
SmartArrayPointer< char > ToCString(AllowNullsFlag allow_nulls, RobustnessFlag robustness_flag, int offset, int length, int *length_output=0)
RegExpNode * FilterSuccessor(int depth)
static void SetLastInput(FixedArray *array, String *to)
virtual void FillInBMInfo(int offset, int recursion_depth, int budget, BoyerMooreLookahead *bm, bool not_at_start)
virtual Interval CaptureRegisters()
static const int kRegWxpCompiledLimit
void Advance(int by, bool ascii)
void Merge(QuickCheckDetails *other, int from_index)
void IncrementRecursionDepth()
struct v8::internal::ActionNode::@6::@11 u_empty_match_check
virtual bool CanReadUnaligned()
RegExpExpansionLimiter(RegExpCompiler *compiler, int factor)
void IncreaseTotalRegexpCodeGenerated(int size)
virtual int EatsAtLeast(int still_to_find, int recursion_depth, bool not_at_start)
virtual void Emit(RegExpCompiler *compiler, Trace *trace)
STATIC_ASSERT((FixedDoubleArray::kHeaderSize &kDoubleAlignmentMask)==0)
union v8::internal::TextElement::@5 data
static const unsigned kFirstLimit
void AddAlternative(GuardedAlternative node)
static void SetLastCaptureCount(FixedArray *array, int to)
void fail(const char *error_message)
AlternativeGeneration * at(int i)
virtual void CheckCharacterGT(uc16 limit, Label *on_greater)=0
void Call(uc32 from, DispatchTable::Entry entry)
virtual void FillInBMInfo(int offset, int recursion_depth, int budget, BoyerMooreLookahead *bm, bool not_at_start)
void set_bound_checked_up_to(int to)
void set_backtrack(Label *backtrack)
static const int kTableSizeBits
static const int kInfinity
virtual void GetQuickCheckDetails(QuickCheckDetails *details, RegExpCompiler *compiler, int characters_filled_in, bool not_at_start)
virtual void Accept(NodeVisitor *visitor)
virtual RegExpNode * ToNode(RegExpCompiler *compiler, RegExpNode *on_success)
v8::Handle< v8::Object > bottom
static const int kTableSize
MemoryAllocator * memory_allocator()
virtual RegExpNode * FilterASCII(int depth)
virtual void GetQuickCheckDetails(QuickCheckDetails *details, RegExpCompiler *compiler, int characters_filled_in, bool not_at_start)
struct v8::internal::ActionNode::@6::@10 u_submatch
void set_slow_safe(bool ssc)
void AddWork(RegExpNode *node)
static bool IsCanonical(ZoneList< CharacterRange > *ranges)
QuickCheckDetails * quick_check_performed()
virtual int EatsAtLeast(int still_to_find, int recursion_depth, bool not_at_start)=0
void AddGuard(Guard *guard, Zone *zone)
static int StartRegister(int index)
static Handle< Object > IrregexpExec(Handle< JSRegExp > regexp, Handle< String > subject, int index, Handle< JSArray > lastMatchInfo, Zone *zone)
void set_bm_info(bool not_at_start, BoyerMooreLookahead *bm)
void AddInverse(ZoneList< CharacterRange > *ranges)
virtual int EatsAtLeast(int still_to_find, int recursion_depth, bool not_at_start)
virtual void VisitLoopChoice(LoopChoiceNode *that)
ZoneList< RegExpTree * > * alternatives()
virtual int min_match()=0
void AddCaseEquivalents(ZoneList< CharacterRange > *ranges, bool is_ascii, Zone *zone)
struct v8::internal::ActionNode::@6::@7 u_store_register
virtual void Emit(RegExpCompiler *compiler, Trace *trace)
virtual void ReadStackPointerFromRegister(int reg)=0
static void IrregexpInitialize(Handle< JSRegExp > re, Handle< String > pattern, JSRegExp::Flags flags, int capture_register_count)
virtual void IfRegisterLT(int reg, int comparand, Label *if_lt)=0
virtual void CheckNotBackReferenceIgnoreCase(int start_reg, Label *on_no_match)=0
static const int kInOverlay
static RegExpImpl::IrregexpResult Match(Isolate *isolate, Handle< ByteArray > code, Handle< String > subject, int *captures, int start_position)
Handle< String > NewStringFromTwoByte(Vector< const uc16 > str, PretenureFlag pretenure=NOT_TENURED)
QuickCheckDetails quick_check_details
Vector< const uc16 > ToUC16Vector()
virtual RegExpNode * FilterASCII(int depth)
const int kMaxLookaheadForBoyerMoore
ContainedInLattice Combine(ContainedInLattice a, ContainedInLattice b)
static const int kMapSize
static Handle< Object > Exec(Handle< JSRegExp > regexp, Handle< String > subject, int index, Handle< JSArray > lastMatchInfo, Zone *zone)
bool determines_perfectly
#define ASSERT_LE(v1, v2)
virtual void CheckNotAtStart(Label *on_not_at_start)=0
void add_action(DeferredAction *new_action)
virtual void Emit(RegExpCompiler *compiler, Trace *trace)
bool has_pending_exception()
BoyerMooreLookahead(int length, RegExpCompiler *compiler, Zone *zone)
virtual void CheckCharacter(unsigned c, Label *on_equal)=0
void SaveBMInfo(BoyerMooreLookahead *bm, bool not_at_start, int offset)
static const int kMaxRegister
static const int kIrregexpCaptureCountIndex
void AddRange(CharacterRange range)
virtual void FillInBMInfo(int offset, int recursion_depth, int budget, BoyerMooreLookahead *bm, bool not_at_start)
void set_being_calculated(bool b)
static void AtomCompile(Handle< JSRegExp > re, Handle< String > pattern, JSRegExp::Flags flags, Handle< String > match_pattern)
virtual RegExpNode * ToNode(RegExpCompiler *compiler, RegExpNode *on_success)
virtual RegExpNode * ToNode(RegExpCompiler *compiler, RegExpNode *on_success)
int characters_preloaded()
DeferredAction * actions()
static const int kNodeIsTooComplexForGreedyLoops
virtual void FillInBMInfo(int offset, int recursion_depth, int budget, BoyerMooreLookahead *bm, bool not_at_start)
void PutRegExp(Handle< String > source, JSRegExp::Flags flags, Handle< FixedArray > data)
Vector< const char > CStrVector(const char *data)
DispatchTable * GetTable(bool ignore_case)
static int IrregexpMaxRegisterCount(FixedArray *re)
void CountCharacter(int character)
RegExpNode * on_success()
static void SetIrregexpMaxRegisterCount(FixedArray *re, int value)
virtual void PushCurrentPosition()=0
static const int kTableMask
BoyerMooreLookahead * bm_info(bool not_at_start)
#define ASSERT_LT(v1, v2)
static const int kLastMatchOverhead
~AlternativeGenerationList()
void set_from(uc16 value)
FlatContent GetFlatContent()
virtual void AppendToText(RegExpText *text, Zone *zone)
virtual RegExpNode * ToNode(RegExpCompiler *compiler, RegExpNode *on_success)
int bound_checked_up_to()
intptr_t SizeExecutable()
virtual int GreedyLoopTextLength()
virtual bool CheckSpecialCharacterClass(uc16 type, Label *on_no_match)
static const int kMaxRecursion
void AddContinueAlternative(GuardedAlternative alt)
struct v8::internal::ActionNode::@6::@9 u_position_register
bool GetStoredPosition(int reg, int *cp_offset)
static AssertionNode * AfterNewline(RegExpNode *on_success)
FrequencyCollator * frequency_collator()
void Sort(int(*cmp)(const T *x, const T *y))
static AssertionNode * AtNonBoundary(RegExpNode *on_success)
virtual void WriteCurrentPositionToRegister(int reg, int cp_offset)=0
static const int kMaxWidth
virtual void VisitLoopChoice(LoopChoiceNode *that)
static const int kAtomPatternIndex
virtual void GetQuickCheckDetails(QuickCheckDetails *details, RegExpCompiler *compiler, int characters_filled_in, bool not_at_start)
virtual void Bind(Label *label)=0
virtual void GetQuickCheckDetails(QuickCheckDetails *details, RegExpCompiler *compiler, int characters_filled_in, bool not_at_start)=0
int Count(int map_number)
void MakeCaseIndependent(bool is_ascii)
virtual void CheckCharacterLT(uc16 limit, Label *on_less)=0
ZoneList< GuardedAlternative > * alternatives()
virtual bool IsAnchoredAtStart()
static int code_index(bool is_ascii)
static void PrintError(const char *format,...)
void DecrementRecursionDepth()
static Handle< T > null()
int SearchString(Isolate *isolate, Vector< const SubjectChar > subject, Vector< const PatternChar > pattern, int start_index)
virtual RegExpNode * FilterASCII(int depth)
void SetRest(int from_map)
Vector< const uc16 > data()
static Result Match(Handle< Code > regexp, Handle< String > subject, int *offsets_vector, int offsets_vector_length, int previous_index, Isolate *isolate)
virtual void Backtrack()=0
#define ASSERT_EQ(v1, v2)
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
void ForEach(Callback *callback)
virtual void AppendToText(RegExpText *text, Zone *zone)
OutSet * Extend(unsigned value, Zone *zone)
static void DotPrint(const char *label, RegExpNode *node, bool ignore_case)
static const uchar kBadChar
virtual RegExpNode * ToNode(RegExpCompiler *compiler, RegExpNode *on_success)
ZoneList< GuardedAlternative > * alternatives_
static const unsigned kMaxAsciiCharCodeU
virtual void CheckCharacterAfterAnd(unsigned c, unsigned and_with, Label *on_equal)=0
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 true
ContainedInLattice AddRange(ContainedInLattice containment, const int *ranges, int ranges_length, Interval new_range)
virtual void IfRegisterEqPos(int reg, Label *if_eq)=0
virtual int GreedyLoopTextLength()
static ByteArray * IrregexpByteCode(FixedArray *re, bool is_ascii)
static FixedArray * cast(Object *obj)
virtual void Emit(RegExpCompiler *compiler, Trace *trace)
void set_current_expansion_factor(int value)
static ActionNode * ClearCaptures(Interval range, RegExpNode *on_success)
static const int kCodeOffset
void Set(int map_number, int character)
static const int kImplementationOffset
static int IrregexpNumberOfRegisters(FixedArray *re)
virtual void CheckBitInTable(Handle< ByteArray > table, Label *on_bit_set)=0
virtual RegExpNode * FilterASCII(int depth)
unibrow::Mapping< unibrow::CanonicalizationRange > * jsregexp_canonrange()
static const int kCompilationErrorValue
void Add(const T &element, AllocationPolicy allocator=AllocationPolicy())
virtual void AppendToText(RegExpText *text, Zone *zone)
bool Rationalize(bool ascii)
virtual void CheckGreedyLoop(Label *on_tos_equals_current_position)=0
void AddLoopAlternative(GuardedAlternative alt)
void set_choice_index(int value)
virtual void Accept(NodeVisitor *visitor)=0
int EatsAtLeastHelper(int still_to_find, int recursion_depth, RegExpNode *ignore_this_node, bool not_at_start)
static Handle< Object > Compile(Handle< JSRegExp > re, Handle< String > pattern, Handle< String > flags)
static TextElement Atom(RegExpAtom *atom)
ZoneList< Guard * > * guards()
static const int kFillInBMBudget
static int EndRegister(int index)
virtual void Emit(RegExpCompiler *compiler, Trace *trace)
#define FOR_EACH_NODE_TYPE(VISIT)
void Call(uc16 from, DispatchTable::Entry entry)
virtual int max_match()=0
~RegExpExpansionLimiter()
void Flush(RegExpCompiler *compiler, RegExpNode *successor)
static const int kUninitializedValue
ZoneList< RegExpTree * > * nodes()
void set_quick_check_performed(QuickCheckDetails *d)
void check(i::Vector< const char > string)
void InvalidateCurrentCharacter()
virtual void CheckNotCharacter(unsigned c, Label *on_not_equal)=0
static void AddClassEscape(uc16 type, ZoneList< CharacterRange > *ranges, Zone *zone)
static int saved_code_index(bool is_ascii)
virtual RegExpNode * ToNode(RegExpCompiler *compiler, RegExpNode *on_success)
int Frequency(int in_character)
virtual void CheckPosition(int cp_offset, Label *on_outside_input)
RecursionCheck(RegExpCompiler *compiler)
static CharacterRange Singleton(uc16 value)
static AssertionNode * AtEnd(RegExpNode *on_success)
virtual RegExpNode * ToNode(RegExpCompiler *compiler, RegExpNode *on_success)
virtual void FillInBMInfo(int offset, int recursion_depth, int budget, BoyerMooreLookahead *bm, bool not_at_start)
void AddElement(TextElement elm, Zone *zone)
virtual void CheckNotCharacterAfterAnd(unsigned c, unsigned and_with, Label *on_not_equal)=0
virtual Handle< HeapObject > GetCode(Handle< String > source)=0
AddDispatchRange(DispatchTableConstructor *constructor)
virtual void GetQuickCheckDetails(QuickCheckDetails *details, RegExpCompiler *compiler, int filled_in, bool not_at_start)
virtual void IfRegisterGE(int reg, int comparand, Label *if_ge)=0
void set_stop_node(RegExpNode *node)
virtual void PushBacktrack(Label *label)=0
static CompilationResult Compile(RegExpCompileData *input, bool ignore_case, bool global, bool multiline, Handle< String > pattern, Handle< String > sample_subject, bool is_ascii, Zone *zone)
virtual RegExpNode * FilterASCII(int depth)
virtual void FillInBMInfo(int offset, int recursion_depth, int budget, BoyerMooreLookahead *bm, bool not_at_start)
static void SetCapture(FixedArray *array, int index, int to)
static AssertionNode * AtBoundary(RegExpNode *on_success)
bool mentions_reg(int reg)
static const int kMaxCPOffset