| OLD | NEW |
| 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 873 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 884 | 884 |
| 885 | 885 |
| 886 TextElement TextElement::CharClass( | 886 TextElement TextElement::CharClass( |
| 887 RegExpCharacterClass* char_class) { | 887 RegExpCharacterClass* char_class) { |
| 888 TextElement result = TextElement(CHAR_CLASS); | 888 TextElement result = TextElement(CHAR_CLASS); |
| 889 result.data.u_char_class = char_class; | 889 result.data.u_char_class = char_class; |
| 890 return result; | 890 return result; |
| 891 } | 891 } |
| 892 | 892 |
| 893 | 893 |
| 894 DispatchTable* ChoiceNode::GetTable(bool ignore_case) { |
| 895 if (table_ == NULL) { |
| 896 table_ = new DispatchTable(); |
| 897 DispatchTableConstructor cons(table_, ignore_case); |
| 898 cons.BuildTable(this); |
| 899 } |
| 900 return table_; |
| 901 } |
| 902 |
| 903 |
| 894 class RegExpCompiler { | 904 class RegExpCompiler { |
| 895 public: | 905 public: |
| 896 RegExpCompiler(int capture_count, bool ignore_case); | 906 RegExpCompiler(int capture_count, bool ignore_case); |
| 897 | 907 |
| 898 int AllocateRegister() { return next_register_++; } | 908 int AllocateRegister() { return next_register_++; } |
| 899 | 909 |
| 900 Handle<FixedArray> Assemble(RegExpMacroAssembler* assembler, | 910 Handle<FixedArray> Assemble(RegExpMacroAssembler* assembler, |
| 901 RegExpNode* start, | 911 RegExpNode* start, |
| 902 int capture_count); | 912 int capture_count); |
| 903 | 913 |
| (...skipping 644 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1548 | 1558 |
| 1549 // ------------------------------------------------------------------- | 1559 // ------------------------------------------------------------------- |
| 1550 // Dot/dotty output | 1560 // Dot/dotty output |
| 1551 | 1561 |
| 1552 | 1562 |
| 1553 #ifdef DEBUG | 1563 #ifdef DEBUG |
| 1554 | 1564 |
| 1555 | 1565 |
| 1556 class DotPrinter: public NodeVisitor { | 1566 class DotPrinter: public NodeVisitor { |
| 1557 public: | 1567 public: |
| 1558 DotPrinter() : stream_(&alloc_) { } | 1568 explicit DotPrinter(bool ignore_case) |
| 1569 : ignore_case_(ignore_case), |
| 1570 stream_(&alloc_) { } |
| 1559 void PrintNode(const char* label, RegExpNode* node); | 1571 void PrintNode(const char* label, RegExpNode* node); |
| 1560 void Visit(RegExpNode* node); | 1572 void Visit(RegExpNode* node); |
| 1561 void PrintOnFailure(RegExpNode* from, RegExpNode* on_failure); | 1573 void PrintOnFailure(RegExpNode* from, RegExpNode* on_failure); |
| 1562 void PrintAttributes(RegExpNode* from); | 1574 void PrintAttributes(RegExpNode* from); |
| 1563 StringStream* stream() { return &stream_; } | 1575 StringStream* stream() { return &stream_; } |
| 1564 #define DECLARE_VISIT(Type) \ | 1576 #define DECLARE_VISIT(Type) \ |
| 1565 virtual void Visit##Type(Type##Node* that); | 1577 virtual void Visit##Type(Type##Node* that); |
| 1566 FOR_EACH_NODE_TYPE(DECLARE_VISIT) | 1578 FOR_EACH_NODE_TYPE(DECLARE_VISIT) |
| 1567 #undef DECLARE_VISIT | 1579 #undef DECLARE_VISIT |
| 1568 private: | 1580 private: |
| 1581 bool ignore_case_; |
| 1569 HeapStringAllocator alloc_; | 1582 HeapStringAllocator alloc_; |
| 1570 StringStream stream_; | 1583 StringStream stream_; |
| 1571 std::set<RegExpNode*> seen_; | 1584 std::set<RegExpNode*> seen_; |
| 1572 }; | 1585 }; |
| 1573 | 1586 |
| 1574 | 1587 |
| 1575 void DotPrinter::PrintNode(const char* label, RegExpNode* node) { | 1588 void DotPrinter::PrintNode(const char* label, RegExpNode* node) { |
| 1576 stream()->Add("digraph G {\n graph [label=\""); | 1589 stream()->Add("digraph G {\n graph [label=\""); |
| 1577 for (int i = 0; label[i]; i++) { | 1590 for (int i = 0; label[i]; i++) { |
| 1578 switch (label[i]) { | 1591 switch (label[i]) { |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1655 } | 1668 } |
| 1656 stream()->Add("}}"); | 1669 stream()->Add("}}"); |
| 1657 } | 1670 } |
| 1658 private: | 1671 private: |
| 1659 bool first_; | 1672 bool first_; |
| 1660 StringStream* stream() { return stream_; } | 1673 StringStream* stream() { return stream_; } |
| 1661 StringStream* stream_; | 1674 StringStream* stream_; |
| 1662 }; | 1675 }; |
| 1663 | 1676 |
| 1664 | 1677 |
| 1678 class AttributePrinter { |
| 1679 public: |
| 1680 AttributePrinter(DotPrinter* out) : out_(out), first_(true) { } |
| 1681 void PrintSeparator() { |
| 1682 if (first_) first_ = false; |
| 1683 else out_->stream()->Add("|"); |
| 1684 } |
| 1685 void PrintBit(const char* name, bool value) { |
| 1686 if (!value) return; |
| 1687 PrintSeparator(); |
| 1688 out_->stream()->Add("{%s}", name); |
| 1689 } |
| 1690 void PrintPositive(const char* name, int value) { |
| 1691 if (value < 0) return; |
| 1692 PrintSeparator(); |
| 1693 out_->stream()->Add("{%s|%x}", name, value); |
| 1694 } |
| 1695 private: |
| 1696 DotPrinter* out_; |
| 1697 bool first_; |
| 1698 }; |
| 1699 |
| 1700 |
| 1665 void DotPrinter::PrintAttributes(RegExpNode* that) { | 1701 void DotPrinter::PrintAttributes(RegExpNode* that) { |
| 1666 stream()->Add(" a%p [shape=Mrecord, style=dashed, color=lightgrey, " | 1702 stream()->Add(" a%p [shape=Mrecord, color=grey, fontcolor=grey, " |
| 1667 "fontcolor=lightgrey, margin=0.1, fontsize=10, label=\"{", | 1703 "margin=0.1, fontsize=10, label=\"{", |
| 1668 that); | 1704 that); |
| 1705 AttributePrinter printer(this); |
| 1669 NodeInfo* info = that->info(); | 1706 NodeInfo* info = that->info(); |
| 1670 stream()->Add("{NI|%i}|{WI|%i}|{SI|%i}", | 1707 printer.PrintBit("NI", info->follows_newline_interest); |
| 1671 info->follows_newline_interest, | 1708 printer.PrintBit("WI", info->follows_word_interest); |
| 1672 info->follows_word_interest, | 1709 printer.PrintBit("SI", info->follows_start_interest); |
| 1673 info->follows_start_interest); | 1710 printer.PrintBit("DN", info->determine_newline); |
| 1674 stream()->Add("|{DN|%i}|{DW|%i}|{DS|%i}|{AE|%i}", | 1711 printer.PrintBit("DW", info->determine_word); |
| 1675 info->determine_newline, | 1712 printer.PrintBit("DS", info->determine_start); |
| 1676 info->determine_word, | 1713 printer.PrintBit("DDN", info->does_determine_newline); |
| 1677 info->determine_start, | 1714 printer.PrintBit("DDW", info->does_determine_word); |
| 1678 info->at_end); | 1715 printer.PrintBit("DDS", info->does_determine_start); |
| 1679 if (info->follows_newline != NodeInfo::UNKNOWN) | 1716 printer.PrintPositive("IW", info->is_word); |
| 1680 stream()->Add("|{FN|%i}", info->follows_newline); | 1717 printer.PrintPositive("IN", info->is_newline); |
| 1681 if (info->follows_word != NodeInfo::UNKNOWN) | 1718 printer.PrintPositive("FN", info->follows_newline); |
| 1682 stream()->Add("|{FW|%i}", info->follows_word); | 1719 printer.PrintPositive("FW", info->follows_word); |
| 1683 if (info->follows_start != NodeInfo::UNKNOWN) | 1720 printer.PrintPositive("FS", info->follows_start); |
| 1684 stream()->Add("|{FS|%i}", info->follows_start); | |
| 1685 Label* label = that->label(); | 1721 Label* label = that->label(); |
| 1686 if (label->is_bound()) | 1722 if (label->is_bound()) |
| 1687 stream()->Add("|{@|%x}", label->pos()); | 1723 printer.PrintPositive("@", label->pos()); |
| 1688 stream()->Add("}\"];\n"); | 1724 stream()->Add("}\"];\n"); |
| 1689 stream()->Add(" a%p -> n%p [style=dashed, color=lightgrey, " | 1725 stream()->Add(" a%p -> n%p [style=dashed, color=grey, " |
| 1690 "arrowhead=none];\n", that, that); | 1726 "arrowhead=none];\n", that, that); |
| 1691 } | 1727 } |
| 1692 | 1728 |
| 1693 | 1729 |
| 1730 static const bool kPrintDispatchTable = false; |
| 1694 void DotPrinter::VisitChoice(ChoiceNode* that) { | 1731 void DotPrinter::VisitChoice(ChoiceNode* that) { |
| 1695 stream()->Add(" n%p [shape=Mrecord, label=\"", that); | 1732 if (kPrintDispatchTable) { |
| 1696 TableEntryHeaderPrinter header_printer(stream()); | 1733 stream()->Add(" n%p [shape=Mrecord, label=\"", that); |
| 1697 that->table()->ForEach(&header_printer); | 1734 TableEntryHeaderPrinter header_printer(stream()); |
| 1698 stream()->Add("\"]\n", that); | 1735 that->GetTable(ignore_case_)->ForEach(&header_printer); |
| 1699 PrintAttributes(that); | 1736 stream()->Add("\"]\n", that); |
| 1700 TableEntryBodyPrinter body_printer(stream(), that); | 1737 PrintAttributes(that); |
| 1701 that->table()->ForEach(&body_printer); | 1738 TableEntryBodyPrinter body_printer(stream(), that); |
| 1702 PrintOnFailure(that, that->on_failure()); | 1739 that->GetTable(ignore_case_)->ForEach(&body_printer); |
| 1740 PrintOnFailure(that, that->on_failure()); |
| 1741 } else { |
| 1742 stream()->Add(" n%p [shape=Mrecord, label=\"?\"];\n", that); |
| 1743 for (int i = 0; i < that->alternatives()->length(); i++) { |
| 1744 GuardedAlternative alt = that->alternatives()->at(i); |
| 1745 stream()->Add(" n%p -> n%p;\n", that, alt.node()); |
| 1746 } |
| 1747 } |
| 1703 for (int i = 0; i < that->alternatives()->length(); i++) { | 1748 for (int i = 0; i < that->alternatives()->length(); i++) { |
| 1704 GuardedAlternative alt = that->alternatives()->at(i); | 1749 GuardedAlternative alt = that->alternatives()->at(i); |
| 1705 alt.node()->Accept(this); | 1750 alt.node()->Accept(this); |
| 1706 } | 1751 } |
| 1707 } | 1752 } |
| 1708 | 1753 |
| 1709 | 1754 |
| 1710 void DotPrinter::VisitText(TextNode* that) { | 1755 void DotPrinter::VisitText(TextNode* that) { |
| 1711 stream()->Add(" n%p [label=\"", that); | 1756 stream()->Add(" n%p [label=\"", that); |
| 1712 for (int i = 0; i < that->elements()->length(); i++) { | 1757 for (int i = 0; i < that->elements()->length(); i++) { |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1824 | 1869 |
| 1825 void DispatchTable::Dump() { | 1870 void DispatchTable::Dump() { |
| 1826 HeapStringAllocator alloc; | 1871 HeapStringAllocator alloc; |
| 1827 StringStream stream(&alloc); | 1872 StringStream stream(&alloc); |
| 1828 DispatchTableDumper dumper(&stream); | 1873 DispatchTableDumper dumper(&stream); |
| 1829 tree()->ForEach(&dumper); | 1874 tree()->ForEach(&dumper); |
| 1830 OS::PrintError("%s", *stream.ToCString()); | 1875 OS::PrintError("%s", *stream.ToCString()); |
| 1831 } | 1876 } |
| 1832 | 1877 |
| 1833 | 1878 |
| 1834 void RegExpEngine::DotPrint(const char* label, RegExpNode* node) { | 1879 void RegExpEngine::DotPrint(const char* label, |
| 1835 DotPrinter printer; | 1880 RegExpNode* node, |
| 1881 bool ignore_case) { |
| 1882 DotPrinter printer(ignore_case); |
| 1836 printer.PrintNode(label, node); | 1883 printer.PrintNode(label, node); |
| 1837 } | 1884 } |
| 1838 | 1885 |
| 1839 | 1886 |
| 1840 #endif // DEBUG | 1887 #endif // DEBUG |
| 1841 | 1888 |
| 1842 | 1889 |
| 1843 // ------------------------------------------------------------------- | 1890 // ------------------------------------------------------------------- |
| 1844 // Tree to graph conversion | 1891 // Tree to graph conversion |
| 1845 | 1892 |
| (...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2168 // character. | 2215 // character. |
| 2169 case '*': | 2216 case '*': |
| 2170 ranges->Add(CharacterRange::Everything()); | 2217 ranges->Add(CharacterRange::Everything()); |
| 2171 break; | 2218 break; |
| 2172 default: | 2219 default: |
| 2173 UNREACHABLE(); | 2220 UNREACHABLE(); |
| 2174 } | 2221 } |
| 2175 } | 2222 } |
| 2176 | 2223 |
| 2177 | 2224 |
| 2225 Vector<const uc16> CharacterRange::GetWordBounds() { |
| 2226 return Vector<const uc16>(kWordRanges, kWordRangeCount); |
| 2227 } |
| 2228 |
| 2229 |
| 2230 class CharacterRangeSplitter { |
| 2231 public: |
| 2232 CharacterRangeSplitter(ZoneList<CharacterRange>** included, |
| 2233 ZoneList<CharacterRange>** excluded) |
| 2234 : included_(included), |
| 2235 excluded_(excluded) { } |
| 2236 void Call(uc16 from, DispatchTable::Entry entry); |
| 2237 |
| 2238 static const int kInBase = 0; |
| 2239 static const int kInOverlay = 1; |
| 2240 |
| 2241 private: |
| 2242 ZoneList<CharacterRange>** included_; |
| 2243 ZoneList<CharacterRange>** excluded_; |
| 2244 }; |
| 2245 |
| 2246 |
| 2247 void CharacterRangeSplitter::Call(uc16 from, DispatchTable::Entry entry) { |
| 2248 if (!entry.out_set()->Get(kInBase)) return; |
| 2249 ZoneList<CharacterRange>** target = entry.out_set()->Get(kInOverlay) |
| 2250 ? included_ |
| 2251 : excluded_; |
| 2252 if (*target == NULL) *target = new ZoneList<CharacterRange>(2); |
| 2253 (*target)->Add(CharacterRange(entry.from(), entry.to())); |
| 2254 } |
| 2255 |
| 2256 |
| 2257 void CharacterRange::Split(ZoneList<CharacterRange>* base, |
| 2258 Vector<const uc16> overlay, |
| 2259 ZoneList<CharacterRange>** included, |
| 2260 ZoneList<CharacterRange>** excluded) { |
| 2261 ASSERT_EQ(NULL, *included); |
| 2262 ASSERT_EQ(NULL, *excluded); |
| 2263 DispatchTable table; |
| 2264 for (int i = 0; i < base->length(); i++) |
| 2265 table.AddRange(base->at(i), CharacterRangeSplitter::kInBase); |
| 2266 for (int i = 0; i < overlay.length(); i += 2) { |
| 2267 table.AddRange(CharacterRange(overlay[i], overlay[i+1]), |
| 2268 CharacterRangeSplitter::kInOverlay); |
| 2269 } |
| 2270 CharacterRangeSplitter callback(included, excluded); |
| 2271 table.ForEach(&callback); |
| 2272 } |
| 2273 |
| 2274 |
| 2178 void CharacterRange::AddCaseEquivalents(ZoneList<CharacterRange>* ranges) { | 2275 void CharacterRange::AddCaseEquivalents(ZoneList<CharacterRange>* ranges) { |
| 2179 unibrow::uchar chars[unibrow::Ecma262UnCanonicalize::kMaxWidth]; | 2276 unibrow::uchar chars[unibrow::Ecma262UnCanonicalize::kMaxWidth]; |
| 2180 if (IsSingleton()) { | 2277 if (IsSingleton()) { |
| 2181 // If this is a singleton we just expand the one character. | 2278 // If this is a singleton we just expand the one character. |
| 2182 int length = uncanonicalize.get(from(), '\0', chars); | 2279 int length = uncanonicalize.get(from(), '\0', chars); |
| 2183 for (int i = 0; i < length; i++) { | 2280 for (int i = 0; i < length; i++) { |
| 2184 uc32 chr = chars[i]; | 2281 uc32 chr = chars[i]; |
| 2185 if (chr != from()) { | 2282 if (chr != from()) { |
| 2186 ranges->Add(CharacterRange::Singleton(chars[i])); | 2283 ranges->Add(CharacterRange::Singleton(chars[i])); |
| 2187 } | 2284 } |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2253 } else { | 2350 } else { |
| 2254 // TODO(plesner) when we've fixed the 2^11 bug in unibrow. | 2351 // TODO(plesner) when we've fixed the 2^11 bug in unibrow. |
| 2255 } | 2352 } |
| 2256 } | 2353 } |
| 2257 | 2354 |
| 2258 | 2355 |
| 2259 // ------------------------------------------------------------------- | 2356 // ------------------------------------------------------------------- |
| 2260 // Interest propagation | 2357 // Interest propagation |
| 2261 | 2358 |
| 2262 | 2359 |
| 2263 RegExpNode* RegExpNode::GetSibling(NodeInfo* info) { | 2360 RegExpNode* RegExpNode::TryGetSibling(NodeInfo* info) { |
| 2264 for (int i = 0; i < siblings_.length(); i++) { | 2361 for (int i = 0; i < siblings_.length(); i++) { |
| 2265 RegExpNode* sibling = siblings_.Get(i); | 2362 RegExpNode* sibling = siblings_.Get(i); |
| 2266 if (sibling->info()->HasSameForwardInterests(info)) | 2363 if (sibling->info()->Matches(info)) |
| 2267 return sibling; | 2364 return sibling; |
| 2268 } | 2365 } |
| 2269 return NULL; | 2366 return NULL; |
| 2270 } | 2367 } |
| 2271 | 2368 |
| 2272 | 2369 |
| 2370 RegExpNode* RegExpNode::EnsureSibling(NodeInfo* info, bool* cloned) { |
| 2371 ASSERT_EQ(false, *cloned); |
| 2372 ASSERT(!info->HasAssertions()); |
| 2373 siblings_.Ensure(this); |
| 2374 RegExpNode* result = TryGetSibling(info); |
| 2375 if (result != NULL) return result; |
| 2376 result = this->Clone(); |
| 2377 NodeInfo* new_info = result->info(); |
| 2378 new_info->ResetCompilationState(); |
| 2379 new_info->AddFromPreceding(info); |
| 2380 AddSibling(result); |
| 2381 *cloned = true; |
| 2382 return result; |
| 2383 } |
| 2384 |
| 2385 |
| 2273 template <class C> | 2386 template <class C> |
| 2274 static RegExpNode* PropagateToEndpoint(C* node, NodeInfo* info) { | 2387 static RegExpNode* PropagateToEndpoint(C* node, NodeInfo* info) { |
| 2275 NodeInfo full_info(*node->info()); | 2388 NodeInfo full_info(*node->info()); |
| 2276 full_info.AddFromPreceding(info); | 2389 full_info.AddFromPreceding(info); |
| 2277 RegExpNode* sibling = node->GetSibling(&full_info); | 2390 bool cloned = false; |
| 2278 if (sibling != NULL) return sibling; | 2391 return RegExpNode::EnsureSibling(node, &full_info, &cloned); |
| 2279 node->EnsureSiblings(); | |
| 2280 sibling = new C(*node); | |
| 2281 sibling->info()->AddFromPreceding(&full_info); | |
| 2282 node->AddSibling(sibling); | |
| 2283 return sibling; | |
| 2284 } | 2392 } |
| 2285 | 2393 |
| 2286 | 2394 |
| 2287 RegExpNode* ActionNode::PropagateForward(NodeInfo* info) { | 2395 RegExpNode* ActionNode::PropagateForward(NodeInfo* info) { |
| 2288 NodeInfo full_info(*this->info()); | 2396 NodeInfo full_info(*this->info()); |
| 2289 full_info.AddFromPreceding(info); | 2397 full_info.AddFromPreceding(info); |
| 2290 RegExpNode* sibling = GetSibling(&full_info); | 2398 bool cloned = false; |
| 2291 if (sibling != NULL) return sibling; | 2399 ActionNode* action = EnsureSibling(this, &full_info, &cloned); |
| 2292 EnsureSiblings(); | 2400 if (cloned && type_ != ESCAPE_SUBMATCH) { |
| 2293 ActionNode* action = new ActionNode(*this); | |
| 2294 action->info()->AddFromPreceding(&full_info); | |
| 2295 AddSibling(action); | |
| 2296 if (type_ != ESCAPE_SUBMATCH) { | |
| 2297 action->set_on_success(action->on_success()->PropagateForward(info)); | 2401 action->set_on_success(action->on_success()->PropagateForward(info)); |
| 2298 } | 2402 } |
| 2299 return action; | 2403 return action; |
| 2300 } | 2404 } |
| 2301 | 2405 |
| 2302 | 2406 |
| 2303 RegExpNode* ChoiceNode::PropagateForward(NodeInfo* info) { | 2407 RegExpNode* ChoiceNode::PropagateForward(NodeInfo* info) { |
| 2304 NodeInfo full_info(*this->info()); | 2408 NodeInfo full_info(*this->info()); |
| 2305 full_info.AddFromPreceding(info); | 2409 full_info.AddFromPreceding(info); |
| 2306 RegExpNode* sibling = GetSibling(&full_info); | 2410 bool cloned = false; |
| 2307 if (sibling != NULL) return sibling; | 2411 ChoiceNode* choice = EnsureSibling(this, &full_info, &cloned); |
| 2308 EnsureSiblings(); | 2412 if (cloned) { |
| 2309 ChoiceNode* choice = new ChoiceNode(*this); | 2413 ZoneList<GuardedAlternative>* old_alternatives = alternatives(); |
| 2310 choice->info()->AddFromPreceding(&full_info); | 2414 int count = old_alternatives->length(); |
| 2311 AddSibling(choice); | 2415 choice->alternatives_ = new ZoneList<GuardedAlternative>(count); |
| 2312 ZoneList<GuardedAlternative>* old_alternatives = alternatives(); | 2416 for (int i = 0; i < count; i++) { |
| 2313 int count = old_alternatives->length(); | 2417 GuardedAlternative alternative = old_alternatives->at(i); |
| 2314 choice->alternatives_ = new ZoneList<GuardedAlternative>(count); | 2418 alternative.set_node(alternative.node()->PropagateForward(info)); |
| 2315 for (int i = 0; i < count; i++) { | 2419 choice->alternatives()->Add(alternative); |
| 2316 GuardedAlternative alternative = old_alternatives->at(i); | 2420 } |
| 2317 alternative.set_node(alternative.node()->PropagateForward(info)); | 2421 if (!choice->on_failure_->IsBacktrack()) { |
| 2318 choice->alternatives()->Add(alternative); | 2422 choice->on_failure_ = choice->on_failure_->PropagateForward(info); |
| 2319 } | 2423 } |
| 2320 if (!choice->on_failure_->IsBacktrack()) { | |
| 2321 choice->on_failure_ = choice->on_failure_->PropagateForward(info); | |
| 2322 } | 2424 } |
| 2323 return choice; | 2425 return choice; |
| 2324 } | 2426 } |
| 2325 | 2427 |
| 2326 | 2428 |
| 2327 RegExpNode* EndNode::PropagateForward(NodeInfo* info) { | 2429 RegExpNode* EndNode::PropagateForward(NodeInfo* info) { |
| 2328 return PropagateToEndpoint(this, info); | 2430 return PropagateToEndpoint(this, info); |
| 2329 } | 2431 } |
| 2330 | 2432 |
| 2331 | 2433 |
| 2332 RegExpNode* BackReferenceNode::PropagateForward(NodeInfo* info) { | 2434 RegExpNode* BackReferenceNode::PropagateForward(NodeInfo* info) { |
| 2333 NodeInfo full_info(*this->info()); | 2435 NodeInfo full_info(*this->info()); |
| 2334 full_info.AddFromPreceding(info); | 2436 full_info.AddFromPreceding(info); |
| 2335 RegExpNode* sibling = GetSibling(&full_info); | 2437 bool cloned = false; |
| 2336 if (sibling != NULL) return sibling; | 2438 BackReferenceNode* back_ref = EnsureSibling(this, &full_info, &cloned); |
| 2337 EnsureSiblings(); | 2439 if (cloned) { |
| 2338 BackReferenceNode* back_ref = new BackReferenceNode(*this); | 2440 // TODO(erikcorry): A back reference has to have two successors (by default |
| 2339 back_ref->info()->AddFromPreceding(&full_info); | 2441 // the same node). The first is used if the back reference matches a non- |
| 2340 AddSibling(back_ref); | 2442 // empty back reference, the second if it matches an empty one. This |
| 2341 // TODO(erikcorry): A back reference has to have two successors (by default | 2443 // doesn't matter for at_end, which is the only one implemented right now, |
| 2342 // the same node). The first is used if the back reference matches a non- | 2444 // but it will matter for other pieces of info. |
| 2343 // empty back reference, the second if it matches an empty one. This doesn't | 2445 back_ref->set_on_success(back_ref->on_success()->PropagateForward(info)); |
| 2344 // matter for at_end, which is the only one implemented right now, but it will | 2446 } |
| 2345 // matter for other pieces of info. | |
| 2346 back_ref->set_on_success(back_ref->on_success()->PropagateForward(info)); | |
| 2347 return back_ref; | 2447 return back_ref; |
| 2348 } | 2448 } |
| 2349 | 2449 |
| 2350 | 2450 |
| 2351 RegExpNode* TextNode::PropagateForward(NodeInfo* info) { | 2451 RegExpNode* TextNode::PropagateForward(NodeInfo* info) { |
| 2352 return PropagateToEndpoint(this, info); | 2452 return PropagateToEndpoint(this, info); |
| 2353 } | 2453 } |
| 2354 | 2454 |
| 2355 | 2455 |
| 2356 // ------------------------------------------------------------------- | 2456 // ------------------------------------------------------------------- |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2547 | 2647 |
| 2548 void Analysis::VisitChoice(ChoiceNode* that) { | 2648 void Analysis::VisitChoice(ChoiceNode* that) { |
| 2549 NodeInfo* info = that->info(); | 2649 NodeInfo* info = that->info(); |
| 2550 for (int i = 0; i < that->alternatives()->length(); i++) { | 2650 for (int i = 0; i < that->alternatives()->length(); i++) { |
| 2551 RegExpNode* node = that->alternatives()->at(i).node(); | 2651 RegExpNode* node = that->alternatives()->at(i).node(); |
| 2552 EnsureAnalyzed(node); | 2652 EnsureAnalyzed(node); |
| 2553 // Anything the following nodes need to know has to be known by | 2653 // Anything the following nodes need to know has to be known by |
| 2554 // this node also, so it can pass it on. | 2654 // this node also, so it can pass it on. |
| 2555 info->AddFromFollowing(node->info()); | 2655 info->AddFromFollowing(node->info()); |
| 2556 } | 2656 } |
| 2557 if (!that->table_calculated()) { | |
| 2558 DispatchTableConstructor cons(that->table()); | |
| 2559 cons.BuildTable(that); | |
| 2560 } | |
| 2561 EnsureAnalyzed(that->on_failure()); | 2657 EnsureAnalyzed(that->on_failure()); |
| 2562 } | 2658 } |
| 2563 | 2659 |
| 2564 | 2660 |
| 2565 void Analysis::VisitBackReference(BackReferenceNode* that) { | 2661 void Analysis::VisitBackReference(BackReferenceNode* that) { |
| 2566 EnsureAnalyzed(that->on_success()); | 2662 EnsureAnalyzed(that->on_success()); |
| 2567 EnsureAnalyzed(that->on_failure()); | 2663 EnsureAnalyzed(that->on_failure()); |
| 2568 } | 2664 } |
| 2569 | 2665 |
| 2570 | 2666 |
| 2571 // ------------------------------------------------------------------- | 2667 // ------------------------------------------------------------------- |
| 2668 // Assumption expansion |
| 2669 |
| 2670 |
| 2671 RegExpNode* RegExpNode::EnsureExpanded(NodeInfo* info) { |
| 2672 siblings_.Ensure(this); |
| 2673 NodeInfo new_info = *this->info(); |
| 2674 if (new_info.follows_word_interest) |
| 2675 new_info.follows_word = info->follows_word; |
| 2676 if (new_info.follows_newline_interest) |
| 2677 new_info.follows_newline = info->follows_newline; |
| 2678 // If the following node should determine something we need to get |
| 2679 // a sibling that determines it. |
| 2680 new_info.does_determine_newline = new_info.determine_newline; |
| 2681 new_info.does_determine_word = new_info.determine_word; |
| 2682 new_info.does_determine_start = new_info.determine_start; |
| 2683 RegExpNode* sibling = TryGetSibling(&new_info); |
| 2684 if (sibling == NULL) { |
| 2685 sibling = ExpandLocal(&new_info); |
| 2686 siblings_.Add(sibling); |
| 2687 sibling->info()->being_expanded = true; |
| 2688 sibling->ExpandChildren(); |
| 2689 sibling->info()->being_expanded = false; |
| 2690 sibling->info()->been_expanded = true; |
| 2691 } else { |
| 2692 NodeInfo* sib_info = sibling->info(); |
| 2693 if (!sib_info->been_expanded && !sib_info->being_expanded) { |
| 2694 sibling->info()->being_expanded = true; |
| 2695 sibling->ExpandChildren(); |
| 2696 sibling->info()->being_expanded = false; |
| 2697 sibling->info()->been_expanded = true; |
| 2698 } |
| 2699 } |
| 2700 return sibling; |
| 2701 } |
| 2702 |
| 2703 |
| 2704 RegExpNode* ChoiceNode::ExpandLocal(NodeInfo* info) { |
| 2705 ChoiceNode* clone = this->Clone(); |
| 2706 clone->info()->ResetCompilationState(); |
| 2707 clone->info()->AddAssumptions(info); |
| 2708 return clone; |
| 2709 } |
| 2710 |
| 2711 |
| 2712 void ChoiceNode::ExpandChildren() { |
| 2713 ZoneList<GuardedAlternative>* alts = alternatives(); |
| 2714 ZoneList<GuardedAlternative>* new_alts |
| 2715 = new ZoneList<GuardedAlternative>(alts->length()); |
| 2716 for (int i = 0; i < alts->length(); i++) { |
| 2717 GuardedAlternative next = alts->at(i); |
| 2718 next.set_node(next.node()->EnsureExpanded(info())); |
| 2719 new_alts->Add(next); |
| 2720 } |
| 2721 alternatives_ = new_alts; |
| 2722 } |
| 2723 |
| 2724 |
| 2725 RegExpNode* TextNode::ExpandLocal(NodeInfo* info) { |
| 2726 TextElement last = elements()->last(); |
| 2727 if (last.type == TextElement::CHAR_CLASS) { |
| 2728 RegExpCharacterClass* char_class = last.data.u_char_class; |
| 2729 if (info->does_determine_word) { |
| 2730 ZoneList<CharacterRange>* word = NULL; |
| 2731 ZoneList<CharacterRange>* non_word = NULL; |
| 2732 CharacterRange::Split(char_class->ranges(), |
| 2733 CharacterRange::GetWordBounds(), |
| 2734 &word, |
| 2735 &non_word); |
| 2736 if (non_word == NULL) { |
| 2737 // This node contains no non-word characters so it must be |
| 2738 // all word. |
| 2739 this->info()->is_word = NodeInfo::TRUE; |
| 2740 } else if (word == NULL) { |
| 2741 // Vice versa. |
| 2742 this->info()->is_word = NodeInfo::FALSE; |
| 2743 } else { |
| 2744 // If this character class contains both word and non-word |
| 2745 // characters we need to split it into two. |
| 2746 ChoiceNode* result = new ChoiceNode(2, on_failure()); |
| 2747 // Welcome to the family, son! |
| 2748 result->set_siblings(this->siblings()); |
| 2749 *result->info() = *this->info(); |
| 2750 result->info()->ResetCompilationState(); |
| 2751 result->info()->AddAssumptions(info); |
| 2752 RegExpNode* word_node |
| 2753 = new TextNode(new RegExpCharacterClass(word, false), |
| 2754 on_success(), |
| 2755 on_failure()); |
| 2756 word_node->info()->determine_word = true; |
| 2757 word_node->info()->does_determine_word = true; |
| 2758 word_node->info()->is_word = NodeInfo::TRUE; |
| 2759 result->alternatives()->Add(GuardedAlternative(word_node)); |
| 2760 RegExpNode* non_word_node |
| 2761 = new TextNode(new RegExpCharacterClass(non_word, false), |
| 2762 on_success(), |
| 2763 on_failure()); |
| 2764 non_word_node->info()->determine_word = true; |
| 2765 non_word_node->info()->does_determine_word = true; |
| 2766 non_word_node->info()->is_word = NodeInfo::FALSE; |
| 2767 result->alternatives()->Add(GuardedAlternative(non_word_node)); |
| 2768 return result; |
| 2769 } |
| 2770 } |
| 2771 } |
| 2772 TextNode* clone = this->Clone(); |
| 2773 clone->info()->ResetCompilationState(); |
| 2774 clone->info()->AddAssumptions(info); |
| 2775 return clone; |
| 2776 } |
| 2777 |
| 2778 |
| 2779 void TextNode::ExpandAtomChildren(RegExpAtom* that) { |
| 2780 NodeInfo new_info = *info(); |
| 2781 uc16 last = that->data()[that->data().length() - 1]; |
| 2782 if (info()->determine_word) { |
| 2783 new_info.follows_word = IsRegExpWord(last) |
| 2784 ? NodeInfo::TRUE : NodeInfo::FALSE; |
| 2785 } else { |
| 2786 new_info.follows_word = NodeInfo::UNKNOWN; |
| 2787 } |
| 2788 if (info()->determine_newline) { |
| 2789 new_info.follows_newline = IsRegExpNewline(last) |
| 2790 ? NodeInfo::TRUE : NodeInfo::FALSE; |
| 2791 } else { |
| 2792 new_info.follows_newline = NodeInfo::UNKNOWN; |
| 2793 } |
| 2794 if (info()->determine_start) { |
| 2795 new_info.follows_start = NodeInfo::FALSE; |
| 2796 } else { |
| 2797 new_info.follows_start = NodeInfo::UNKNOWN; |
| 2798 } |
| 2799 set_on_success(on_success()->EnsureExpanded(&new_info)); |
| 2800 } |
| 2801 |
| 2802 |
| 2803 void TextNode::ExpandCharClassChildren(RegExpCharacterClass* that) { |
| 2804 if (info()->does_determine_word) { |
| 2805 // ASSERT(info()->is_word != NodeInfo::UNKNOWN); |
| 2806 NodeInfo next_info = *on_success()->info(); |
| 2807 next_info.follows_word = info()->is_word; |
| 2808 set_on_success(on_success()->EnsureExpanded(&next_info)); |
| 2809 } else { |
| 2810 set_on_success(on_success()->EnsureExpanded(info())); |
| 2811 } |
| 2812 } |
| 2813 |
| 2814 |
| 2815 void TextNode::ExpandChildren() { |
| 2816 TextElement last = elements()->last(); |
| 2817 switch (last.type) { |
| 2818 case TextElement::ATOM: |
| 2819 ExpandAtomChildren(last.data.u_atom); |
| 2820 break; |
| 2821 case TextElement::CHAR_CLASS: |
| 2822 ExpandCharClassChildren(last.data.u_char_class); |
| 2823 break; |
| 2824 default: |
| 2825 UNREACHABLE(); |
| 2826 } |
| 2827 } |
| 2828 |
| 2829 |
| 2830 RegExpNode* ActionNode::ExpandLocal(NodeInfo* info) { |
| 2831 ActionNode* clone = this->Clone(); |
| 2832 clone->info()->ResetCompilationState(); |
| 2833 clone->info()->AddAssumptions(info); |
| 2834 return clone; |
| 2835 } |
| 2836 |
| 2837 |
| 2838 void ActionNode::ExpandChildren() { |
| 2839 set_on_success(on_success()->EnsureExpanded(info())); |
| 2840 } |
| 2841 |
| 2842 |
| 2843 RegExpNode* BackReferenceNode::ExpandLocal(NodeInfo* info) { |
| 2844 BackReferenceNode* clone = this->Clone(); |
| 2845 clone->info()->ResetCompilationState(); |
| 2846 clone->info()->AddAssumptions(info); |
| 2847 return clone; |
| 2848 } |
| 2849 |
| 2850 |
| 2851 void BackReferenceNode::ExpandChildren() { |
| 2852 set_on_success(on_success()->EnsureExpanded(info())); |
| 2853 } |
| 2854 |
| 2855 |
| 2856 RegExpNode* EndNode::ExpandLocal(NodeInfo* info) { |
| 2857 EndNode* clone = this->Clone(); |
| 2858 clone->info()->ResetCompilationState(); |
| 2859 clone->info()->AddAssumptions(info); |
| 2860 return clone; |
| 2861 } |
| 2862 |
| 2863 |
| 2864 void EndNode::ExpandChildren() { |
| 2865 // nothing to do |
| 2866 } |
| 2867 |
| 2868 |
| 2869 // ------------------------------------------------------------------- |
| 2572 // Dispatch table construction | 2870 // Dispatch table construction |
| 2573 | 2871 |
| 2574 | 2872 |
| 2575 void DispatchTableConstructor::VisitEnd(EndNode* that) { | 2873 void DispatchTableConstructor::VisitEnd(EndNode* that) { |
| 2576 AddRange(CharacterRange::Everything()); | 2874 AddRange(CharacterRange::Everything()); |
| 2577 } | 2875 } |
| 2578 | 2876 |
| 2579 | 2877 |
| 2580 void DispatchTableConstructor::BuildTable(ChoiceNode* node) { | 2878 void DispatchTableConstructor::BuildTable(ChoiceNode* node) { |
| 2581 ASSERT(!node->table_calculated()); | |
| 2582 node->set_being_calculated(true); | 2879 node->set_being_calculated(true); |
| 2583 ZoneList<GuardedAlternative>* alternatives = node->alternatives(); | 2880 ZoneList<GuardedAlternative>* alternatives = node->alternatives(); |
| 2584 for (int i = 0; i < alternatives->length(); i++) { | 2881 for (int i = 0; i < alternatives->length(); i++) { |
| 2585 set_choice_index(i); | 2882 set_choice_index(i); |
| 2586 alternatives->at(i).node()->Accept(this); | 2883 alternatives->at(i).node()->Accept(this); |
| 2587 } | 2884 } |
| 2588 node->set_being_calculated(false); | 2885 node->set_being_calculated(false); |
| 2589 node->set_table_calculated(true); | |
| 2590 } | 2886 } |
| 2591 | 2887 |
| 2592 | 2888 |
| 2593 class AddDispatchRange { | 2889 class AddDispatchRange { |
| 2594 public: | 2890 public: |
| 2595 explicit AddDispatchRange(DispatchTableConstructor* constructor) | 2891 explicit AddDispatchRange(DispatchTableConstructor* constructor) |
| 2596 : constructor_(constructor) { } | 2892 : constructor_(constructor) { } |
| 2597 void Call(uc32 from, DispatchTable::Entry entry); | 2893 void Call(uc32 from, DispatchTable::Entry entry); |
| 2598 private: | 2894 private: |
| 2599 DispatchTableConstructor* constructor_; | 2895 DispatchTableConstructor* constructor_; |
| 2600 }; | 2896 }; |
| 2601 | 2897 |
| 2602 | 2898 |
| 2603 void AddDispatchRange::Call(uc32 from, DispatchTable::Entry entry) { | 2899 void AddDispatchRange::Call(uc32 from, DispatchTable::Entry entry) { |
| 2604 CharacterRange range(from, entry.to()); | 2900 CharacterRange range(from, entry.to()); |
| 2605 constructor_->AddRange(range); | 2901 constructor_->AddRange(range); |
| 2606 } | 2902 } |
| 2607 | 2903 |
| 2608 | 2904 |
| 2609 void DispatchTableConstructor::VisitChoice(ChoiceNode* node) { | 2905 void DispatchTableConstructor::VisitChoice(ChoiceNode* node) { |
| 2610 if (node->being_calculated()) | 2906 if (node->being_calculated()) |
| 2611 return; | 2907 return; |
| 2612 if (!node->table_calculated()) { | 2908 DispatchTable* table = node->GetTable(ignore_case_); |
| 2613 DispatchTableConstructor constructor(node->table()); | |
| 2614 constructor.BuildTable(node); | |
| 2615 } | |
| 2616 ASSERT(node->table_calculated()); | |
| 2617 AddDispatchRange adder(this); | 2909 AddDispatchRange adder(this); |
| 2618 node->table()->ForEach(&adder); | 2910 table->ForEach(&adder); |
| 2619 } | 2911 } |
| 2620 | 2912 |
| 2621 | 2913 |
| 2622 void DispatchTableConstructor::VisitBackReference(BackReferenceNode* that) { | 2914 void DispatchTableConstructor::VisitBackReference(BackReferenceNode* that) { |
| 2623 // TODO(160): Find the node that we refer back to and propagate its start | 2915 // TODO(160): Find the node that we refer back to and propagate its start |
| 2624 // set back to here. For now we just accept anything. | 2916 // set back to here. For now we just accept anything. |
| 2625 AddRange(CharacterRange::Everything()); | 2917 AddRange(CharacterRange::Everything()); |
| 2626 } | 2918 } |
| 2627 | 2919 |
| 2628 | 2920 |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2703 RegExpQuantifier::kInfinity, | 2995 RegExpQuantifier::kInfinity, |
| 2704 false, | 2996 false, |
| 2705 new RegExpCharacterClass('*'), | 2997 new RegExpCharacterClass('*'), |
| 2706 &compiler, | 2998 &compiler, |
| 2707 captured_body, | 2999 captured_body, |
| 2708 compiler.backtrack()); | 3000 compiler.backtrack()); |
| 2709 if (node_return != NULL) *node_return = node; | 3001 if (node_return != NULL) *node_return = node; |
| 2710 Analysis analysis(ignore_case); | 3002 Analysis analysis(ignore_case); |
| 2711 analysis.EnsureAnalyzed(node); | 3003 analysis.EnsureAnalyzed(node); |
| 2712 | 3004 |
| 3005 NodeInfo info = *node->info(); |
| 3006 node = node->EnsureExpanded(&info); |
| 3007 |
| 2713 if (!FLAG_irregexp) { | 3008 if (!FLAG_irregexp) { |
| 2714 return Handle<FixedArray>::null(); | 3009 return Handle<FixedArray>::null(); |
| 2715 } | 3010 } |
| 2716 | 3011 |
| 2717 if (is_multiline && !FLAG_attempt_multiline_irregexp) { | 3012 if (is_multiline && !FLAG_attempt_multiline_irregexp) { |
| 2718 return Handle<FixedArray>::null(); | 3013 return Handle<FixedArray>::null(); |
| 2719 } | 3014 } |
| 2720 | 3015 |
| 2721 if (FLAG_irregexp_native) { | 3016 if (FLAG_irregexp_native) { |
| 2722 #ifdef ARM | 3017 #ifdef ARM |
| 2723 UNIMPLEMENTED(); | 3018 UNIMPLEMENTED(); |
| 2724 #else // IA32 | 3019 #else // IA32 |
| 2725 RegExpMacroAssemblerIA32 macro_assembler(RegExpMacroAssemblerIA32::UC16, | 3020 RegExpMacroAssemblerIA32 macro_assembler(RegExpMacroAssemblerIA32::UC16, |
| 2726 (input->capture_count + 1) * 2); | 3021 (input->capture_count + 1) * 2); |
| 2727 return compiler.Assemble(¯o_assembler, | 3022 return compiler.Assemble(¯o_assembler, |
| 2728 node, | 3023 node, |
| 2729 input->capture_count); | 3024 input->capture_count); |
| 2730 #endif | 3025 #endif |
| 2731 } | 3026 } |
| 2732 EmbeddedVector<byte, 1024> codes; | 3027 EmbeddedVector<byte, 1024> codes; |
| 2733 RegExpMacroAssemblerIrregexp macro_assembler(codes); | 3028 RegExpMacroAssemblerIrregexp macro_assembler(codes); |
| 2734 return compiler.Assemble(¯o_assembler, | 3029 return compiler.Assemble(¯o_assembler, |
| 2735 node, | 3030 node, |
| 2736 input->capture_count); | 3031 input->capture_count); |
| 2737 } | 3032 } |
| 2738 | 3033 |
| 2739 | 3034 |
| 2740 }} // namespace v8::internal | 3035 }} // namespace v8::internal |
| OLD | NEW |