Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(148)

Side by Side Diff: src/jsregexp.cc

Issue 13014: Rudimentary assertion expansion (Closed)
Patch Set: Created 12 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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
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(&macro_assembler, 3022 return compiler.Assemble(&macro_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(&macro_assembler, 3029 return compiler.Assemble(&macro_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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698