| 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 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 280 } | 280 } |
| 281 bool Contains(uc16 i) { return from_ <= i && i <= to_; } | 281 bool Contains(uc16 i) { return from_ <= i && i <= to_; } |
| 282 uc16 from() const { return from_; } | 282 uc16 from() const { return from_; } |
| 283 void set_from(uc16 value) { from_ = value; } | 283 void set_from(uc16 value) { from_ = value; } |
| 284 uc16 to() const { return to_; } | 284 uc16 to() const { return to_; } |
| 285 void set_to(uc16 value) { to_ = value; } | 285 void set_to(uc16 value) { to_ = value; } |
| 286 bool is_valid() { return from_ <= to_; } | 286 bool is_valid() { return from_ <= to_; } |
| 287 bool IsEverything(uc16 max) { return from_ == 0 && to_ >= max; } | 287 bool IsEverything(uc16 max) { return from_ == 0 && to_ >= max; } |
| 288 bool IsSingleton() { return (from_ == to_); } | 288 bool IsSingleton() { return (from_ == to_); } |
| 289 void AddCaseEquivalents(ZoneList<CharacterRange>* ranges, bool is_ascii); | 289 void AddCaseEquivalents(ZoneList<CharacterRange>* ranges, bool is_ascii); |
| 290 static void Split(ZoneList<CharacterRange>* base, | 290 static void Split(Zone* zone, |
| 291 ZoneList<CharacterRange>* base, |
| 291 Vector<const uc16> overlay, | 292 Vector<const uc16> overlay, |
| 292 ZoneList<CharacterRange>** included, | 293 ZoneList<CharacterRange>** included, |
| 293 ZoneList<CharacterRange>** excluded); | 294 ZoneList<CharacterRange>** excluded); |
| 294 // Whether a range list is in canonical form: Ranges ordered by from value, | 295 // Whether a range list is in canonical form: Ranges ordered by from value, |
| 295 // and ranges non-overlapping and non-adjacent. | 296 // and ranges non-overlapping and non-adjacent. |
| 296 static bool IsCanonical(ZoneList<CharacterRange>* ranges); | 297 static bool IsCanonical(ZoneList<CharacterRange>* ranges); |
| 297 // Convert range list to canonical form. The characters covered by the ranges | 298 // Convert range list to canonical form. The characters covered by the ranges |
| 298 // will still be the same, but no character is in more than one range, and | 299 // will still be the same, but no character is in more than one range, and |
| 299 // adjacent ranges are merged. The resulting list may be shorter than the | 300 // adjacent ranges are merged. The resulting list may be shorter than the |
| 300 // original, but cannot be longer. | 301 // original, but cannot be longer. |
| (...skipping 30 matching lines...) Expand all Loading... |
| 331 uc16 from_; | 332 uc16 from_; |
| 332 uc16 to_; | 333 uc16 to_; |
| 333 }; | 334 }; |
| 334 | 335 |
| 335 | 336 |
| 336 // A set of unsigned integers that behaves especially well on small | 337 // A set of unsigned integers that behaves especially well on small |
| 337 // integers (< 32). May do zone-allocation. | 338 // integers (< 32). May do zone-allocation. |
| 338 class OutSet: public ZoneObject { | 339 class OutSet: public ZoneObject { |
| 339 public: | 340 public: |
| 340 OutSet() : first_(0), remaining_(NULL), successors_(NULL) { } | 341 OutSet() : first_(0), remaining_(NULL), successors_(NULL) { } |
| 341 OutSet* Extend(unsigned value); | 342 OutSet* Extend(Zone* zone, unsigned value); |
| 342 bool Get(unsigned value); | 343 bool Get(unsigned value); |
| 343 static const unsigned kFirstLimit = 32; | 344 static const unsigned kFirstLimit = 32; |
| 344 | 345 |
| 345 private: | 346 private: |
| 346 // Destructively set a value in this set. In most cases you want | 347 // Destructively set a value in this set. In most cases you want |
| 347 // to use Extend instead to ensure that only one instance exists | 348 // to use Extend instead to ensure that only one instance exists |
| 348 // that contains the same values. | 349 // that contains the same values. |
| 349 void Set(unsigned value); | 350 void Set(Zone* zone, unsigned value); |
| 350 | 351 |
| 351 // The successors are a list of sets that contain the same values | 352 // The successors are a list of sets that contain the same values |
| 352 // as this set and the one more value that is not present in this | 353 // as this set and the one more value that is not present in this |
| 353 // set. | 354 // set. |
| 354 ZoneList<OutSet*>* successors() { return successors_; } | 355 ZoneList<OutSet*>* successors() { return successors_; } |
| 355 | 356 |
| 356 OutSet(uint32_t first, ZoneList<unsigned>* remaining) | 357 OutSet(uint32_t first, ZoneList<unsigned>* remaining) |
| 357 : first_(first), remaining_(remaining), successors_(NULL) { } | 358 : first_(first), remaining_(remaining), successors_(NULL) { } |
| 358 uint32_t first_; | 359 uint32_t first_; |
| 359 ZoneList<unsigned>* remaining_; | 360 ZoneList<unsigned>* remaining_; |
| 360 ZoneList<OutSet*>* successors_; | 361 ZoneList<OutSet*>* successors_; |
| 361 friend class Trace; | 362 friend class Trace; |
| 362 }; | 363 }; |
| 363 | 364 |
| 364 | 365 |
| 365 // A mapping from integers, specified as ranges, to a set of integers. | 366 // A mapping from integers, specified as ranges, to a set of integers. |
| 366 // Used for mapping character ranges to choices. | 367 // Used for mapping character ranges to choices. |
| 367 class DispatchTable : public ZoneObject { | 368 class DispatchTable : public ZoneObject { |
| 368 public: | 369 public: |
| 369 class Entry { | 370 class Entry { |
| 370 public: | 371 public: |
| 371 Entry() : from_(0), to_(0), out_set_(NULL) { } | 372 Entry() : from_(0), to_(0), out_set_(NULL) { } |
| 372 Entry(uc16 from, uc16 to, OutSet* out_set) | 373 Entry(uc16 from, uc16 to, OutSet* out_set) |
| 373 : from_(from), to_(to), out_set_(out_set) { } | 374 : from_(from), to_(to), out_set_(out_set) { } |
| 374 uc16 from() { return from_; } | 375 uc16 from() { return from_; } |
| 375 uc16 to() { return to_; } | 376 uc16 to() { return to_; } |
| 376 void set_to(uc16 value) { to_ = value; } | 377 void set_to(uc16 value) { to_ = value; } |
| 377 void AddValue(int value) { out_set_ = out_set_->Extend(value); } | 378 void AddValue(Zone* zone, int value) { |
| 379 out_set_ = out_set_->Extend(zone, value); |
| 380 } |
| 378 OutSet* out_set() { return out_set_; } | 381 OutSet* out_set() { return out_set_; } |
| 379 private: | 382 private: |
| 380 uc16 from_; | 383 uc16 from_; |
| 381 uc16 to_; | 384 uc16 to_; |
| 382 OutSet* out_set_; | 385 OutSet* out_set_; |
| 383 }; | 386 }; |
| 384 | 387 |
| 385 class Config { | 388 class Config { |
| 386 public: | 389 public: |
| 387 typedef uc16 Key; | 390 typedef uc16 Key; |
| 388 typedef Entry Value; | 391 typedef Entry Value; |
| 389 static const uc16 kNoKey; | 392 static const uc16 kNoKey; |
| 390 static const Entry kNoValue; | 393 static const Entry kNoValue; |
| 391 static inline int Compare(uc16 a, uc16 b) { | 394 static inline int Compare(uc16 a, uc16 b) { |
| 392 if (a == b) | 395 if (a == b) |
| 393 return 0; | 396 return 0; |
| 394 else if (a < b) | 397 else if (a < b) |
| 395 return -1; | 398 return -1; |
| 396 else | 399 else |
| 397 return 1; | 400 return 1; |
| 398 } | 401 } |
| 399 }; | 402 }; |
| 400 | 403 |
| 404 explicit DispatchTable(Zone* zone) : zone_(zone), tree_(zone) {} |
| 405 |
| 401 void AddRange(CharacterRange range, int value); | 406 void AddRange(CharacterRange range, int value); |
| 402 OutSet* Get(uc16 value); | 407 OutSet* Get(uc16 value); |
| 403 void Dump(); | 408 void Dump(); |
| 404 | 409 |
| 405 template <typename Callback> | 410 template <typename Callback> |
| 406 void ForEach(Callback* callback) { return tree()->ForEach(callback); } | 411 void ForEach(Callback* callback) { return tree()->ForEach(callback); } |
| 407 private: | 412 private: |
| 408 // There can't be a static empty set since it allocates its | 413 // There can't be a static empty set since it allocates its |
| 409 // successors in a zone and caches them. | 414 // successors in a zone and caches them. |
| 410 OutSet* empty() { return &empty_; } | 415 OutSet* empty() { return &empty_; } |
| 416 Zone* zone_; |
| 411 OutSet empty_; | 417 OutSet empty_; |
| 412 ZoneSplayTree<Config>* tree() { return &tree_; } | 418 ZoneSplayTree<Config>* tree() { return &tree_; } |
| 413 ZoneSplayTree<Config> tree_; | 419 ZoneSplayTree<Config> tree_; |
| 414 }; | 420 }; |
| 415 | 421 |
| 416 | 422 |
| 417 #define FOR_EACH_NODE_TYPE(VISIT) \ | 423 #define FOR_EACH_NODE_TYPE(VISIT) \ |
| 418 VISIT(End) \ | 424 VISIT(End) \ |
| 419 VISIT(Action) \ | 425 VISIT(Action) \ |
| 420 VISIT(Choice) \ | 426 VISIT(Choice) \ |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 522 bool visited: 1; | 528 bool visited: 1; |
| 523 }; | 529 }; |
| 524 | 530 |
| 525 | 531 |
| 526 class SiblingList { | 532 class SiblingList { |
| 527 public: | 533 public: |
| 528 SiblingList() : list_(NULL) { } | 534 SiblingList() : list_(NULL) { } |
| 529 int length() { | 535 int length() { |
| 530 return list_ == NULL ? 0 : list_->length(); | 536 return list_ == NULL ? 0 : list_->length(); |
| 531 } | 537 } |
| 532 void Ensure(RegExpNode* parent) { | 538 void Ensure(Zone* zone, RegExpNode* parent) { |
| 533 if (list_ == NULL) { | 539 if (list_ == NULL) { |
| 534 list_ = new ZoneList<RegExpNode*>(2); | 540 list_ = ZoneList<RegExpNode*>::New(zone, 2); |
| 535 list_->Add(parent); | 541 list_->Add(parent); |
| 536 } | 542 } |
| 537 } | 543 } |
| 538 void Add(RegExpNode* node) { list_->Add(node); } | 544 void Add(RegExpNode* node) { list_->Add(node); } |
| 539 RegExpNode* Get(int index) { return list_->at(index); } | 545 RegExpNode* Get(int index) { return list_->at(index); } |
| 540 private: | 546 private: |
| 541 ZoneList<RegExpNode*>* list_; | 547 ZoneList<RegExpNode*>* list_; |
| 542 }; | 548 }; |
| 543 | 549 |
| 544 | 550 |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 638 // the deferred actions in the current trace and generating a goto. | 644 // the deferred actions in the current trace and generating a goto. |
| 639 static const int kMaxCopiesCodeGenerated = 10; | 645 static const int kMaxCopiesCodeGenerated = 10; |
| 640 | 646 |
| 641 NodeInfo* info() { return &info_; } | 647 NodeInfo* info() { return &info_; } |
| 642 | 648 |
| 643 void AddSibling(RegExpNode* node) { siblings_.Add(node); } | 649 void AddSibling(RegExpNode* node) { siblings_.Add(node); } |
| 644 | 650 |
| 645 // Static version of EnsureSibling that expresses the fact that the | 651 // Static version of EnsureSibling that expresses the fact that the |
| 646 // result has the same type as the input. | 652 // result has the same type as the input. |
| 647 template <class C> | 653 template <class C> |
| 648 static C* EnsureSibling(C* node, NodeInfo* info, bool* cloned) { | 654 static C* EnsureSibling(Zone* zone, C* node, NodeInfo* info, bool* cloned) { |
| 649 return static_cast<C*>(node->EnsureSibling(info, cloned)); | 655 return static_cast<C*>(node->EnsureSibling(zone, info, cloned)); |
| 650 } | 656 } |
| 651 | 657 |
| 652 SiblingList* siblings() { return &siblings_; } | 658 SiblingList* siblings() { return &siblings_; } |
| 653 void set_siblings(SiblingList* other) { siblings_ = *other; } | 659 void set_siblings(SiblingList* other) { siblings_ = *other; } |
| 654 | 660 |
| 655 // Return the set of possible next characters recognized by the regexp | 661 // Return the set of possible next characters recognized by the regexp |
| 656 // (or a safe subset, potentially the set of all characters). | 662 // (or a safe subset, potentially the set of all characters). |
| 657 ZoneList<CharacterRange>* FirstCharacterSet(); | 663 ZoneList<CharacterRange>* FirstCharacterSet(Zone* zone); |
| 658 | 664 |
| 659 // Compute (if possible within the budget of traversed nodes) the | 665 // Compute (if possible within the budget of traversed nodes) the |
| 660 // possible first characters of the input matched by this node and | 666 // possible first characters of the input matched by this node and |
| 661 // its continuation. Returns the remaining budget after the computation. | 667 // its continuation. Returns the remaining budget after the computation. |
| 662 // If the budget is spent, the result is negative, and the cached | 668 // If the budget is spent, the result is negative, and the cached |
| 663 // first_character_set_ value isn't set. | 669 // first_character_set_ value isn't set. |
| 664 virtual int ComputeFirstCharacterSet(int budget); | 670 virtual int ComputeFirstCharacterSet(Zone* zone, int budget); |
| 665 | 671 |
| 666 // Get and set the cached first character set value. | 672 // Get and set the cached first character set value. |
| 667 ZoneList<CharacterRange>* first_character_set() { | 673 ZoneList<CharacterRange>* first_character_set() { |
| 668 return first_character_set_; | 674 return first_character_set_; |
| 669 } | 675 } |
| 670 void set_first_character_set(ZoneList<CharacterRange>* character_set) { | 676 void set_first_character_set(ZoneList<CharacterRange>* character_set) { |
| 671 first_character_set_ = character_set; | 677 first_character_set_ = character_set; |
| 672 } | 678 } |
| 673 | 679 |
| 674 protected: | 680 protected: |
| 675 enum LimitResult { DONE, CONTINUE }; | 681 enum LimitResult { DONE, CONTINUE }; |
| 676 static const int kComputeFirstCharacterSetFail = -1; | 682 static const int kComputeFirstCharacterSetFail = -1; |
| 677 | 683 |
| 678 LimitResult LimitVersions(RegExpCompiler* compiler, Trace* trace); | 684 LimitResult LimitVersions(RegExpCompiler* compiler, Trace* trace); |
| 679 | 685 |
| 680 // Returns a sibling of this node whose interests and assumptions | 686 // Returns a sibling of this node whose interests and assumptions |
| 681 // match the ones in the given node info. If no sibling exists NULL | 687 // match the ones in the given node info. If no sibling exists NULL |
| 682 // is returned. | 688 // is returned. |
| 683 RegExpNode* TryGetSibling(NodeInfo* info); | 689 RegExpNode* TryGetSibling(NodeInfo* info); |
| 684 | 690 |
| 685 // Returns a sibling of this node whose interests match the ones in | 691 // Returns a sibling of this node whose interests match the ones in |
| 686 // the given node info. The info must not contain any assertions. | 692 // the given node info. The info must not contain any assertions. |
| 687 // If no node exists a new one will be created by cloning the current | 693 // If no node exists a new one will be created by cloning the current |
| 688 // node. The result will always be an instance of the same concrete | 694 // node. The result will always be an instance of the same concrete |
| 689 // class as this node. | 695 // class as this node. |
| 690 RegExpNode* EnsureSibling(NodeInfo* info, bool* cloned); | 696 RegExpNode* EnsureSibling(Zone* zone, NodeInfo* info, bool* cloned); |
| 691 | 697 |
| 692 // Returns a clone of this node initialized using the copy constructor | 698 // Returns a clone of this node initialized using the copy constructor |
| 693 // of its concrete class. Note that the node may have to be pre- | 699 // of its concrete class. Note that the node may have to be pre- |
| 694 // processed before it is on a usable state. | 700 // processed before it is on a usable state. |
| 695 virtual RegExpNode* Clone() = 0; | 701 virtual RegExpNode* Clone() = 0; |
| 696 | 702 |
| 697 private: | 703 private: |
| 698 static const int kFirstCharBudget = 10; | 704 static const int kFirstCharBudget = 10; |
| 699 Label label_; | 705 Label label_; |
| 700 NodeInfo info_; | 706 NodeInfo info_; |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 785 RegExpCompiler* compiler, | 791 RegExpCompiler* compiler, |
| 786 int filled_in, | 792 int filled_in, |
| 787 bool not_at_start) { | 793 bool not_at_start) { |
| 788 return on_success()->GetQuickCheckDetails( | 794 return on_success()->GetQuickCheckDetails( |
| 789 details, compiler, filled_in, not_at_start); | 795 details, compiler, filled_in, not_at_start); |
| 790 } | 796 } |
| 791 Type type() { return type_; } | 797 Type type() { return type_; } |
| 792 // TODO(erikcorry): We should allow some action nodes in greedy loops. | 798 // TODO(erikcorry): We should allow some action nodes in greedy loops. |
| 793 virtual int GreedyLoopTextLength() { return kNodeIsTooComplexForGreedyLoops; } | 799 virtual int GreedyLoopTextLength() { return kNodeIsTooComplexForGreedyLoops; } |
| 794 virtual ActionNode* Clone() { return new ActionNode(*this); } | 800 virtual ActionNode* Clone() { return new ActionNode(*this); } |
| 795 virtual int ComputeFirstCharacterSet(int budget); | 801 virtual int ComputeFirstCharacterSet(Zone* zone, int budget); |
| 796 private: | 802 private: |
| 797 union { | 803 union { |
| 798 struct { | 804 struct { |
| 799 int reg; | 805 int reg; |
| 800 int value; | 806 int value; |
| 801 } u_store_register; | 807 } u_store_register; |
| 802 struct { | 808 struct { |
| 803 int reg; | 809 int reg; |
| 804 } u_increment_register; | 810 } u_increment_register; |
| 805 struct { | 811 struct { |
| (...skipping 23 matching lines...) Expand all Loading... |
| 829 friend class DotPrinter; | 835 friend class DotPrinter; |
| 830 }; | 836 }; |
| 831 | 837 |
| 832 | 838 |
| 833 class TextNode: public SeqRegExpNode { | 839 class TextNode: public SeqRegExpNode { |
| 834 public: | 840 public: |
| 835 TextNode(ZoneList<TextElement>* elms, | 841 TextNode(ZoneList<TextElement>* elms, |
| 836 RegExpNode* on_success) | 842 RegExpNode* on_success) |
| 837 : SeqRegExpNode(on_success), | 843 : SeqRegExpNode(on_success), |
| 838 elms_(elms) { } | 844 elms_(elms) { } |
| 839 TextNode(RegExpCharacterClass* that, | 845 TextNode(Zone* zone, |
| 846 RegExpCharacterClass* that, |
| 840 RegExpNode* on_success) | 847 RegExpNode* on_success) |
| 841 : SeqRegExpNode(on_success), | 848 : SeqRegExpNode(on_success), |
| 842 elms_(new ZoneList<TextElement>(1)) { | 849 elms_(ZoneList<TextElement>::New(zone, 1)) { |
| 843 elms_->Add(TextElement::CharClass(that)); | 850 elms_->Add(TextElement::CharClass(that)); |
| 844 } | 851 } |
| 845 virtual void Accept(NodeVisitor* visitor); | 852 virtual void Accept(NodeVisitor* visitor); |
| 846 virtual void Emit(RegExpCompiler* compiler, Trace* trace); | 853 virtual void Emit(RegExpCompiler* compiler, Trace* trace); |
| 847 virtual int EatsAtLeast(int still_to_find, | 854 virtual int EatsAtLeast(int still_to_find, |
| 848 int recursion_depth, | 855 int recursion_depth, |
| 849 bool not_at_start); | 856 bool not_at_start); |
| 850 virtual void GetQuickCheckDetails(QuickCheckDetails* details, | 857 virtual void GetQuickCheckDetails(QuickCheckDetails* details, |
| 851 RegExpCompiler* compiler, | 858 RegExpCompiler* compiler, |
| 852 int characters_filled_in, | 859 int characters_filled_in, |
| 853 bool not_at_start); | 860 bool not_at_start); |
| 854 ZoneList<TextElement>* elements() { return elms_; } | 861 ZoneList<TextElement>* elements() { return elms_; } |
| 855 void MakeCaseIndependent(bool is_ascii); | 862 void MakeCaseIndependent(Zone* zone, bool is_ascii); |
| 856 virtual int GreedyLoopTextLength(); | 863 virtual int GreedyLoopTextLength(); |
| 857 virtual TextNode* Clone() { | 864 virtual TextNode* Clone() { |
| 858 TextNode* result = new TextNode(*this); | 865 TextNode* result = new TextNode(*this); |
| 859 result->CalculateOffsets(); | 866 result->CalculateOffsets(); |
| 860 return result; | 867 return result; |
| 861 } | 868 } |
| 862 void CalculateOffsets(); | 869 void CalculateOffsets(); |
| 863 virtual int ComputeFirstCharacterSet(int budget); | 870 virtual int ComputeFirstCharacterSet(Zone* zone, int budget); |
| 864 private: | 871 private: |
| 865 enum TextEmitPassType { | 872 enum TextEmitPassType { |
| 866 NON_ASCII_MATCH, // Check for characters that can't match. | 873 NON_ASCII_MATCH, // Check for characters that can't match. |
| 867 SIMPLE_CHARACTER_MATCH, // Case-dependent single character check. | 874 SIMPLE_CHARACTER_MATCH, // Case-dependent single character check. |
| 868 NON_LETTER_CHARACTER_MATCH, // Check characters that have no case equivs. | 875 NON_LETTER_CHARACTER_MATCH, // Check characters that have no case equivs. |
| 869 CASE_CHARACTER_MATCH, // Case-independent single character check. | 876 CASE_CHARACTER_MATCH, // Case-independent single character check. |
| 870 CHARACTER_CLASS_MATCH // Character class. | 877 CHARACTER_CLASS_MATCH // Character class. |
| 871 }; | 878 }; |
| 872 static bool SkipPass(int pass, bool ignore_case); | 879 static bool SkipPass(int pass, bool ignore_case); |
| 873 static const int kFirstRealPass = SIMPLE_CHARACTER_MATCH; | 880 static const int kFirstRealPass = SIMPLE_CHARACTER_MATCH; |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 914 } | 921 } |
| 915 virtual void Accept(NodeVisitor* visitor); | 922 virtual void Accept(NodeVisitor* visitor); |
| 916 virtual void Emit(RegExpCompiler* compiler, Trace* trace); | 923 virtual void Emit(RegExpCompiler* compiler, Trace* trace); |
| 917 virtual int EatsAtLeast(int still_to_find, | 924 virtual int EatsAtLeast(int still_to_find, |
| 918 int recursion_depth, | 925 int recursion_depth, |
| 919 bool not_at_start); | 926 bool not_at_start); |
| 920 virtual void GetQuickCheckDetails(QuickCheckDetails* details, | 927 virtual void GetQuickCheckDetails(QuickCheckDetails* details, |
| 921 RegExpCompiler* compiler, | 928 RegExpCompiler* compiler, |
| 922 int filled_in, | 929 int filled_in, |
| 923 bool not_at_start); | 930 bool not_at_start); |
| 924 virtual int ComputeFirstCharacterSet(int budget); | 931 virtual int ComputeFirstCharacterSet(Zone* zone, int budget); |
| 925 virtual AssertionNode* Clone() { return new AssertionNode(*this); } | 932 virtual AssertionNode* Clone() { return new AssertionNode(*this); } |
| 926 AssertionNodeType type() { return type_; } | 933 AssertionNodeType type() { return type_; } |
| 927 void set_type(AssertionNodeType type) { type_ = type; } | 934 void set_type(AssertionNodeType type) { type_ = type; } |
| 928 private: | 935 private: |
| 929 AssertionNode(AssertionNodeType t, RegExpNode* on_success) | 936 AssertionNode(AssertionNodeType t, RegExpNode* on_success) |
| 930 : SeqRegExpNode(on_success), type_(t) { } | 937 : SeqRegExpNode(on_success), type_(t) { } |
| 931 AssertionNodeType type_; | 938 AssertionNodeType type_; |
| 932 }; | 939 }; |
| 933 | 940 |
| 934 | 941 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 947 virtual int EatsAtLeast(int still_to_find, | 954 virtual int EatsAtLeast(int still_to_find, |
| 948 int recursion_depth, | 955 int recursion_depth, |
| 949 bool not_at_start); | 956 bool not_at_start); |
| 950 virtual void GetQuickCheckDetails(QuickCheckDetails* details, | 957 virtual void GetQuickCheckDetails(QuickCheckDetails* details, |
| 951 RegExpCompiler* compiler, | 958 RegExpCompiler* compiler, |
| 952 int characters_filled_in, | 959 int characters_filled_in, |
| 953 bool not_at_start) { | 960 bool not_at_start) { |
| 954 return; | 961 return; |
| 955 } | 962 } |
| 956 virtual BackReferenceNode* Clone() { return new BackReferenceNode(*this); } | 963 virtual BackReferenceNode* Clone() { return new BackReferenceNode(*this); } |
| 957 virtual int ComputeFirstCharacterSet(int budget); | 964 virtual int ComputeFirstCharacterSet(Zone* zone, int budget); |
| 958 private: | 965 private: |
| 959 int start_reg_; | 966 int start_reg_; |
| 960 int end_reg_; | 967 int end_reg_; |
| 961 }; | 968 }; |
| 962 | 969 |
| 963 | 970 |
| 964 class EndNode: public RegExpNode { | 971 class EndNode: public RegExpNode { |
| 965 public: | 972 public: |
| 966 enum Action { ACCEPT, BACKTRACK, NEGATIVE_SUBMATCH_SUCCESS }; | 973 enum Action { ACCEPT, BACKTRACK, NEGATIVE_SUBMATCH_SUCCESS }; |
| 967 explicit EndNode(Action action) : action_(action) { } | 974 explicit EndNode(Action action) : action_(action) { } |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1018 private: | 1025 private: |
| 1019 int reg_; | 1026 int reg_; |
| 1020 Relation op_; | 1027 Relation op_; |
| 1021 int value_; | 1028 int value_; |
| 1022 }; | 1029 }; |
| 1023 | 1030 |
| 1024 | 1031 |
| 1025 class GuardedAlternative { | 1032 class GuardedAlternative { |
| 1026 public: | 1033 public: |
| 1027 explicit GuardedAlternative(RegExpNode* node) : node_(node), guards_(NULL) { } | 1034 explicit GuardedAlternative(RegExpNode* node) : node_(node), guards_(NULL) { } |
| 1028 void AddGuard(Guard* guard); | 1035 void AddGuard(Zone* zone, Guard* guard); |
| 1029 RegExpNode* node() { return node_; } | 1036 RegExpNode* node() { return node_; } |
| 1030 void set_node(RegExpNode* node) { node_ = node; } | 1037 void set_node(RegExpNode* node) { node_ = node; } |
| 1031 ZoneList<Guard*>* guards() { return guards_; } | 1038 ZoneList<Guard*>* guards() { return guards_; } |
| 1032 | 1039 |
| 1033 private: | 1040 private: |
| 1034 RegExpNode* node_; | 1041 RegExpNode* node_; |
| 1035 ZoneList<Guard*>* guards_; | 1042 ZoneList<Guard*>* guards_; |
| 1036 }; | 1043 }; |
| 1037 | 1044 |
| 1038 | 1045 |
| 1039 class AlternativeGeneration; | 1046 class AlternativeGeneration; |
| 1040 | 1047 |
| 1041 | 1048 |
| 1042 class ChoiceNode: public RegExpNode { | 1049 class ChoiceNode: public RegExpNode { |
| 1043 public: | 1050 public: |
| 1044 explicit ChoiceNode(int expected_size) | 1051 ChoiceNode(Zone* zone, int expected_size) |
| 1045 : alternatives_(new ZoneList<GuardedAlternative>(expected_size)), | 1052 : alternatives_(ZoneList<GuardedAlternative>::New(zone, expected_size)), |
| 1046 table_(NULL), | 1053 table_(NULL), |
| 1047 not_at_start_(false), | 1054 not_at_start_(false), |
| 1048 being_calculated_(false) { } | 1055 being_calculated_(false) { } |
| 1049 virtual void Accept(NodeVisitor* visitor); | 1056 virtual void Accept(NodeVisitor* visitor); |
| 1050 void AddAlternative(GuardedAlternative node) { alternatives()->Add(node); } | 1057 void AddAlternative(GuardedAlternative node) { alternatives()->Add(node); } |
| 1051 ZoneList<GuardedAlternative>* alternatives() { return alternatives_; } | 1058 ZoneList<GuardedAlternative>* alternatives() { return alternatives_; } |
| 1052 DispatchTable* GetTable(bool ignore_case); | 1059 DispatchTable* GetTable(Zone* zone, bool ignore_case); |
| 1053 virtual void Emit(RegExpCompiler* compiler, Trace* trace); | 1060 virtual void Emit(RegExpCompiler* compiler, Trace* trace); |
| 1054 virtual int EatsAtLeast(int still_to_find, | 1061 virtual int EatsAtLeast(int still_to_find, |
| 1055 int recursion_depth, | 1062 int recursion_depth, |
| 1056 bool not_at_start); | 1063 bool not_at_start); |
| 1057 int EatsAtLeastHelper(int still_to_find, | 1064 int EatsAtLeastHelper(int still_to_find, |
| 1058 int recursion_depth, | 1065 int recursion_depth, |
| 1059 RegExpNode* ignore_this_node, | 1066 RegExpNode* ignore_this_node, |
| 1060 bool not_at_start); | 1067 bool not_at_start); |
| 1061 virtual void GetQuickCheckDetails(QuickCheckDetails* details, | 1068 virtual void GetQuickCheckDetails(QuickCheckDetails* details, |
| 1062 RegExpCompiler* compiler, | 1069 RegExpCompiler* compiler, |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1090 DispatchTable* table_; | 1097 DispatchTable* table_; |
| 1091 // If true, this node is never checked at the start of the input. | 1098 // If true, this node is never checked at the start of the input. |
| 1092 // Allows a new trace to start with at_start() set to false. | 1099 // Allows a new trace to start with at_start() set to false. |
| 1093 bool not_at_start_; | 1100 bool not_at_start_; |
| 1094 bool being_calculated_; | 1101 bool being_calculated_; |
| 1095 }; | 1102 }; |
| 1096 | 1103 |
| 1097 | 1104 |
| 1098 class NegativeLookaheadChoiceNode: public ChoiceNode { | 1105 class NegativeLookaheadChoiceNode: public ChoiceNode { |
| 1099 public: | 1106 public: |
| 1100 explicit NegativeLookaheadChoiceNode(GuardedAlternative this_must_fail, | 1107 explicit NegativeLookaheadChoiceNode(Zone* zone, |
| 1108 GuardedAlternative this_must_fail, |
| 1101 GuardedAlternative then_do_this) | 1109 GuardedAlternative then_do_this) |
| 1102 : ChoiceNode(2) { | 1110 : ChoiceNode(zone, 2) { |
| 1103 AddAlternative(this_must_fail); | 1111 AddAlternative(this_must_fail); |
| 1104 AddAlternative(then_do_this); | 1112 AddAlternative(then_do_this); |
| 1105 } | 1113 } |
| 1106 virtual int EatsAtLeast(int still_to_find, | 1114 virtual int EatsAtLeast(int still_to_find, |
| 1107 int recursion_depth, | 1115 int recursion_depth, |
| 1108 bool not_at_start); | 1116 bool not_at_start); |
| 1109 virtual void GetQuickCheckDetails(QuickCheckDetails* details, | 1117 virtual void GetQuickCheckDetails(QuickCheckDetails* details, |
| 1110 RegExpCompiler* compiler, | 1118 RegExpCompiler* compiler, |
| 1111 int characters_filled_in, | 1119 int characters_filled_in, |
| 1112 bool not_at_start); | 1120 bool not_at_start); |
| 1113 // For a negative lookahead we don't emit the quick check for the | 1121 // For a negative lookahead we don't emit the quick check for the |
| 1114 // alternative that is expected to fail. This is because quick check code | 1122 // alternative that is expected to fail. This is because quick check code |
| 1115 // starts by loading enough characters for the alternative that takes fewest | 1123 // starts by loading enough characters for the alternative that takes fewest |
| 1116 // characters, but on a negative lookahead the negative branch did not take | 1124 // characters, but on a negative lookahead the negative branch did not take |
| 1117 // part in that calculation (EatsAtLeast) so the assumptions don't hold. | 1125 // part in that calculation (EatsAtLeast) so the assumptions don't hold. |
| 1118 virtual bool try_to_emit_quick_check_for_alternative(int i) { return i != 0; } | 1126 virtual bool try_to_emit_quick_check_for_alternative(int i) { return i != 0; } |
| 1119 virtual int ComputeFirstCharacterSet(int budget); | 1127 virtual int ComputeFirstCharacterSet(Zone* zone, int budget); |
| 1120 }; | 1128 }; |
| 1121 | 1129 |
| 1122 | 1130 |
| 1123 class LoopChoiceNode: public ChoiceNode { | 1131 class LoopChoiceNode: public ChoiceNode { |
| 1124 public: | 1132 public: |
| 1125 explicit LoopChoiceNode(bool body_can_be_zero_length) | 1133 LoopChoiceNode(Zone* zone, bool body_can_be_zero_length) |
| 1126 : ChoiceNode(2), | 1134 : ChoiceNode(zone, 2), |
| 1127 loop_node_(NULL), | 1135 loop_node_(NULL), |
| 1128 continue_node_(NULL), | 1136 continue_node_(NULL), |
| 1129 body_can_be_zero_length_(body_can_be_zero_length) { } | 1137 body_can_be_zero_length_(body_can_be_zero_length) { } |
| 1130 void AddLoopAlternative(GuardedAlternative alt); | 1138 void AddLoopAlternative(GuardedAlternative alt); |
| 1131 void AddContinueAlternative(GuardedAlternative alt); | 1139 void AddContinueAlternative(GuardedAlternative alt); |
| 1132 virtual void Emit(RegExpCompiler* compiler, Trace* trace); | 1140 virtual void Emit(RegExpCompiler* compiler, Trace* trace); |
| 1133 virtual int EatsAtLeast(int still_to_find, | 1141 virtual int EatsAtLeast(int still_to_find, |
| 1134 int recursion_depth, | 1142 int recursion_depth, |
| 1135 bool not_at_start); | 1143 bool not_at_start); |
| 1136 virtual void GetQuickCheckDetails(QuickCheckDetails* details, | 1144 virtual void GetQuickCheckDetails(QuickCheckDetails* details, |
| 1137 RegExpCompiler* compiler, | 1145 RegExpCompiler* compiler, |
| 1138 int characters_filled_in, | 1146 int characters_filled_in, |
| 1139 bool not_at_start); | 1147 bool not_at_start); |
| 1140 virtual int ComputeFirstCharacterSet(int budget); | 1148 virtual int ComputeFirstCharacterSet(Zone* zone, int budget); |
| 1141 virtual LoopChoiceNode* Clone() { return new LoopChoiceNode(*this); } | 1149 virtual LoopChoiceNode* Clone() { return new LoopChoiceNode(*this); } |
| 1142 RegExpNode* loop_node() { return loop_node_; } | 1150 RegExpNode* loop_node() { return loop_node_; } |
| 1143 RegExpNode* continue_node() { return continue_node_; } | 1151 RegExpNode* continue_node() { return continue_node_; } |
| 1144 bool body_can_be_zero_length() { return body_can_be_zero_length_; } | 1152 bool body_can_be_zero_length() { return body_can_be_zero_length_; } |
| 1145 virtual void Accept(NodeVisitor* visitor); | 1153 virtual void Accept(NodeVisitor* visitor); |
| 1146 | 1154 |
| 1147 private: | 1155 private: |
| 1148 // AddAlternative is made private for loop nodes because alternatives | 1156 // AddAlternative is made private for loop nodes because alternatives |
| 1149 // should not be added freely, we need to keep track of which node | 1157 // should not be added freely, we need to keep track of which node |
| 1150 // goes back to the node itself. | 1158 // goes back to the node itself. |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1295 void set_loop_label(Label* label) { loop_label_ = label; } | 1303 void set_loop_label(Label* label) { loop_label_ = label; } |
| 1296 void set_characters_preloaded(int count) { characters_preloaded_ = count; } | 1304 void set_characters_preloaded(int count) { characters_preloaded_ = count; } |
| 1297 void set_bound_checked_up_to(int to) { bound_checked_up_to_ = to; } | 1305 void set_bound_checked_up_to(int to) { bound_checked_up_to_ = to; } |
| 1298 void set_flush_budget(int to) { flush_budget_ = to; } | 1306 void set_flush_budget(int to) { flush_budget_ = to; } |
| 1299 void set_quick_check_performed(QuickCheckDetails* d) { | 1307 void set_quick_check_performed(QuickCheckDetails* d) { |
| 1300 quick_check_performed_ = *d; | 1308 quick_check_performed_ = *d; |
| 1301 } | 1309 } |
| 1302 void InvalidateCurrentCharacter(); | 1310 void InvalidateCurrentCharacter(); |
| 1303 void AdvanceCurrentPositionInTrace(int by, RegExpCompiler* compiler); | 1311 void AdvanceCurrentPositionInTrace(int by, RegExpCompiler* compiler); |
| 1304 private: | 1312 private: |
| 1305 int FindAffectedRegisters(OutSet* affected_registers); | 1313 int FindAffectedRegisters(Zone* zone, OutSet* affected_registers); |
| 1306 void PerformDeferredActions(RegExpMacroAssembler* macro, | 1314 void PerformDeferredActions(Zone* zone, |
| 1307 int max_register, | 1315 RegExpMacroAssembler* macro, |
| 1308 OutSet& affected_registers, | 1316 int max_register, |
| 1309 OutSet* registers_to_pop, | 1317 OutSet& affected_registers, |
| 1310 OutSet* registers_to_clear); | 1318 OutSet* registers_to_pop, |
| 1319 OutSet* registers_to_clear); |
| 1311 void RestoreAffectedRegisters(RegExpMacroAssembler* macro, | 1320 void RestoreAffectedRegisters(RegExpMacroAssembler* macro, |
| 1312 int max_register, | 1321 int max_register, |
| 1313 OutSet& registers_to_pop, | 1322 OutSet& registers_to_pop, |
| 1314 OutSet& registers_to_clear); | 1323 OutSet& registers_to_clear); |
| 1315 int cp_offset_; | 1324 int cp_offset_; |
| 1316 DeferredAction* actions_; | 1325 DeferredAction* actions_; |
| 1317 Label* backtrack_; | 1326 Label* backtrack_; |
| 1318 RegExpNode* stop_node_; | 1327 RegExpNode* stop_node_; |
| 1319 Label* loop_label_; | 1328 Label* loop_label_; |
| 1320 int characters_preloaded_; | 1329 int characters_preloaded_; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1333 FOR_EACH_NODE_TYPE(DECLARE_VISIT) | 1342 FOR_EACH_NODE_TYPE(DECLARE_VISIT) |
| 1334 #undef DECLARE_VISIT | 1343 #undef DECLARE_VISIT |
| 1335 virtual void VisitLoopChoice(LoopChoiceNode* that) { VisitChoice(that); } | 1344 virtual void VisitLoopChoice(LoopChoiceNode* that) { VisitChoice(that); } |
| 1336 }; | 1345 }; |
| 1337 | 1346 |
| 1338 | 1347 |
| 1339 // Node visitor used to add the start set of the alternatives to the | 1348 // Node visitor used to add the start set of the alternatives to the |
| 1340 // dispatch table of a choice node. | 1349 // dispatch table of a choice node. |
| 1341 class DispatchTableConstructor: public NodeVisitor { | 1350 class DispatchTableConstructor: public NodeVisitor { |
| 1342 public: | 1351 public: |
| 1343 DispatchTableConstructor(DispatchTable* table, bool ignore_case) | 1352 DispatchTableConstructor(Zone* zone, DispatchTable* table, bool ignore_case) |
| 1344 : table_(table), | 1353 : zone_(zone), |
| 1354 table_(table), |
| 1345 choice_index_(-1), | 1355 choice_index_(-1), |
| 1346 ignore_case_(ignore_case) { } | 1356 ignore_case_(ignore_case) { } |
| 1347 | 1357 |
| 1348 void BuildTable(ChoiceNode* node); | 1358 void BuildTable(ChoiceNode* node); |
| 1349 | 1359 |
| 1350 void AddRange(CharacterRange range) { | 1360 void AddRange(CharacterRange range) { |
| 1351 table()->AddRange(range, choice_index_); | 1361 table()->AddRange(range, choice_index_); |
| 1352 } | 1362 } |
| 1353 | 1363 |
| 1354 void AddInverse(ZoneList<CharacterRange>* ranges); | 1364 void AddInverse(ZoneList<CharacterRange>* ranges); |
| 1355 | 1365 |
| 1356 #define DECLARE_VISIT(Type) \ | 1366 #define DECLARE_VISIT(Type) \ |
| 1357 virtual void Visit##Type(Type##Node* that); | 1367 virtual void Visit##Type(Type##Node* that); |
| 1358 FOR_EACH_NODE_TYPE(DECLARE_VISIT) | 1368 FOR_EACH_NODE_TYPE(DECLARE_VISIT) |
| 1359 #undef DECLARE_VISIT | 1369 #undef DECLARE_VISIT |
| 1360 | 1370 |
| 1361 DispatchTable* table() { return table_; } | 1371 DispatchTable* table() { return table_; } |
| 1362 void set_choice_index(int value) { choice_index_ = value; } | 1372 void set_choice_index(int value) { choice_index_ = value; } |
| 1363 | 1373 |
| 1364 protected: | 1374 protected: |
| 1375 Zone* zone_; |
| 1365 DispatchTable* table_; | 1376 DispatchTable* table_; |
| 1366 int choice_index_; | 1377 int choice_index_; |
| 1367 bool ignore_case_; | 1378 bool ignore_case_; |
| 1368 }; | 1379 }; |
| 1369 | 1380 |
| 1370 | 1381 |
| 1371 // Assertion propagation moves information about assertions such as | 1382 // Assertion propagation moves information about assertions such as |
| 1372 // \b to the affected nodes. For instance, in /.\b./ information must | 1383 // \b to the affected nodes. For instance, in /.\b./ information must |
| 1373 // be propagated to the first '.' that whatever follows needs to know | 1384 // be propagated to the first '.' that whatever follows needs to know |
| 1374 // if it matched a word or a non-word, and to the second '.' that it | 1385 // if it matched a word or a non-word, and to the second '.' that it |
| 1375 // has to check if it succeeds a word or non-word. In this case the | 1386 // has to check if it succeeds a word or non-word. In this case the |
| 1376 // result will be something like: | 1387 // result will be something like: |
| 1377 // | 1388 // |
| 1378 // +-------+ +------------+ | 1389 // +-------+ +------------+ |
| 1379 // | . | | . | | 1390 // | . | | . | |
| 1380 // +-------+ ---> +------------+ | 1391 // +-------+ ---> +------------+ |
| 1381 // | word? | | check word | | 1392 // | word? | | check word | |
| 1382 // +-------+ +------------+ | 1393 // +-------+ +------------+ |
| 1383 class Analysis: public NodeVisitor { | 1394 class Analysis: public NodeVisitor { |
| 1384 public: | 1395 public: |
| 1385 Analysis(bool ignore_case, bool is_ascii) | 1396 Analysis(Zone* zone, bool ignore_case, bool is_ascii) |
| 1386 : ignore_case_(ignore_case), | 1397 : zone_(zone), |
| 1398 ignore_case_(ignore_case), |
| 1387 is_ascii_(is_ascii), | 1399 is_ascii_(is_ascii), |
| 1388 error_message_(NULL) { } | 1400 error_message_(NULL) { } |
| 1389 void EnsureAnalyzed(RegExpNode* node); | 1401 void EnsureAnalyzed(RegExpNode* node); |
| 1390 | 1402 |
| 1391 #define DECLARE_VISIT(Type) \ | 1403 #define DECLARE_VISIT(Type) \ |
| 1392 virtual void Visit##Type(Type##Node* that); | 1404 virtual void Visit##Type(Type##Node* that); |
| 1393 FOR_EACH_NODE_TYPE(DECLARE_VISIT) | 1405 FOR_EACH_NODE_TYPE(DECLARE_VISIT) |
| 1394 #undef DECLARE_VISIT | 1406 #undef DECLARE_VISIT |
| 1395 virtual void VisitLoopChoice(LoopChoiceNode* that); | 1407 virtual void VisitLoopChoice(LoopChoiceNode* that); |
| 1396 | 1408 |
| 1397 bool has_failed() { return error_message_ != NULL; } | 1409 bool has_failed() { return error_message_ != NULL; } |
| 1398 const char* error_message() { | 1410 const char* error_message() { |
| 1399 ASSERT(error_message_ != NULL); | 1411 ASSERT(error_message_ != NULL); |
| 1400 return error_message_; | 1412 return error_message_; |
| 1401 } | 1413 } |
| 1402 void fail(const char* error_message) { | 1414 void fail(const char* error_message) { |
| 1403 error_message_ = error_message; | 1415 error_message_ = error_message; |
| 1404 } | 1416 } |
| 1405 private: | 1417 private: |
| 1418 Zone* zone_; |
| 1406 bool ignore_case_; | 1419 bool ignore_case_; |
| 1407 bool is_ascii_; | 1420 bool is_ascii_; |
| 1408 const char* error_message_; | 1421 const char* error_message_; |
| 1409 | 1422 |
| 1410 DISALLOW_IMPLICIT_CONSTRUCTORS(Analysis); | 1423 DISALLOW_IMPLICIT_CONSTRUCTORS(Analysis); |
| 1411 }; | 1424 }; |
| 1412 | 1425 |
| 1413 | 1426 |
| 1414 struct RegExpCompileData { | 1427 struct RegExpCompileData { |
| 1415 RegExpCompileData() | 1428 RegExpCompileData() |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1482 int* vector_; | 1495 int* vector_; |
| 1483 int offsets_vector_length_; | 1496 int offsets_vector_length_; |
| 1484 | 1497 |
| 1485 friend class ExternalReference; | 1498 friend class ExternalReference; |
| 1486 }; | 1499 }; |
| 1487 | 1500 |
| 1488 | 1501 |
| 1489 } } // namespace v8::internal | 1502 } } // namespace v8::internal |
| 1490 | 1503 |
| 1491 #endif // V8_JSREGEXP_H_ | 1504 #endif // V8_JSREGEXP_H_ |
| OLD | NEW |