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

Side by Side Diff: src/jsregexp.h

Issue 14892: Merge changes from bleeding_edge into experimental toiger branch.... (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/toiger/
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 | Annotate | Revision Log
« no previous file with comments | « src/interpreter-irregexp.cc ('k') | src/jsregexp.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 421 matching lines...) Expand 10 before | Expand all | Expand 10 after
432 #undef FORWARD_DECLARE 432 #undef FORWARD_DECLARE
433 433
434 434
435 class TextElement { 435 class TextElement {
436 public: 436 public:
437 enum Type {UNINITIALIZED, ATOM, CHAR_CLASS}; 437 enum Type {UNINITIALIZED, ATOM, CHAR_CLASS};
438 TextElement() : type(UNINITIALIZED) { } 438 TextElement() : type(UNINITIALIZED) { }
439 explicit TextElement(Type t) : type(t), cp_offset(-1) { } 439 explicit TextElement(Type t) : type(t), cp_offset(-1) { }
440 static TextElement Atom(RegExpAtom* atom); 440 static TextElement Atom(RegExpAtom* atom);
441 static TextElement CharClass(RegExpCharacterClass* char_class); 441 static TextElement CharClass(RegExpCharacterClass* char_class);
442 int length();
442 Type type; 443 Type type;
443 union { 444 union {
444 RegExpAtom* u_atom; 445 RegExpAtom* u_atom;
445 RegExpCharacterClass* u_char_class; 446 RegExpCharacterClass* u_char_class;
446 } data; 447 } data;
447 int cp_offset; 448 int cp_offset;
448 }; 449 };
449 450
450 451
451 class GenerationVariant; 452 class GenerationVariant;
452 453
453 454
454 struct NodeInfo { 455 struct NodeInfo {
455 enum TriBool { 456 enum TriBool {
456 UNKNOWN = -1, FALSE = 0, TRUE = 1 457 UNKNOWN = -1, FALSE = 0, TRUE = 1
457 }; 458 };
458 459
459 NodeInfo() 460 NodeInfo()
460 : being_analyzed(false), 461 : being_analyzed(false),
461 been_analyzed(false), 462 been_analyzed(false),
462 being_expanded(false),
463 been_expanded(false),
464 determine_word(false),
465 determine_newline(false),
466 determine_start(false),
467 does_determine_word(false),
468 does_determine_newline(false),
469 does_determine_start(false),
470 follows_word_interest(false), 463 follows_word_interest(false),
471 follows_newline_interest(false), 464 follows_newline_interest(false),
472 follows_start_interest(false), 465 follows_start_interest(false),
473 is_word(UNKNOWN),
474 is_newline(UNKNOWN),
475 at_end(false), 466 at_end(false),
476 follows_word(UNKNOWN),
477 follows_newline(UNKNOWN),
478 follows_start(UNKNOWN),
479 visited(false) { } 467 visited(false) { }
480 468
481 // Returns true if the interests and assumptions of this node 469 // Returns true if the interests and assumptions of this node
482 // matches the given one. 470 // matches the given one.
483 bool Matches(NodeInfo* that) { 471 bool Matches(NodeInfo* that) {
484 return (at_end == that->at_end) && 472 return (at_end == that->at_end) &&
485 (follows_word_interest == that->follows_word_interest) && 473 (follows_word_interest == that->follows_word_interest) &&
486 (follows_newline_interest == that->follows_newline_interest) && 474 (follows_newline_interest == that->follows_newline_interest) &&
487 (follows_start_interest == that->follows_start_interest) && 475 (follows_start_interest == that->follows_start_interest);
488 (follows_word == that->follows_word) &&
489 (follows_newline == that->follows_newline) &&
490 (follows_start == that->follows_start) &&
491 (does_determine_word == that->does_determine_word) &&
492 (does_determine_newline == that->does_determine_newline) &&
493 (does_determine_start == that->does_determine_start);
494 }
495
496 bool HasAssertions() {
497 return (follows_word != UNKNOWN) ||
498 (follows_newline != UNKNOWN) ||
499 (follows_start != UNKNOWN);
500 } 476 }
501 477
502 // Updates the interests of this node given the interests of the 478 // Updates the interests of this node given the interests of the
503 // node preceding it. 479 // node preceding it.
504 void AddFromPreceding(NodeInfo* that) { 480 void AddFromPreceding(NodeInfo* that) {
505 at_end |= that->at_end; 481 at_end |= that->at_end;
506 follows_word_interest |= that->follows_word_interest; 482 follows_word_interest |= that->follows_word_interest;
507 follows_newline_interest |= that->follows_newline_interest; 483 follows_newline_interest |= that->follows_newline_interest;
508 follows_start_interest |= that->follows_start_interest; 484 follows_start_interest |= that->follows_start_interest;
509 } 485 }
510 486
511 void AddAssumptions(NodeInfo* that) {
512 if (that->follows_word != UNKNOWN) {
513 ASSERT(follows_word == UNKNOWN || follows_word == that->follows_word);
514 follows_word = that->follows_word;
515 }
516 if (that->follows_newline != UNKNOWN) {
517 ASSERT(follows_newline == UNKNOWN ||
518 follows_newline == that->follows_newline);
519 follows_newline = that->follows_newline;
520 }
521 if (that->follows_start != UNKNOWN) {
522 ASSERT(follows_start == UNKNOWN ||
523 follows_start == that->follows_start);
524 follows_start = that->follows_start;
525 }
526 does_determine_word = that->does_determine_word;
527 does_determine_newline = that->does_determine_newline;
528 does_determine_start = that->does_determine_start;
529 }
530
531 bool HasLookbehind() { 487 bool HasLookbehind() {
532 return follows_word_interest || 488 return follows_word_interest ||
533 follows_newline_interest || 489 follows_newline_interest ||
534 follows_start_interest; 490 follows_start_interest;
535 } 491 }
536 492
537 // Sets the interests of this node to include the interests of the 493 // Sets the interests of this node to include the interests of the
538 // following node. 494 // following node.
539 void AddFromFollowing(NodeInfo* that) { 495 void AddFromFollowing(NodeInfo* that) {
540 follows_word_interest |= that->follows_word_interest; 496 follows_word_interest |= that->follows_word_interest;
541 follows_newline_interest |= that->follows_newline_interest; 497 follows_newline_interest |= that->follows_newline_interest;
542 follows_start_interest |= that->follows_start_interest; 498 follows_start_interest |= that->follows_start_interest;
543 } 499 }
544 500
545 void ResetCompilationState() { 501 void ResetCompilationState() {
546 being_analyzed = false; 502 being_analyzed = false;
547 been_analyzed = false; 503 been_analyzed = false;
548 being_expanded = false;
549 been_expanded = false;
550 } 504 }
551 505
552 bool being_analyzed: 1; 506 bool being_analyzed: 1;
553 bool been_analyzed: 1; 507 bool been_analyzed: 1;
554 bool being_expanded: 1;
555 bool been_expanded: 1;
556
557 // These bits are set if this node must propagate forward information
558 // about the last character it consumed (or, in the case of 'start',
559 // if it is at the start of the input).
560 bool determine_word: 1;
561 bool determine_newline: 1;
562 bool determine_start: 1;
563
564 bool does_determine_word: 1;
565 bool does_determine_newline: 1;
566 bool does_determine_start: 1;
567 508
568 // These bits are set of this node has to know what the preceding 509 // These bits are set of this node has to know what the preceding
569 // character was. 510 // character was.
570 bool follows_word_interest: 1; 511 bool follows_word_interest: 1;
571 bool follows_newline_interest: 1; 512 bool follows_newline_interest: 1;
572 bool follows_start_interest: 1; 513 bool follows_start_interest: 1;
573 514
574 TriBool is_word: 2;
575 TriBool is_newline: 2;
576
577 bool at_end: 1; 515 bool at_end: 1;
578
579 // These bits are set if the node can make assumptions about what
580 // the previous character was.
581 TriBool follows_word: 2;
582 TriBool follows_newline: 2;
583 TriBool follows_start: 2;
584
585 bool visited: 1; 516 bool visited: 1;
586 }; 517 };
587 518
588 519
589 class ExpansionGuard {
590 public:
591 explicit inline ExpansionGuard(NodeInfo* info) : info_(info) {
592 ASSERT(!info->being_expanded);
593 info->being_expanded = true;
594 }
595 inline ~ExpansionGuard() {
596 info_->being_expanded = false;
597 }
598 private:
599 NodeInfo* info_;
600 };
601
602
603 class SiblingList { 520 class SiblingList {
604 public: 521 public:
605 SiblingList() : list_(NULL) { } 522 SiblingList() : list_(NULL) { }
606 int length() { 523 int length() {
607 return list_ == NULL ? 0 : list_->length(); 524 return list_ == NULL ? 0 : list_->length();
608 } 525 }
609 void Ensure(RegExpNode* parent) { 526 void Ensure(RegExpNode* parent) {
610 if (list_ == NULL) { 527 if (list_ == NULL) {
611 list_ = new ZoneList<RegExpNode*>(2); 528 list_ = new ZoneList<RegExpNode*>(2);
612 list_->Add(parent); 529 list_->Add(parent);
613 } 530 }
614 } 531 }
615 void Add(RegExpNode* node) { list_->Add(node); } 532 void Add(RegExpNode* node) { list_->Add(node); }
616 RegExpNode* Get(int index) { return list_->at(index); } 533 RegExpNode* Get(int index) { return list_->at(index); }
617 private: 534 private:
618 ZoneList<RegExpNode*>* list_; 535 ZoneList<RegExpNode*>* list_;
619 }; 536 };
620 537
621 538
539 // Details of a quick mask-compare check that can look ahead in the
540 // input stream.
541 class QuickCheckDetails {
542 public:
543 QuickCheckDetails()
544 : characters_(0),
545 mask_(0),
546 value_(0) { }
547 explicit QuickCheckDetails(int characters)
548 : characters_(characters),
549 mask_(0),
550 value_(0) { }
551 bool Rationalize(bool ascii);
552 // Merge in the information from another branch of an alternation.
553 void Merge(QuickCheckDetails* other, int from_index);
554 // Advance the current position by some amount.
555 void Advance(int by, bool ascii);
556 void Clear();
557 struct Position {
558 Position() : mask(0), value(0), determines_perfectly(false) { }
559 uc16 mask;
560 uc16 value;
561 bool determines_perfectly;
562 };
563 int characters() { return characters_; }
564 void set_characters(int characters) { characters_ = characters; }
565 Position* positions(int index) {
566 ASSERT(index >= 0);
567 ASSERT(index < characters_);
568 return positions_ + index;
569 }
570 uint32_t mask() { return mask_; }
571 uint32_t value() { return value_; }
572
573 private:
574 // How many characters do we have quick check information from. This is
575 // the same for all branches of a choice node.
576 int characters_;
577 Position positions_[4];
578 // These values are the condensate of the above array after Rationalize().
579 uint32_t mask_;
580 uint32_t value_;
581 };
582
583
622 class RegExpNode: public ZoneObject { 584 class RegExpNode: public ZoneObject {
623 public: 585 public:
624 RegExpNode() : variants_generated_(0) { } 586 RegExpNode() : variants_generated_(0) { }
625 virtual ~RegExpNode() { } 587 virtual ~RegExpNode();
626 virtual void Accept(NodeVisitor* visitor) = 0; 588 virtual void Accept(NodeVisitor* visitor) = 0;
627 // Generates a goto to this node or actually generates the code at this point. 589 // Generates a goto to this node or actually generates the code at this point.
628 // Until the implementation is complete we will return true for success and 590 // Until the implementation is complete we will return true for success and
629 // false for failure. 591 // false for failure.
630 virtual bool Emit(RegExpCompiler* compiler, GenerationVariant* variant) = 0; 592 virtual bool Emit(RegExpCompiler* compiler, GenerationVariant* variant) = 0;
593 // How many characters must this node consume at a minimum in order to
594 // succeed.
595 virtual int EatsAtLeast(int recursion_depth) = 0;
596 // Emits some quick code that checks whether the preloaded characters match.
597 // Falls through on certain failure, jumps to the label on possible success.
598 // If the node cannot make a quick check it does nothing and returns false.
599 bool EmitQuickCheck(RegExpCompiler* compiler,
600 GenerationVariant* variant,
601 bool preload_has_checked_bounds,
602 Label* on_possible_success,
603 QuickCheckDetails* details_return,
604 bool fall_through_on_failure);
605 // For a given number of characters this returns a mask and a value. The
606 // next n characters are anded with the mask and compared with the value.
607 // A comparison failure indicates the node cannot match the next n characters.
608 // A comparison success indicates the node may match.
609 virtual void GetQuickCheckDetails(QuickCheckDetails* details,
610 RegExpCompiler* compiler,
611 int characters_filled_in) = 0;
631 static const int kNodeIsTooComplexForGreedyLoops = -1; 612 static const int kNodeIsTooComplexForGreedyLoops = -1;
632 virtual int GreedyLoopTextLength() { return kNodeIsTooComplexForGreedyLoops; } 613 virtual int GreedyLoopTextLength() { return kNodeIsTooComplexForGreedyLoops; }
633 Label* label() { return &label_; } 614 Label* label() { return &label_; }
634 static const int kMaxVariantsGenerated = 10; 615 static const int kMaxVariantsGenerated = 10;
635 616
636 RegExpNode* EnsureExpanded(NodeInfo* info);
637 virtual RegExpNode* ExpandLocal(NodeInfo* info) = 0;
638 virtual void ExpandChildren() = 0;
639
640 // Propagates the given interest information forward. When seeing 617 // Propagates the given interest information forward. When seeing
641 // \bfoo for instance, the \b is implemented by propagating forward 618 // \bfoo for instance, the \b is implemented by propagating forward
642 // to the 'foo' string that it should only succeed if its first 619 // to the 'foo' string that it should only succeed if its first
643 // character is a letter xor the previous character was a letter. 620 // character is a letter xor the previous character was a letter.
644 virtual RegExpNode* PropagateForward(NodeInfo* info) = 0; 621 virtual RegExpNode* PropagateForward(NodeInfo* info) = 0;
645 622
646 NodeInfo* info() { return &info_; } 623 NodeInfo* info() { return &info_; }
647 624
648 void AddSibling(RegExpNode* node) { siblings_.Add(node); } 625 void AddSibling(RegExpNode* node) { siblings_.Add(node); }
649 626
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
713 static ActionNode* BeginSubmatch( 690 static ActionNode* BeginSubmatch(
714 int stack_pointer_reg, 691 int stack_pointer_reg,
715 int position_reg, 692 int position_reg,
716 RegExpNode* on_success); 693 RegExpNode* on_success);
717 static ActionNode* PositiveSubmatchSuccess( 694 static ActionNode* PositiveSubmatchSuccess(
718 int stack_pointer_reg, 695 int stack_pointer_reg,
719 int restore_reg, 696 int restore_reg,
720 RegExpNode* on_success); 697 RegExpNode* on_success);
721 virtual void Accept(NodeVisitor* visitor); 698 virtual void Accept(NodeVisitor* visitor);
722 virtual bool Emit(RegExpCompiler* compiler, GenerationVariant* variant); 699 virtual bool Emit(RegExpCompiler* compiler, GenerationVariant* variant);
723 virtual RegExpNode* ExpandLocal(NodeInfo* info); 700 virtual int EatsAtLeast(int recursion_depth);
724 virtual void ExpandChildren(); 701 virtual void GetQuickCheckDetails(QuickCheckDetails* details,
702 RegExpCompiler* compiler,
703 int filled_in) {
704 return on_success()->GetQuickCheckDetails(details, compiler, filled_in);
705 }
725 virtual RegExpNode* PropagateForward(NodeInfo* info); 706 virtual RegExpNode* PropagateForward(NodeInfo* info);
726 Type type() { return type_; } 707 Type type() { return type_; }
727 // TODO(erikcorry): We should allow some action nodes in greedy loops. 708 // TODO(erikcorry): We should allow some action nodes in greedy loops.
728 virtual int GreedyLoopTextLength() { return kNodeIsTooComplexForGreedyLoops; } 709 virtual int GreedyLoopTextLength() { return kNodeIsTooComplexForGreedyLoops; }
729 virtual ActionNode* Clone() { return new ActionNode(*this); } 710 virtual ActionNode* Clone() { return new ActionNode(*this); }
730 711
731 private: 712 private:
732 union { 713 union {
733 struct { 714 struct {
734 int reg; 715 int reg;
(...skipping 25 matching lines...) Expand all
760 : SeqRegExpNode(on_success), 741 : SeqRegExpNode(on_success),
761 elms_(elms) { } 742 elms_(elms) { }
762 TextNode(RegExpCharacterClass* that, 743 TextNode(RegExpCharacterClass* that,
763 RegExpNode* on_success) 744 RegExpNode* on_success)
764 : SeqRegExpNode(on_success), 745 : SeqRegExpNode(on_success),
765 elms_(new ZoneList<TextElement>(1)) { 746 elms_(new ZoneList<TextElement>(1)) {
766 elms_->Add(TextElement::CharClass(that)); 747 elms_->Add(TextElement::CharClass(that));
767 } 748 }
768 virtual void Accept(NodeVisitor* visitor); 749 virtual void Accept(NodeVisitor* visitor);
769 virtual RegExpNode* PropagateForward(NodeInfo* info); 750 virtual RegExpNode* PropagateForward(NodeInfo* info);
770 virtual RegExpNode* ExpandLocal(NodeInfo* info);
771 virtual void ExpandChildren();
772 virtual bool Emit(RegExpCompiler* compiler, GenerationVariant* variant); 751 virtual bool Emit(RegExpCompiler* compiler, GenerationVariant* variant);
752 virtual int EatsAtLeast(int recursion_depth);
753 virtual void GetQuickCheckDetails(QuickCheckDetails* details,
754 RegExpCompiler* compiler,
755 int characters_filled_in);
773 ZoneList<TextElement>* elements() { return elms_; } 756 ZoneList<TextElement>* elements() { return elms_; }
774 void MakeCaseIndependent(); 757 void MakeCaseIndependent();
775 virtual int GreedyLoopTextLength(); 758 virtual int GreedyLoopTextLength();
776 virtual TextNode* Clone() { 759 virtual TextNode* Clone() {
777 TextNode* result = new TextNode(*this); 760 TextNode* result = new TextNode(*this);
778 result->CalculateOffsets(); 761 result->CalculateOffsets();
779 return result; 762 return result;
780 } 763 }
781 void CalculateOffsets(); 764 void CalculateOffsets();
765
782 private: 766 private:
783 void ExpandAtomChildren(RegExpAtom* that); 767 enum TextEmitPassType {
784 void ExpandCharClassChildren(RegExpCharacterClass* that); 768 NON_ASCII_MATCH,
785 769 CHARACTER_MATCH,
770 CASE_CHARACTER_MATCH,
771 CHARACTER_CLASS_MATCH
772 };
773 void TextEmitPass(RegExpCompiler* compiler,
774 TextEmitPassType pass,
775 bool preloaded,
776 GenerationVariant* variant,
777 bool first_element_checked,
778 int* checked_up_to);
779 int Length();
786 ZoneList<TextElement>* elms_; 780 ZoneList<TextElement>* elms_;
787 }; 781 };
788 782
789 783
790 class BackReferenceNode: public SeqRegExpNode { 784 class BackReferenceNode: public SeqRegExpNode {
791 public: 785 public:
792 BackReferenceNode(int start_reg, 786 BackReferenceNode(int start_reg,
793 int end_reg, 787 int end_reg,
794 RegExpNode* on_success) 788 RegExpNode* on_success)
795 : SeqRegExpNode(on_success), 789 : SeqRegExpNode(on_success),
796 start_reg_(start_reg), 790 start_reg_(start_reg),
797 end_reg_(end_reg) { } 791 end_reg_(end_reg) { }
798 virtual void Accept(NodeVisitor* visitor); 792 virtual void Accept(NodeVisitor* visitor);
799 int start_register() { return start_reg_; } 793 int start_register() { return start_reg_; }
800 int end_register() { return end_reg_; } 794 int end_register() { return end_reg_; }
801 virtual bool Emit(RegExpCompiler* compiler, GenerationVariant* variant); 795 virtual bool Emit(RegExpCompiler* compiler, GenerationVariant* variant);
796 virtual int EatsAtLeast(int recursion_depth) { return 0; }
797 virtual void GetQuickCheckDetails(QuickCheckDetails* details,
798 RegExpCompiler* compiler,
799 int characters_filled_in) {
800 return;
801 }
802 virtual RegExpNode* PropagateForward(NodeInfo* info); 802 virtual RegExpNode* PropagateForward(NodeInfo* info);
803 virtual RegExpNode* ExpandLocal(NodeInfo* info);
804 virtual void ExpandChildren();
805 virtual BackReferenceNode* Clone() { return new BackReferenceNode(*this); } 803 virtual BackReferenceNode* Clone() { return new BackReferenceNode(*this); }
806 804
807 private: 805 private:
808 int start_reg_; 806 int start_reg_;
809 int end_reg_; 807 int end_reg_;
810 }; 808 };
811 809
812 810
813 class EndNode: public RegExpNode { 811 class EndNode: public RegExpNode {
814 public: 812 public:
815 enum Action { ACCEPT, BACKTRACK, NEGATIVE_SUBMATCH_SUCCESS }; 813 enum Action { ACCEPT, BACKTRACK, NEGATIVE_SUBMATCH_SUCCESS };
816 explicit EndNode(Action action) : action_(action) { } 814 explicit EndNode(Action action) : action_(action) { }
817 virtual void Accept(NodeVisitor* visitor); 815 virtual void Accept(NodeVisitor* visitor);
818 virtual bool Emit(RegExpCompiler* compiler, GenerationVariant* variant); 816 virtual bool Emit(RegExpCompiler* compiler, GenerationVariant* variant);
817 virtual int EatsAtLeast(int recursion_depth) { return 0; }
818 virtual void GetQuickCheckDetails(QuickCheckDetails* details,
819 RegExpCompiler* compiler,
820 int characters_filled_in) {
821 // Returning 0 from EatsAtLeast should ensure we never get here.
822 UNREACHABLE();
823 }
819 virtual RegExpNode* PropagateForward(NodeInfo* info); 824 virtual RegExpNode* PropagateForward(NodeInfo* info);
820 virtual RegExpNode* ExpandLocal(NodeInfo* info);
821 virtual void ExpandChildren();
822 virtual EndNode* Clone() { return new EndNode(*this); } 825 virtual EndNode* Clone() { return new EndNode(*this); }
823 826
824 protected: 827 protected:
825 void EmitInfoChecks(RegExpMacroAssembler* macro, GenerationVariant* variant); 828 void EmitInfoChecks(RegExpMacroAssembler* macro, GenerationVariant* variant);
826 829
827 private: 830 private:
828 Action action_; 831 Action action_;
829 }; 832 };
830 833
831 834
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
868 RegExpNode* node() { return node_; } 871 RegExpNode* node() { return node_; }
869 void set_node(RegExpNode* node) { node_ = node; } 872 void set_node(RegExpNode* node) { node_ = node; }
870 ZoneList<Guard*>* guards() { return guards_; } 873 ZoneList<Guard*>* guards() { return guards_; }
871 874
872 private: 875 private:
873 RegExpNode* node_; 876 RegExpNode* node_;
874 ZoneList<Guard*>* guards_; 877 ZoneList<Guard*>* guards_;
875 }; 878 };
876 879
877 880
881 class AlternativeGeneration;
882
883
878 class ChoiceNode: public RegExpNode { 884 class ChoiceNode: public RegExpNode {
879 public: 885 public:
880 explicit ChoiceNode(int expected_size) 886 explicit ChoiceNode(int expected_size)
881 : alternatives_(new ZoneList<GuardedAlternative>(expected_size)), 887 : alternatives_(new ZoneList<GuardedAlternative>(expected_size)),
882 table_(NULL), 888 table_(NULL),
883 being_calculated_(false) { } 889 being_calculated_(false) { }
884 virtual void Accept(NodeVisitor* visitor); 890 virtual void Accept(NodeVisitor* visitor);
885 void AddAlternative(GuardedAlternative node) { alternatives()->Add(node); } 891 void AddAlternative(GuardedAlternative node) { alternatives()->Add(node); }
886 ZoneList<GuardedAlternative>* alternatives() { return alternatives_; } 892 ZoneList<GuardedAlternative>* alternatives() { return alternatives_; }
887 DispatchTable* GetTable(bool ignore_case); 893 DispatchTable* GetTable(bool ignore_case);
888 virtual bool Emit(RegExpCompiler* compiler, GenerationVariant* variant); 894 virtual bool Emit(RegExpCompiler* compiler, GenerationVariant* variant);
895 virtual int EatsAtLeast(int recursion_depth);
896 int EatsAtLeastHelper(int recursion_depth, RegExpNode* ignore_this_node);
897 virtual void GetQuickCheckDetails(QuickCheckDetails* details,
898 RegExpCompiler* compiler,
899 int characters_filled_in);
889 virtual RegExpNode* PropagateForward(NodeInfo* info); 900 virtual RegExpNode* PropagateForward(NodeInfo* info);
890 virtual RegExpNode* ExpandLocal(NodeInfo* info);
891 virtual void ExpandChildren();
892 virtual ChoiceNode* Clone() { return new ChoiceNode(*this); } 901 virtual ChoiceNode* Clone() { return new ChoiceNode(*this); }
893 902
894 bool being_calculated() { return being_calculated_; } 903 bool being_calculated() { return being_calculated_; }
895 void set_being_calculated(bool b) { being_calculated_ = b; } 904 void set_being_calculated(bool b) { being_calculated_ = b; }
896 905
897 protected: 906 protected:
898 int GreedyLoopTextLength(GuardedAlternative *alternative); 907 int GreedyLoopTextLength(GuardedAlternative *alternative);
899 ZoneList<GuardedAlternative>* alternatives_; 908 ZoneList<GuardedAlternative>* alternatives_;
900 909
901 private: 910 private:
902 friend class DispatchTableConstructor; 911 friend class DispatchTableConstructor;
903 friend class AssertionPropagation; 912 friend class Analysis;
904 void GenerateGuard(RegExpMacroAssembler* macro_assembler, 913 void GenerateGuard(RegExpMacroAssembler* macro_assembler,
905 Guard *guard, 914 Guard *guard,
906 GenerationVariant* variant); 915 GenerationVariant* variant);
916 int CalculatePreloadCharacters(RegExpCompiler* compiler);
917 bool EmitOutOfLineContinuation(RegExpCompiler* compiler,
918 GenerationVariant* variant,
919 GuardedAlternative alternative,
920 AlternativeGeneration* alt_gen,
921 int preload_characters,
922 bool next_expects_preload);
907 DispatchTable* table_; 923 DispatchTable* table_;
908 bool being_calculated_; 924 bool being_calculated_;
909 }; 925 };
910 926
911 927
912 class LoopChoiceNode: public ChoiceNode { 928 class LoopChoiceNode: public ChoiceNode {
913 public: 929 public:
914 explicit LoopChoiceNode(int expected_size) : ChoiceNode(expected_size) { } 930 explicit LoopChoiceNode(bool body_can_be_zero_length)
931 : ChoiceNode(2),
932 loop_node_(NULL),
933 continue_node_(NULL),
934 body_can_be_zero_length_(body_can_be_zero_length) { }
935 void AddLoopAlternative(GuardedAlternative alt);
936 void AddContinueAlternative(GuardedAlternative alt);
915 virtual bool Emit(RegExpCompiler* compiler, GenerationVariant* variant); 937 virtual bool Emit(RegExpCompiler* compiler, GenerationVariant* variant);
938 virtual int EatsAtLeast(int recursion_depth); // Returns 0.
939 virtual void GetQuickCheckDetails(QuickCheckDetails* details,
940 RegExpCompiler* compiler,
941 int characters_filled_in);
916 virtual LoopChoiceNode* Clone() { return new LoopChoiceNode(*this); } 942 virtual LoopChoiceNode* Clone() { return new LoopChoiceNode(*this); }
943 RegExpNode* loop_node() { return loop_node_; }
944 RegExpNode* continue_node() { return continue_node_; }
945 bool body_can_be_zero_length() { return body_can_be_zero_length_; }
946 virtual void Accept(NodeVisitor* visitor);
947
948 private:
949 // AddAlternative is made private for loop nodes because alternatives
950 // should not be added freely, we need to keep track of which node
951 // goes back to the node itself.
952 void AddAlternative(GuardedAlternative node) {
953 ChoiceNode::AddAlternative(node);
954 }
955
956 RegExpNode* loop_node_;
957 RegExpNode* continue_node_;
958 bool body_can_be_zero_length_;
917 }; 959 };
918 960
919 961
920 // There are many ways to generate code for a node. This class encapsulates 962 // There are many ways to generate code for a node. This class encapsulates
921 // the current way we should be generating. In other words it encapsulates 963 // the current way we should be generating. In other words it encapsulates
922 // the current state of the code generator. 964 // the current state of the code generator.
923 class GenerationVariant { 965 class GenerationVariant {
924 public: 966 public:
925 class DeferredAction { 967 class DeferredAction {
926 public: 968 public:
(...skipping 29 matching lines...) Expand all
956 private: 998 private:
957 int value_; 999 int value_;
958 }; 1000 };
959 1001
960 class DeferredIncrementRegister: public DeferredAction { 1002 class DeferredIncrementRegister: public DeferredAction {
961 public: 1003 public:
962 explicit DeferredIncrementRegister(int reg) 1004 explicit DeferredIncrementRegister(int reg)
963 : DeferredAction(ActionNode::INCREMENT_REGISTER, reg) { } 1005 : DeferredAction(ActionNode::INCREMENT_REGISTER, reg) { }
964 }; 1006 };
965 1007
966 explicit GenerationVariant(Label* backtrack)
967 : cp_offset_(0),
968 actions_(NULL),
969 backtrack_(backtrack),
970 stop_node_(NULL),
971 loop_label_(NULL) { }
972 GenerationVariant() 1008 GenerationVariant()
973 : cp_offset_(0), 1009 : cp_offset_(0),
974 actions_(NULL), 1010 actions_(NULL),
975 backtrack_(NULL), 1011 backtrack_(NULL),
976 stop_node_(NULL), 1012 stop_node_(NULL),
977 loop_label_(NULL) { } 1013 loop_label_(NULL),
1014 characters_preloaded_(0) { }
978 bool Flush(RegExpCompiler* compiler, RegExpNode* successor); 1015 bool Flush(RegExpCompiler* compiler, RegExpNode* successor);
979 int cp_offset() { return cp_offset_; } 1016 int cp_offset() { return cp_offset_; }
980 DeferredAction* actions() { return actions_; } 1017 DeferredAction* actions() { return actions_; }
981 bool is_trivial() { 1018 bool is_trivial() {
982 return backtrack_ == NULL && actions_ == NULL && cp_offset_ == 0; 1019 return backtrack_ == NULL &&
1020 actions_ == NULL &&
1021 cp_offset_ == 0 &&
1022 characters_preloaded_ == 0 &&
1023 quick_check_performed_.characters() == 0;
983 } 1024 }
984 Label* backtrack() { return backtrack_; } 1025 Label* backtrack() { return backtrack_; }
985 Label* loop_label() { return loop_label_; } 1026 Label* loop_label() { return loop_label_; }
986 RegExpNode* stop_node() { return stop_node_; } 1027 RegExpNode* stop_node() { return stop_node_; }
987 // These set methods should be used only on new GenerationVariants - the 1028 int characters_preloaded() { return characters_preloaded_; }
988 // intention is that GenerationVariants are immutable after creation. 1029 QuickCheckDetails* quick_check_performed() { return &quick_check_performed_; }
1030 bool mentions_reg(int reg);
1031 // These set methods and AdvanceVariant should be used only on new
1032 // GenerationVariants - the intention is that GenerationVariants are
1033 // immutable after creation.
989 void add_action(DeferredAction* new_action) { 1034 void add_action(DeferredAction* new_action) {
990 ASSERT(new_action->next_ == NULL); 1035 ASSERT(new_action->next_ == NULL);
991 new_action->next_ = actions_; 1036 new_action->next_ = actions_;
992 actions_ = new_action; 1037 actions_ = new_action;
993 } 1038 }
994 void set_cp_offset(int new_cp_offset) {
995 ASSERT(new_cp_offset >= cp_offset_);
996 cp_offset_ = new_cp_offset;
997 }
998 void set_backtrack(Label* backtrack) { backtrack_ = backtrack; } 1039 void set_backtrack(Label* backtrack) { backtrack_ = backtrack; }
999 void set_stop_node(RegExpNode* node) { stop_node_ = node; } 1040 void set_stop_node(RegExpNode* node) { stop_node_ = node; }
1000 void set_loop_label(Label* label) { loop_label_ = label; } 1041 void set_loop_label(Label* label) { loop_label_ = label; }
1001 bool mentions_reg(int reg); 1042 void set_characters_preloaded(int cpre) { characters_preloaded_ = cpre; }
1043 void set_quick_check_performed(QuickCheckDetails* d) {
1044 quick_check_performed_ = *d;
1045 }
1046 void clear_quick_check_performed() {
1047 }
1048 void AdvanceVariant(int by, bool ascii);
1002 private: 1049 private:
1003 int FindAffectedRegisters(OutSet* affected_registers); 1050 int FindAffectedRegisters(OutSet* affected_registers);
1004 void PerformDeferredActions(RegExpMacroAssembler* macro, 1051 void PerformDeferredActions(RegExpMacroAssembler* macro,
1005 int max_register, 1052 int max_register,
1006 OutSet& affected_registers); 1053 OutSet& affected_registers);
1007 void RestoreAffectedRegisters(RegExpMacroAssembler* macro, 1054 void RestoreAffectedRegisters(RegExpMacroAssembler* macro,
1008 int max_register, 1055 int max_register,
1009 OutSet& affected_registers); 1056 OutSet& affected_registers);
1010 void PushAffectedRegisters(RegExpMacroAssembler* macro, 1057 void PushAffectedRegisters(RegExpMacroAssembler* macro,
1011 int max_register, 1058 int max_register,
1012 OutSet& affected_registers); 1059 OutSet& affected_registers);
1013 int cp_offset_; 1060 int cp_offset_;
1014 DeferredAction* actions_; 1061 DeferredAction* actions_;
1015 Label* backtrack_; 1062 Label* backtrack_;
1016 RegExpNode* stop_node_; 1063 RegExpNode* stop_node_;
1017 Label* loop_label_; 1064 Label* loop_label_;
1065 int characters_preloaded_;
1066 QuickCheckDetails quick_check_performed_;
1018 }; 1067 };
1068
1069
1019 class NodeVisitor { 1070 class NodeVisitor {
1020 public: 1071 public:
1021 virtual ~NodeVisitor() { } 1072 virtual ~NodeVisitor() { }
1022 #define DECLARE_VISIT(Type) \ 1073 #define DECLARE_VISIT(Type) \
1023 virtual void Visit##Type(Type##Node* that) = 0; 1074 virtual void Visit##Type(Type##Node* that) = 0;
1024 FOR_EACH_NODE_TYPE(DECLARE_VISIT) 1075 FOR_EACH_NODE_TYPE(DECLARE_VISIT)
1025 #undef DECLARE_VISIT 1076 #undef DECLARE_VISIT
1077 virtual void VisitLoopChoice(LoopChoiceNode* that) { VisitChoice(that); }
1026 }; 1078 };
1027 1079
1028 1080
1029 // Node visitor used to add the start set of the alternatives to the 1081 // Node visitor used to add the start set of the alternatives to the
1030 // dispatch table of a choice node. 1082 // dispatch table of a choice node.
1031 class DispatchTableConstructor: public NodeVisitor { 1083 class DispatchTableConstructor: public NodeVisitor {
1032 public: 1084 public:
1033 DispatchTableConstructor(DispatchTable* table, bool ignore_case) 1085 DispatchTableConstructor(DispatchTable* table, bool ignore_case)
1034 : table_(table), 1086 : table_(table),
1035 choice_index_(-1), 1087 choice_index_(-1),
(...skipping 27 matching lines...) Expand all
1063 // be propagated to the first '.' that whatever follows needs to know 1115 // be propagated to the first '.' that whatever follows needs to know
1064 // if it matched a word or a non-word, and to the second '.' that it 1116 // if it matched a word or a non-word, and to the second '.' that it
1065 // has to check if it succeeds a word or non-word. In this case the 1117 // has to check if it succeeds a word or non-word. In this case the
1066 // result will be something like: 1118 // result will be something like:
1067 // 1119 //
1068 // +-------+ +------------+ 1120 // +-------+ +------------+
1069 // | . | | . | 1121 // | . | | . |
1070 // +-------+ ---> +------------+ 1122 // +-------+ ---> +------------+
1071 // | word? | | check word | 1123 // | word? | | check word |
1072 // +-------+ +------------+ 1124 // +-------+ +------------+
1073 // 1125 class Analysis: public NodeVisitor {
1074 // At a later phase all nodes that determine information for their
1075 // following nodes are split into several 'sibling' nodes. In this
1076 // case the first '.' is split into one node that only matches words
1077 // and one that only matches non-words. The second '.' is also split,
1078 // into one node that assumes that the previous character was a word
1079 // character and one that assumes that is was non-word. In this case
1080 // the result is
1081 //
1082 // +------------------+ +------------------+
1083 // /--> | intersect(., \w) | ---> | intersect(., \W) |
1084 // | +------------------+ +------------------+
1085 // | | follows \w |
1086 // | +------------------+
1087 // --?
1088 // | +------------------+ +------------------+
1089 // \--> | intersect(., \W) | ---> | intersect(., \w) |
1090 // +------------------+ +------------------+
1091 // | follows \W |
1092 // +------------------+
1093 //
1094 // This way we don't need to explicitly check the previous character
1095 // but can always assume that whoever consumed the previous character
1096 // has propagated the relevant information forward.
1097 class AssertionPropagation: public NodeVisitor {
1098 public: 1126 public:
1099 explicit AssertionPropagation(bool ignore_case) 1127 explicit Analysis(bool ignore_case)
1100 : ignore_case_(ignore_case) { } 1128 : ignore_case_(ignore_case) { }
1101 void EnsureAnalyzed(RegExpNode* node); 1129 void EnsureAnalyzed(RegExpNode* node);
1102 1130
1103 #define DECLARE_VISIT(Type) \ 1131 #define DECLARE_VISIT(Type) \
1104 virtual void Visit##Type(Type##Node* that); 1132 virtual void Visit##Type(Type##Node* that);
1105 FOR_EACH_NODE_TYPE(DECLARE_VISIT) 1133 FOR_EACH_NODE_TYPE(DECLARE_VISIT)
1106 #undef DECLARE_VISIT 1134 #undef DECLARE_VISIT
1135 virtual void VisitLoopChoice(LoopChoiceNode* that);
1107 1136
1108 private: 1137 private:
1109 bool ignore_case_; 1138 bool ignore_case_;
1110 1139
1111 DISALLOW_IMPLICIT_CONSTRUCTORS(AssertionPropagation); 1140 DISALLOW_IMPLICIT_CONSTRUCTORS(Analysis);
1112 }; 1141 };
1113 1142
1114 1143
1115 struct RegExpCompileData { 1144 struct RegExpCompileData {
1116 RegExpCompileData() 1145 RegExpCompileData()
1117 : tree(NULL), 1146 : tree(NULL),
1118 node(NULL), 1147 node(NULL),
1119 has_lookbehind(false),
1120 simple(true), 1148 simple(true),
1121 capture_count(0) { } 1149 capture_count(0) { }
1122 RegExpTree* tree; 1150 RegExpTree* tree;
1123 RegExpNode* node; 1151 RegExpNode* node;
1124 bool has_lookbehind;
1125 bool simple; 1152 bool simple;
1126 Handle<String> error; 1153 Handle<String> error;
1127 int capture_count; 1154 int capture_count;
1128 }; 1155 };
1129 1156
1130 1157
1131 class RegExpEngine: public AllStatic { 1158 class RegExpEngine: public AllStatic {
1132 public: 1159 public:
1133 static Handle<FixedArray> Compile(RegExpCompileData* input, 1160 static Handle<FixedArray> Compile(RegExpCompileData* input,
1134 bool ignore_case, 1161 bool ignore_case,
1135 bool multiline, 1162 bool multiline,
1136 Handle<String> pattern, 1163 Handle<String> pattern,
1137 bool is_ascii); 1164 bool is_ascii);
1138 1165
1139 static void DotPrint(const char* label, RegExpNode* node, bool ignore_case); 1166 static void DotPrint(const char* label, RegExpNode* node, bool ignore_case);
1140 }; 1167 };
1141 1168
1142 1169
1143 } } // namespace v8::internal 1170 } } // namespace v8::internal
1144 1171
1145 #endif // V8_JSREGEXP_H_ 1172 #endif // V8_JSREGEXP_H_
OLDNEW
« no previous file with comments | « src/interpreter-irregexp.cc ('k') | src/jsregexp.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698