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

Side by Side Diff: runtime/vm/regexp.cc

Issue 982873004: Thread/Isolate refactoring: new(Isolate) -> new(Zone) (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 5 years, 9 months 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
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/regexp.h" 5 #include "vm/regexp.h"
6 6
7 #include "vm/dart_entry.h" 7 #include "vm/dart_entry.h"
8 #include "vm/regexp_assembler.h" 8 #include "vm/regexp_assembler.h"
9 #include "vm/regexp_ast.h" 9 #include "vm/regexp_ast.h"
10 #include "vm/unibrow-inl.h" 10 #include "vm/unibrow-inl.h"
11 #include "vm/unicode.h" 11 #include "vm/unicode.h"
12 #include "vm/symbols.h" 12 #include "vm/symbols.h"
13 #include "vm/thread.h"
13 14
14 #define I (isolate()) 15 #define Z (zone())
15 #define CI (compiler->isolate()) 16 #define CZ (compiler->zone())
Ivan Posva 2015/03/13 21:56:50 I know this is not your code, but please investiga
koda 2015/03/14 00:46:37 Within this file, Z and CZ always refer to the sam
16 17
17 namespace dart { 18 namespace dart {
18 19
19 DECLARE_FLAG(bool, trace_irregexp); 20 DECLARE_FLAG(bool, trace_irregexp);
20 21
21 // Default to generating optimized regexp code. 22 // Default to generating optimized regexp code.
22 static const bool kRegexpOptimization = true; 23 static const bool kRegexpOptimization = true;
23 24
24 // More makes code generation slower, less makes V8 benchmark score lower. 25 // More makes code generation slower, less makes V8 benchmark score lower.
25 static const intptr_t kMaxLookaheadForBoyerMoore = 8; 26 static const intptr_t kMaxLookaheadForBoyerMoore = 8;
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after
327 specialization_cid_ == kExternalOneByteStringCid); 328 specialization_cid_ == kExternalOneByteStringCid);
328 } 329 }
329 inline intptr_t specialization_cid() { return specialization_cid_; } 330 inline intptr_t specialization_cid() { return specialization_cid_; }
330 FrequencyCollator* frequency_collator() { return &frequency_collator_; } 331 FrequencyCollator* frequency_collator() { return &frequency_collator_; }
331 332
332 intptr_t current_expansion_factor() { return current_expansion_factor_; } 333 intptr_t current_expansion_factor() { return current_expansion_factor_; }
333 void set_current_expansion_factor(intptr_t value) { 334 void set_current_expansion_factor(intptr_t value) {
334 current_expansion_factor_ = value; 335 current_expansion_factor_ = value;
335 } 336 }
336 337
337 Isolate* isolate() const { return isolate_; } 338 Zone* zone() const { return zone_; }
338 339
339 static const intptr_t kNoRegister = -1; 340 static const intptr_t kNoRegister = -1;
340 341
341 private: 342 private:
342 EndNode* accept_; 343 EndNode* accept_;
343 intptr_t next_register_; 344 intptr_t next_register_;
344 ZoneGrowableArray<RegExpNode*>* work_list_; 345 ZoneGrowableArray<RegExpNode*>* work_list_;
345 intptr_t recursion_depth_; 346 intptr_t recursion_depth_;
346 IRRegExpMacroAssembler* macro_assembler_; 347 IRRegExpMacroAssembler* macro_assembler_;
347 bool ignore_case_; 348 bool ignore_case_;
348 intptr_t specialization_cid_; 349 intptr_t specialization_cid_;
349 bool reg_exp_too_big_; 350 bool reg_exp_too_big_;
350 intptr_t current_expansion_factor_; 351 intptr_t current_expansion_factor_;
351 FrequencyCollator frequency_collator_; 352 FrequencyCollator frequency_collator_;
352 Isolate* isolate_; 353 Zone* zone_;
353 }; 354 };
354 355
355 356
356 class RecursionCheck : public ValueObject { 357 class RecursionCheck : public ValueObject {
357 public: 358 public:
358 explicit RecursionCheck(RegExpCompiler* compiler) : compiler_(compiler) { 359 explicit RecursionCheck(RegExpCompiler* compiler) : compiler_(compiler) {
359 compiler->IncrementRecursionDepth(); 360 compiler->IncrementRecursionDepth();
360 } 361 }
361 ~RecursionCheck() { compiler_->DecrementRecursionDepth(); } 362 ~RecursionCheck() { compiler_->DecrementRecursionDepth(); }
362 private: 363 private:
(...skipping 10 matching lines...) Expand all
373 // a fixed array or a null handle depending on whether it succeeded. 374 // a fixed array or a null handle depending on whether it succeeded.
374 RegExpCompiler::RegExpCompiler(intptr_t capture_count, bool ignore_case, 375 RegExpCompiler::RegExpCompiler(intptr_t capture_count, bool ignore_case,
375 intptr_t specialization_cid) 376 intptr_t specialization_cid)
376 : next_register_(2 * (capture_count + 1)), 377 : next_register_(2 * (capture_count + 1)),
377 work_list_(NULL), 378 work_list_(NULL),
378 recursion_depth_(0), 379 recursion_depth_(0),
379 ignore_case_(ignore_case), 380 ignore_case_(ignore_case),
380 specialization_cid_(specialization_cid), 381 specialization_cid_(specialization_cid),
381 reg_exp_too_big_(false), 382 reg_exp_too_big_(false),
382 current_expansion_factor_(1), 383 current_expansion_factor_(1),
383 isolate_(Isolate::Current()) { 384 zone_(Thread::Current()->zone()) {
384 accept_ = new(I) EndNode(EndNode::ACCEPT, I); 385 accept_ = new(Z) EndNode(EndNode::ACCEPT, Z);
385 } 386 }
386 387
387 388
388 RegExpEngine::CompilationResult RegExpCompiler::Assemble( 389 RegExpEngine::CompilationResult RegExpCompiler::Assemble(
389 IRRegExpMacroAssembler* macro_assembler, 390 IRRegExpMacroAssembler* macro_assembler,
390 RegExpNode* start, 391 RegExpNode* start,
391 intptr_t capture_count, 392 intptr_t capture_count,
392 const String& pattern) { 393 const String& pattern) {
393 static const bool use_slow_safe_regexp_compiler = false; 394 static const bool use_slow_safe_regexp_compiler = false;
394 395
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
454 } 455 }
455 } 456 }
456 return false; 457 return false;
457 } 458 }
458 459
459 460
460 // This is called as we come into a loop choice node and some other tricky 461 // This is called as we come into a loop choice node and some other tricky
461 // nodes. It normalizes the state of the code generator to ensure we can 462 // nodes. It normalizes the state of the code generator to ensure we can
462 // generate generic code. 463 // generate generic code.
463 intptr_t Trace::FindAffectedRegisters(OutSet* affected_registers, 464 intptr_t Trace::FindAffectedRegisters(OutSet* affected_registers,
464 Isolate* isolate) { 465 Zone* zone) {
465 intptr_t max_register = RegExpCompiler::kNoRegister; 466 intptr_t max_register = RegExpCompiler::kNoRegister;
466 for (DeferredAction* action = actions_; 467 for (DeferredAction* action = actions_;
467 action != NULL; 468 action != NULL;
468 action = action->next()) { 469 action = action->next()) {
469 if (action->action_type() == ActionNode::CLEAR_CAPTURES) { 470 if (action->action_type() == ActionNode::CLEAR_CAPTURES) {
470 Interval range = static_cast<DeferredClearCaptures*>(action)->range(); 471 Interval range = static_cast<DeferredClearCaptures*>(action)->range();
471 for (intptr_t i = range.from(); i <= range.to(); i++) 472 for (intptr_t i = range.from(); i <= range.to(); i++)
472 affected_registers->Set(i, isolate); 473 affected_registers->Set(i, zone);
473 if (range.to() > max_register) max_register = range.to(); 474 if (range.to() > max_register) max_register = range.to();
474 } else { 475 } else {
475 affected_registers->Set(action->reg(), isolate); 476 affected_registers->Set(action->reg(), zone);
476 if (action->reg() > max_register) max_register = action->reg(); 477 if (action->reg() > max_register) max_register = action->reg();
477 } 478 }
478 } 479 }
479 return max_register; 480 return max_register;
480 } 481 }
481 482
482 483
483 void Trace::RestoreAffectedRegisters(RegExpMacroAssembler* assembler, 484 void Trace::RestoreAffectedRegisters(RegExpMacroAssembler* assembler,
484 intptr_t max_register, 485 intptr_t max_register,
485 const OutSet& registers_to_pop, 486 const OutSet& registers_to_pop,
(...skipping 10 matching lines...) Expand all
496 } 497 }
497 } 498 }
498 } 499 }
499 500
500 501
501 void Trace::PerformDeferredActions(RegExpMacroAssembler* assembler, 502 void Trace::PerformDeferredActions(RegExpMacroAssembler* assembler,
502 intptr_t max_register, 503 intptr_t max_register,
503 const OutSet& affected_registers, 504 const OutSet& affected_registers,
504 OutSet* registers_to_pop, 505 OutSet* registers_to_pop,
505 OutSet* registers_to_clear, 506 OutSet* registers_to_clear,
506 Isolate* isolate) { 507 Zone* zone) {
507 for (intptr_t reg = 0; reg <= max_register; reg++) { 508 for (intptr_t reg = 0; reg <= max_register; reg++) {
508 if (!affected_registers.Get(reg)) { 509 if (!affected_registers.Get(reg)) {
509 continue; 510 continue;
510 } 511 }
511 512
512 // The chronologically first deferred action in the trace 513 // The chronologically first deferred action in the trace
513 // is used to infer the action needed to restore a register 514 // is used to infer the action needed to restore a register
514 // to its previous state (or not, if it's safe to ignore it). 515 // to its previous state (or not, if it's safe to ignore it).
515 enum DeferredActionUndoType { ACTION_IGNORE, ACTION_RESTORE, ACTION_CLEAR }; 516 enum DeferredActionUndoType { ACTION_IGNORE, ACTION_RESTORE, ACTION_CLEAR };
516 DeferredActionUndoType undo_action = ACTION_IGNORE; 517 DeferredActionUndoType undo_action = ACTION_IGNORE;
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
588 } 589 }
589 default: 590 default:
590 UNREACHABLE(); 591 UNREACHABLE();
591 break; 592 break;
592 } 593 }
593 } 594 }
594 } 595 }
595 // Prepare for the undo-action (e.g., push if it's going to be popped). 596 // Prepare for the undo-action (e.g., push if it's going to be popped).
596 if (undo_action == ACTION_RESTORE) { 597 if (undo_action == ACTION_RESTORE) {
597 assembler->PushRegister(reg); 598 assembler->PushRegister(reg);
598 registers_to_pop->Set(reg, isolate); 599 registers_to_pop->Set(reg, zone);
599 } else if (undo_action == ACTION_CLEAR) { 600 } else if (undo_action == ACTION_CLEAR) {
600 registers_to_clear->Set(reg, isolate); 601 registers_to_clear->Set(reg, zone);
601 } 602 }
602 // Perform the chronologically last action (or accumulated increment) 603 // Perform the chronologically last action (or accumulated increment)
603 // for the register. 604 // for the register.
604 if (store_position != -1) { 605 if (store_position != -1) {
605 assembler->WriteCurrentPositionToRegister(reg, store_position); 606 assembler->WriteCurrentPositionToRegister(reg, store_position);
606 } else if (clear) { 607 } else if (clear) {
607 assembler->ClearRegisters(reg, reg); 608 assembler->ClearRegisters(reg, reg);
608 } else if (absolute) { 609 } else if (absolute) {
609 assembler->SetRegister(reg, value); 610 assembler->SetRegister(reg, value);
610 } else if (value != 0) { 611 } else if (value != 0) {
(...skipping 25 matching lines...) Expand all
636 // Generate deferred actions here along with code to undo them again. 637 // Generate deferred actions here along with code to undo them again.
637 OutSet affected_registers; 638 OutSet affected_registers;
638 639
639 if (backtrack() != NULL) { 640 if (backtrack() != NULL) {
640 // Here we have a concrete backtrack location. These are set up by choice 641 // Here we have a concrete backtrack location. These are set up by choice
641 // nodes and so they indicate that we have a deferred save of the current 642 // nodes and so they indicate that we have a deferred save of the current
642 // position which we may need to emit here. 643 // position which we may need to emit here.
643 assembler->PushCurrentPosition(); 644 assembler->PushCurrentPosition();
644 } 645 }
645 646
646 intptr_t max_register = FindAffectedRegisters(&affected_registers, CI); 647 intptr_t max_register = FindAffectedRegisters(&affected_registers, CZ);
647 OutSet registers_to_pop; 648 OutSet registers_to_pop;
648 OutSet registers_to_clear; 649 OutSet registers_to_clear;
649 PerformDeferredActions(assembler, 650 PerformDeferredActions(assembler,
650 max_register, 651 max_register,
651 affected_registers, 652 affected_registers,
652 &registers_to_pop, 653 &registers_to_pop,
653 &registers_to_clear, 654 &registers_to_clear,
654 CI); 655 CZ);
655 if (cp_offset_ != 0) { 656 if (cp_offset_ != 0) {
656 assembler->AdvanceCurrentPosition(cp_offset_); 657 assembler->AdvanceCurrentPosition(cp_offset_);
657 } 658 }
658 659
659 // Create a new trivial state and generate the node with that. 660 // Create a new trivial state and generate the node with that.
660 BlockLabel undo; 661 BlockLabel undo;
661 assembler->PushBacktrack(&undo); 662 assembler->PushBacktrack(&undo);
662 Trace new_state; 663 Trace new_state;
663 successor->Emit(compiler, &new_state); 664 successor->Emit(compiler, &new_state);
664 665
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
721 assembler->GoTo(trace->backtrack()); 722 assembler->GoTo(trace->backtrack());
722 return; 723 return;
723 case NEGATIVE_SUBMATCH_SUCCESS: 724 case NEGATIVE_SUBMATCH_SUCCESS:
724 // This case is handled in a different virtual method. 725 // This case is handled in a different virtual method.
725 UNREACHABLE(); 726 UNREACHABLE();
726 } 727 }
727 UNIMPLEMENTED(); 728 UNIMPLEMENTED();
728 } 729 }
729 730
730 731
731 void GuardedAlternative::AddGuard(Guard* guard, Isolate* isolate) { 732 void GuardedAlternative::AddGuard(Guard* guard, Zone* zone) {
732 if (guards_ == NULL) 733 if (guards_ == NULL)
733 guards_ = new(isolate) ZoneGrowableArray<Guard*>(1); 734 guards_ = new(zone) ZoneGrowableArray<Guard*>(1);
734 guards_->Add(guard); 735 guards_->Add(guard);
735 } 736 }
736 737
737 738
738 ActionNode* ActionNode::SetRegister(intptr_t reg, 739 ActionNode* ActionNode::SetRegister(intptr_t reg,
739 intptr_t val, 740 intptr_t val,
740 RegExpNode* on_success) { 741 RegExpNode* on_success) {
741 ActionNode* result = 742 ActionNode* result =
742 new(on_success->isolate()) ActionNode(SET_REGISTER, on_success); 743 new(on_success->zone()) ActionNode(SET_REGISTER, on_success);
743 result->data_.u_store_register.reg = reg; 744 result->data_.u_store_register.reg = reg;
744 result->data_.u_store_register.value = val; 745 result->data_.u_store_register.value = val;
745 return result; 746 return result;
746 } 747 }
747 748
748 749
749 ActionNode* ActionNode::IncrementRegister(intptr_t reg, 750 ActionNode* ActionNode::IncrementRegister(intptr_t reg,
750 RegExpNode* on_success) { 751 RegExpNode* on_success) {
751 ActionNode* result = 752 ActionNode* result =
752 new(on_success->isolate()) ActionNode(INCREMENT_REGISTER, on_success); 753 new(on_success->zone()) ActionNode(INCREMENT_REGISTER, on_success);
753 result->data_.u_increment_register.reg = reg; 754 result->data_.u_increment_register.reg = reg;
754 return result; 755 return result;
755 } 756 }
756 757
757 758
758 ActionNode* ActionNode::StorePosition(intptr_t reg, 759 ActionNode* ActionNode::StorePosition(intptr_t reg,
759 bool is_capture, 760 bool is_capture,
760 RegExpNode* on_success) { 761 RegExpNode* on_success) {
761 ActionNode* result = 762 ActionNode* result =
762 new(on_success->isolate()) ActionNode(STORE_POSITION, on_success); 763 new(on_success->zone()) ActionNode(STORE_POSITION, on_success);
763 result->data_.u_position_register.reg = reg; 764 result->data_.u_position_register.reg = reg;
764 result->data_.u_position_register.is_capture = is_capture; 765 result->data_.u_position_register.is_capture = is_capture;
765 return result; 766 return result;
766 } 767 }
767 768
768 769
769 ActionNode* ActionNode::ClearCaptures(Interval range, 770 ActionNode* ActionNode::ClearCaptures(Interval range,
770 RegExpNode* on_success) { 771 RegExpNode* on_success) {
771 ActionNode* result = 772 ActionNode* result =
772 new(on_success->isolate()) ActionNode(CLEAR_CAPTURES, on_success); 773 new(on_success->zone()) ActionNode(CLEAR_CAPTURES, on_success);
773 result->data_.u_clear_captures.range_from = range.from(); 774 result->data_.u_clear_captures.range_from = range.from();
774 result->data_.u_clear_captures.range_to = range.to(); 775 result->data_.u_clear_captures.range_to = range.to();
775 return result; 776 return result;
776 } 777 }
777 778
778 779
779 ActionNode* ActionNode::BeginSubmatch(intptr_t stack_reg, 780 ActionNode* ActionNode::BeginSubmatch(intptr_t stack_reg,
780 intptr_t position_reg, 781 intptr_t position_reg,
781 RegExpNode* on_success) { 782 RegExpNode* on_success) {
782 ActionNode* result = 783 ActionNode* result =
783 new(on_success->isolate()) ActionNode(BEGIN_SUBMATCH, on_success); 784 new(on_success->zone()) ActionNode(BEGIN_SUBMATCH, on_success);
784 result->data_.u_submatch.stack_pointer_register = stack_reg; 785 result->data_.u_submatch.stack_pointer_register = stack_reg;
785 result->data_.u_submatch.current_position_register = position_reg; 786 result->data_.u_submatch.current_position_register = position_reg;
786 return result; 787 return result;
787 } 788 }
788 789
789 790
790 ActionNode* ActionNode::PositiveSubmatchSuccess(intptr_t stack_reg, 791 ActionNode* ActionNode::PositiveSubmatchSuccess(intptr_t stack_reg,
791 intptr_t position_reg, 792 intptr_t position_reg,
792 intptr_t clear_register_count, 793 intptr_t clear_register_count,
793 intptr_t clear_register_from, 794 intptr_t clear_register_from,
794 RegExpNode* on_success) { 795 RegExpNode* on_success) {
795 ActionNode* result = 796 ActionNode* result =
796 new(on_success->isolate()) ActionNode(POSITIVE_SUBMATCH_SUCCESS, 797 new(on_success->zone()) ActionNode(POSITIVE_SUBMATCH_SUCCESS,
797 on_success); 798 on_success);
798 result->data_.u_submatch.stack_pointer_register = stack_reg; 799 result->data_.u_submatch.stack_pointer_register = stack_reg;
799 result->data_.u_submatch.current_position_register = position_reg; 800 result->data_.u_submatch.current_position_register = position_reg;
800 result->data_.u_submatch.clear_register_count = clear_register_count; 801 result->data_.u_submatch.clear_register_count = clear_register_count;
801 result->data_.u_submatch.clear_register_from = clear_register_from; 802 result->data_.u_submatch.clear_register_from = clear_register_from;
802 return result; 803 return result;
803 } 804 }
804 805
805 806
806 ActionNode* ActionNode::EmptyMatchCheck(intptr_t start_register, 807 ActionNode* ActionNode::EmptyMatchCheck(intptr_t start_register,
807 intptr_t repetition_register, 808 intptr_t repetition_register,
808 intptr_t repetition_limit, 809 intptr_t repetition_limit,
809 RegExpNode* on_success) { 810 RegExpNode* on_success) {
810 ActionNode* result = 811 ActionNode* result =
811 new(on_success->isolate()) ActionNode(EMPTY_MATCH_CHECK, on_success); 812 new(on_success->zone()) ActionNode(EMPTY_MATCH_CHECK, on_success);
812 result->data_.u_empty_match_check.start_register = start_register; 813 result->data_.u_empty_match_check.start_register = start_register;
813 result->data_.u_empty_match_check.repetition_register = repetition_register; 814 result->data_.u_empty_match_check.repetition_register = repetition_register;
814 result->data_.u_empty_match_check.repetition_limit = repetition_limit; 815 result->data_.u_empty_match_check.repetition_limit = repetition_limit;
815 return result; 816 return result;
816 } 817 }
817 818
818 819
819 #define DEFINE_ACCEPT(Type) \ 820 #define DEFINE_ACCEPT(Type) \
820 void Type##Node::Accept(NodeVisitor* visitor) { \ 821 void Type##Node::Accept(NodeVisitor* visitor) { \
821 visitor->Visit##Type(this); \ 822 visitor->Visit##Type(this); \
(...skipping 25 matching lines...) Expand all
847 ASSERT(!trace->mentions_reg(guard->reg())); 848 ASSERT(!trace->mentions_reg(guard->reg()));
848 macro_assembler->IfRegisterLT(guard->reg(), 849 macro_assembler->IfRegisterLT(guard->reg(),
849 guard->value(), 850 guard->value(),
850 trace->backtrack()); 851 trace->backtrack());
851 break; 852 break;
852 } 853 }
853 } 854 }
854 855
855 856
856 // Returns the number of characters in the equivalence class, omitting those 857 // Returns the number of characters in the equivalence class, omitting those
857 // that cannot occur in the source string because it is ASCII. 858 // that cannot occur in the source string because it is ASCZI.
858 static intptr_t GetCaseIndependentLetters(uint16_t character, 859 static intptr_t GetCaseIndependentLetters(uint16_t character,
859 bool one_byte_subject, 860 bool one_byte_subject,
860 int32_t* letters) { 861 int32_t* letters) {
861 unibrow::Mapping<unibrow::Ecma262UnCanonicalize> jsregexp_uncanonicalize; 862 unibrow::Mapping<unibrow::Ecma262UnCanonicalize> jsregexp_uncanonicalize;
862 intptr_t length = jsregexp_uncanonicalize.get(character, '\0', letters); 863 intptr_t length = jsregexp_uncanonicalize.get(character, '\0', letters);
863 // Unibrow returns 0 or 1 for characters where case independence is 864 // Unibrow returns 0 or 1 for characters where case independence is
864 // trivial. 865 // trivial.
865 if (length == 0) { 866 if (length == 0) {
866 letters[0] = character; 867 letters[0] = character;
867 length = 1; 868 length = 1;
868 } 869 }
869 if (!one_byte_subject || character <= Symbols::kMaxOneCharCodeSymbol) { 870 if (!one_byte_subject || character <= Symbols::kMaxOneCharCodeSymbol) {
870 return length; 871 return length;
871 } 872 }
872 873
873 // The standard requires that non-ASCII characters cannot have ASCII 874 // The standard requires that non-ASCZI characters cannot have ASCZI
874 // character codes in their equivalence class. 875 // character codes in their equivalence class.
875 // TODO(dcarney): issue 3550 this is not actually true for Latin1 anymore, 876 // TODO(dcarney): issue 3550 this is not actually true for Latin1 anymore,
876 // is it? For example, \u00C5 is equivalent to \u212B. 877 // is it? For example, \u00C5 is equivalent to \u212B.
877 return 0; 878 return 0;
878 } 879 }
879 880
880 881
881 static inline bool EmitSimpleCharacter(Isolate* isolate, 882 static inline bool EmitSimpleCharacter(Zone* zone,
882 RegExpCompiler* compiler, 883 RegExpCompiler* compiler,
883 uint16_t c, 884 uint16_t c,
884 BlockLabel* on_failure, 885 BlockLabel* on_failure,
885 intptr_t cp_offset, 886 intptr_t cp_offset,
886 bool check, 887 bool check,
887 bool preloaded) { 888 bool preloaded) {
888 RegExpMacroAssembler* assembler = compiler->macro_assembler(); 889 RegExpMacroAssembler* assembler = compiler->macro_assembler();
889 bool bound_checked = false; 890 bool bound_checked = false;
890 if (!preloaded) { 891 if (!preloaded) {
891 assembler->LoadCurrentCharacter( 892 assembler->LoadCurrentCharacter(
892 cp_offset, 893 cp_offset,
893 on_failure, 894 on_failure,
894 check); 895 check);
895 bound_checked = true; 896 bound_checked = true;
896 } 897 }
897 assembler->CheckNotCharacter(c, on_failure); 898 assembler->CheckNotCharacter(c, on_failure);
898 return bound_checked; 899 return bound_checked;
899 } 900 }
900 901
901 902
902 // Only emits non-letters (things that don't have case). Only used for case 903 // Only emits non-letters (things that don't have case). Only used for case
903 // independent matches. 904 // independent matches.
904 static inline bool EmitAtomNonLetter(Isolate* isolate, 905 static inline bool EmitAtomNonLetter(Zone* zone,
905 RegExpCompiler* compiler, 906 RegExpCompiler* compiler,
906 uint16_t c, 907 uint16_t c,
907 BlockLabel* on_failure, 908 BlockLabel* on_failure,
908 intptr_t cp_offset, 909 intptr_t cp_offset,
909 bool check, 910 bool check,
910 bool preloaded) { 911 bool preloaded) {
911 RegExpMacroAssembler* macro_assembler = compiler->macro_assembler(); 912 RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
912 bool one_byte = compiler->one_byte(); 913 bool one_byte = compiler->one_byte();
913 int32_t chars[unibrow::Ecma262UnCanonicalize::kMaxWidth]; 914 int32_t chars[unibrow::Ecma262UnCanonicalize::kMaxWidth];
914 intptr_t length = GetCaseIndependentLetters(c, one_byte, chars); 915 intptr_t length = GetCaseIndependentLetters(c, one_byte, chars);
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
967 macro_assembler->CheckNotCharacterAfterMinusAnd(c1 - diff, 968 macro_assembler->CheckNotCharacterAfterMinusAnd(c1 - diff,
968 diff, 969 diff,
969 mask, 970 mask,
970 on_failure); 971 on_failure);
971 return true; 972 return true;
972 } 973 }
973 return false; 974 return false;
974 } 975 }
975 976
976 977
977 typedef bool EmitCharacterFunction(Isolate* isolate, 978 typedef bool EmitCharacterFunction(Zone* zone,
978 RegExpCompiler* compiler, 979 RegExpCompiler* compiler,
979 uint16_t c, 980 uint16_t c,
980 BlockLabel* on_failure, 981 BlockLabel* on_failure,
981 intptr_t cp_offset, 982 intptr_t cp_offset,
982 bool check, 983 bool check,
983 bool preloaded); 984 bool preloaded);
984 985
985 // Only emits letters (things that have case). Only used for case independent 986 // Only emits letters (things that have case). Only used for case independent
986 // matches. 987 // matches.
987 static inline bool EmitAtomLetter(Isolate* isolate, 988 static inline bool EmitAtomLetter(Zone* zone,
988 RegExpCompiler* compiler, 989 RegExpCompiler* compiler,
989 uint16_t c, 990 uint16_t c,
990 BlockLabel* on_failure, 991 BlockLabel* on_failure,
991 intptr_t cp_offset, 992 intptr_t cp_offset,
992 bool check, 993 bool check,
993 bool preloaded) { 994 bool preloaded) {
994 RegExpMacroAssembler* macro_assembler = compiler->macro_assembler(); 995 RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
995 bool one_byte = compiler->one_byte(); 996 bool one_byte = compiler->one_byte();
996 int32_t chars[unibrow::Ecma262UnCanonicalize::kMaxWidth]; 997 int32_t chars[unibrow::Ecma262UnCanonicalize::kMaxWidth];
997 intptr_t length = GetCaseIndependentLetters(c, one_byte, chars); 998 intptr_t length = GetCaseIndependentLetters(c, one_byte, chars);
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
1116 for (j = (ranges->At(i) & kMask); j < (ranges->At(i + 1) & kMask); j++) { 1117 for (j = (ranges->At(i) & kMask); j < (ranges->At(i + 1) & kMask); j++) {
1117 templ[j] = bit; 1118 templ[j] = bit;
1118 } 1119 }
1119 bit ^= 1; 1120 bit ^= 1;
1120 } 1121 }
1121 for (intptr_t i = j; i < kSize; i++) { 1122 for (intptr_t i = j; i < kSize; i++) {
1122 templ[i] = bit; 1123 templ[i] = bit;
1123 } 1124 }
1124 // TODO(erikcorry): Cache these. 1125 // TODO(erikcorry): Cache these.
1125 const TypedData& ba = TypedData::ZoneHandle( 1126 const TypedData& ba = TypedData::ZoneHandle(
1126 masm->isolate(), 1127 masm->zone(),
1127 TypedData::New(kTypedDataUint8ArrayCid, kSize, Heap::kOld)); 1128 TypedData::New(kTypedDataUint8ArrayCid, kSize, Heap::kOld));
1128 for (intptr_t i = 0; i < kSize; i++) { 1129 for (intptr_t i = 0; i < kSize; i++) {
1129 ba.SetUint8(i, templ[i]); 1130 ba.SetUint8(i, templ[i]);
1130 } 1131 }
1131 masm->CheckBitInTable(ba, on_bit_set); 1132 masm->CheckBitInTable(ba, on_bit_set);
1132 if (on_bit_clear != fall_through) masm->GoTo(on_bit_clear); 1133 if (on_bit_clear != fall_through) masm->GoTo(on_bit_clear);
1133 } 1134 }
1134 1135
1135 1136
1136 static void CutOutRange(RegExpMacroAssembler* masm, 1137 static void CutOutRange(RegExpMacroAssembler* masm,
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after
1388 } 1389 }
1389 1390
1390 1391
1391 static void EmitCharClass(RegExpMacroAssembler* macro_assembler, 1392 static void EmitCharClass(RegExpMacroAssembler* macro_assembler,
1392 RegExpCharacterClass* cc, 1393 RegExpCharacterClass* cc,
1393 bool one_byte, 1394 bool one_byte,
1394 BlockLabel* on_failure, 1395 BlockLabel* on_failure,
1395 intptr_t cp_offset, 1396 intptr_t cp_offset,
1396 bool check_offset, 1397 bool check_offset,
1397 bool preloaded, 1398 bool preloaded,
1398 Isolate* isolate) { 1399 Zone* zone) {
1399 ZoneGrowableArray<CharacterRange>* ranges = cc->ranges(); 1400 ZoneGrowableArray<CharacterRange>* ranges = cc->ranges();
1400 if (!CharacterRange::IsCanonical(ranges)) { 1401 if (!CharacterRange::IsCanonical(ranges)) {
1401 CharacterRange::Canonicalize(ranges); 1402 CharacterRange::Canonicalize(ranges);
1402 } 1403 }
1403 1404
1404 intptr_t max_char; 1405 intptr_t max_char;
1405 if (one_byte) { 1406 if (one_byte) {
1406 max_char = Symbols::kMaxOneCharCodeSymbol; 1407 max_char = Symbols::kMaxOneCharCodeSymbol;
1407 } else { 1408 } else {
1408 max_char = Utf16::kMaxCodeUnit; 1409 max_char = Utf16::kMaxCodeUnit;
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
1462 } 1463 }
1463 1464
1464 1465
1465 // A new list with ascending entries. Each entry is a code unit 1466 // A new list with ascending entries. Each entry is a code unit
1466 // where there is a boundary between code units that are part of 1467 // where there is a boundary between code units that are part of
1467 // the class and code units that are not. Normally we insert an 1468 // the class and code units that are not. Normally we insert an
1468 // entry at zero which goes to the failure label, but if there 1469 // entry at zero which goes to the failure label, but if there
1469 // was already one there we fall through for success on that entry. 1470 // was already one there we fall through for success on that entry.
1470 // Subsequent entries have alternating meaning (success/failure). 1471 // Subsequent entries have alternating meaning (success/failure).
1471 ZoneGrowableArray<int>* range_boundaries = 1472 ZoneGrowableArray<int>* range_boundaries =
1472 new(isolate) ZoneGrowableArray<int>(last_valid_range); 1473 new(zone) ZoneGrowableArray<int>(last_valid_range);
1473 1474
1474 bool zeroth_entry_is_failure = !cc->is_negated(); 1475 bool zeroth_entry_is_failure = !cc->is_negated();
1475 1476
1476 for (intptr_t i = 0; i <= last_valid_range; i++) { 1477 for (intptr_t i = 0; i <= last_valid_range; i++) {
1477 CharacterRange& range = (*ranges)[i]; 1478 CharacterRange& range = (*ranges)[i];
1478 if (range.from() == 0) { 1479 if (range.from() == 0) {
1479 ASSERT(i == 0); 1480 ASSERT(i == 0);
1480 zeroth_entry_is_failure = !zeroth_entry_is_failure; 1481 zeroth_entry_is_failure = !zeroth_entry_is_failure;
1481 } else { 1482 } else {
1482 range_boundaries->Add(range.from()); 1483 range_boundaries->Add(range.from());
(...skipping 705 matching lines...) Expand 10 before | Expand all | Expand 10 after
2188 } 2189 }
2189 if (surviving < 2) return set_replacement(survivor); 2190 if (surviving < 2) return set_replacement(survivor);
2190 2191
2191 set_replacement(this); 2192 set_replacement(this);
2192 if (surviving == choice_count) { 2193 if (surviving == choice_count) {
2193 return this; 2194 return this;
2194 } 2195 }
2195 // Only some of the nodes survived the filtering. We need to rebuild the 2196 // Only some of the nodes survived the filtering. We need to rebuild the
2196 // alternatives list. 2197 // alternatives list.
2197 ZoneGrowableArray<GuardedAlternative>* new_alternatives = 2198 ZoneGrowableArray<GuardedAlternative>* new_alternatives =
2198 new(I) ZoneGrowableArray<GuardedAlternative>(surviving); 2199 new(Z) ZoneGrowableArray<GuardedAlternative>(surviving);
2199 for (intptr_t i = 0; i < choice_count; i++) { 2200 for (intptr_t i = 0; i < choice_count; i++) {
2200 RegExpNode* replacement = 2201 RegExpNode* replacement =
2201 (*alternatives_)[i].node()->FilterOneByte(depth - 1, ignore_case); 2202 (*alternatives_)[i].node()->FilterOneByte(depth - 1, ignore_case);
2202 if (replacement != NULL) { 2203 if (replacement != NULL) {
2203 (*alternatives_)[i].set_node(replacement); 2204 (*alternatives_)[i].set_node(replacement);
2204 new_alternatives->Add((*alternatives_)[i]); 2205 new_alternatives->Add((*alternatives_)[i]);
2205 } 2206 }
2206 } 2207 }
2207 alternatives_ = new_alternatives; 2208 alternatives_ = new_alternatives;
2208 return this; 2209 return this;
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
2350 bool not_at_start = (trace->at_start() == Trace::FALSE_VALUE); 2351 bool not_at_start = (trace->at_start() == Trace::FALSE_VALUE);
2351 BoyerMooreLookahead* lookahead = bm_info(not_at_start); 2352 BoyerMooreLookahead* lookahead = bm_info(not_at_start);
2352 if (lookahead == NULL) { 2353 if (lookahead == NULL) {
2353 intptr_t eats_at_least = 2354 intptr_t eats_at_least =
2354 Utils::Minimum(kMaxLookaheadForBoyerMoore, 2355 Utils::Minimum(kMaxLookaheadForBoyerMoore,
2355 EatsAtLeast(kMaxLookaheadForBoyerMoore, 2356 EatsAtLeast(kMaxLookaheadForBoyerMoore,
2356 kRecursionBudget, 2357 kRecursionBudget,
2357 not_at_start)); 2358 not_at_start));
2358 if (eats_at_least >= 1) { 2359 if (eats_at_least >= 1) {
2359 BoyerMooreLookahead* bm = 2360 BoyerMooreLookahead* bm =
2360 new(I) BoyerMooreLookahead(eats_at_least, compiler, I); 2361 new(Z) BoyerMooreLookahead(eats_at_least, compiler, Z);
2361 FillInBMInfo(0, kRecursionBudget, bm, not_at_start); 2362 FillInBMInfo(0, kRecursionBudget, bm, not_at_start);
2362 if (bm->at(0)->is_non_word()) 2363 if (bm->at(0)->is_non_word())
2363 next_is_word_character = Trace::FALSE_VALUE; 2364 next_is_word_character = Trace::FALSE_VALUE;
2364 if (bm->at(0)->is_word()) next_is_word_character = Trace::TRUE_VALUE; 2365 if (bm->at(0)->is_word()) next_is_word_character = Trace::TRUE_VALUE;
2365 } 2366 }
2366 } else { 2367 } else {
2367 if (lookahead->at(0)->is_non_word()) 2368 if (lookahead->at(0)->is_non_word())
2368 next_is_word_character = Trace::FALSE_VALUE; 2369 next_is_word_character = Trace::FALSE_VALUE;
2369 if (lookahead->at(0)->is_word()) 2370 if (lookahead->at(0)->is_word())
2370 next_is_word_character = Trace::TRUE_VALUE; 2371 next_is_word_character = Trace::TRUE_VALUE;
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
2562 case SIMPLE_CHARACTER_MATCH: 2563 case SIMPLE_CHARACTER_MATCH:
2563 emit_function = &EmitSimpleCharacter; 2564 emit_function = &EmitSimpleCharacter;
2564 break; 2565 break;
2565 case CASE_CHARACTER_MATCH: 2566 case CASE_CHARACTER_MATCH:
2566 emit_function = &EmitAtomLetter; 2567 emit_function = &EmitAtomLetter;
2567 break; 2568 break;
2568 default: 2569 default:
2569 break; 2570 break;
2570 } 2571 }
2571 if (emit_function != NULL) { 2572 if (emit_function != NULL) {
2572 bool bound_checked = emit_function(I, 2573 bool bound_checked = emit_function(Z,
2573 compiler, 2574 compiler,
2574 quarks->At(j), 2575 quarks->At(j),
2575 backtrack, 2576 backtrack,
2576 cp_offset + j, 2577 cp_offset + j,
2577 *checked_up_to < cp_offset + j, 2578 *checked_up_to < cp_offset + j,
2578 preloaded); 2579 preloaded);
2579 if (bound_checked) UpdateBoundsCheck(cp_offset + j, checked_up_to); 2580 if (bound_checked) UpdateBoundsCheck(cp_offset + j, checked_up_to);
2580 } 2581 }
2581 } 2582 }
2582 } else { 2583 } else {
2583 ASSERT(elm.text_type() == TextElement::CHAR_CLASS); 2584 ASSERT(elm.text_type() == TextElement::CHAR_CLASS);
2584 if (pass == CHARACTER_CLASS_MATCH) { 2585 if (pass == CHARACTER_CLASS_MATCH) {
2585 if (first_element_checked && i == 0) continue; 2586 if (first_element_checked && i == 0) continue;
2586 if (DeterminedAlready(quick_check, elm.cp_offset())) continue; 2587 if (DeterminedAlready(quick_check, elm.cp_offset())) continue;
2587 RegExpCharacterClass* cc = elm.char_class(); 2588 RegExpCharacterClass* cc = elm.char_class();
2588 EmitCharClass(assembler, 2589 EmitCharClass(assembler,
2589 cc, 2590 cc,
2590 one_byte, 2591 one_byte,
2591 backtrack, 2592 backtrack,
2592 cp_offset, 2593 cp_offset,
2593 *checked_up_to < cp_offset, 2594 *checked_up_to < cp_offset,
2594 preloaded, 2595 preloaded,
2595 I); 2596 Z);
2596 UpdateBoundsCheck(cp_offset, checked_up_to); 2597 UpdateBoundsCheck(cp_offset, checked_up_to);
2597 } 2598 }
2598 } 2599 }
2599 } 2600 }
2600 } 2601 }
2601 2602
2602 2603
2603 intptr_t TextNode::Length() { 2604 intptr_t TextNode::Length() {
2604 TextElement elm = elms_->Last(); 2605 TextElement elm = elms_->Last();
2605 ASSERT(elm.cp_offset() >= 0); 2606 ASSERT(elm.cp_offset() >= 0);
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
2708 for (intptr_t i = 0; i < element_count; i++) { 2709 for (intptr_t i = 0; i < element_count; i++) {
2709 TextElement elm = elms_->At(i); 2710 TextElement elm = elms_->At(i);
2710 if (elm.text_type() == TextElement::CHAR_CLASS) { 2711 if (elm.text_type() == TextElement::CHAR_CLASS) {
2711 RegExpCharacterClass* cc = elm.char_class(); 2712 RegExpCharacterClass* cc = elm.char_class();
2712 // None of the standard character classes is different in the case 2713 // None of the standard character classes is different in the case
2713 // independent case and it slows us down if we don't know that. 2714 // independent case and it slows us down if we don't know that.
2714 if (cc->is_standard()) continue; 2715 if (cc->is_standard()) continue;
2715 ZoneGrowableArray<CharacterRange>* ranges = cc->ranges(); 2716 ZoneGrowableArray<CharacterRange>* ranges = cc->ranges();
2716 intptr_t range_count = ranges->length(); 2717 intptr_t range_count = ranges->length();
2717 for (intptr_t j = 0; j < range_count; j++) { 2718 for (intptr_t j = 0; j < range_count; j++) {
2718 (*ranges)[j].AddCaseEquivalents(ranges, is_one_byte, I); 2719 (*ranges)[j].AddCaseEquivalents(ranges, is_one_byte, Z);
2719 } 2720 }
2720 } 2721 }
2721 } 2722 }
2722 } 2723 }
2723 2724
2724 2725
2725 intptr_t TextNode::GreedyLoopTextLength() { 2726 intptr_t TextNode::GreedyLoopTextLength() {
2726 TextElement elm = elms_->At(elms_->length() - 1); 2727 TextElement elm = elms_->At(elms_->length() - 1);
2727 return elm.cp_offset() + elm.length(); 2728 return elm.cp_offset() + elm.length();
2728 } 2729 }
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after
2939 void BoyerMoorePositionInfo::SetAll() { 2940 void BoyerMoorePositionInfo::SetAll() {
2940 s_ = w_ = d_ = kLatticeUnknown; 2941 s_ = w_ = d_ = kLatticeUnknown;
2941 if (map_count_ != kMapSize) { 2942 if (map_count_ != kMapSize) {
2942 map_count_ = kMapSize; 2943 map_count_ = kMapSize;
2943 for (intptr_t i = 0; i < kMapSize; i++) (*map_)[i] = true; 2944 for (intptr_t i = 0; i < kMapSize; i++) (*map_)[i] = true;
2944 } 2945 }
2945 } 2946 }
2946 2947
2947 2948
2948 BoyerMooreLookahead::BoyerMooreLookahead( 2949 BoyerMooreLookahead::BoyerMooreLookahead(
2949 intptr_t length, RegExpCompiler* compiler, Isolate* isolate) 2950 intptr_t length, RegExpCompiler* compiler, Zone* zone)
2950 : length_(length), 2951 : length_(length),
2951 compiler_(compiler) { 2952 compiler_(compiler) {
2952 if (compiler->one_byte()) { 2953 if (compiler->one_byte()) {
2953 max_char_ = Symbols::kMaxOneCharCodeSymbol; 2954 max_char_ = Symbols::kMaxOneCharCodeSymbol;
2954 } else { 2955 } else {
2955 max_char_ = Utf16::kMaxCodeUnit; 2956 max_char_ = Utf16::kMaxCodeUnit;
2956 } 2957 }
2957 bitmaps_ = new(isolate) ZoneGrowableArray<BoyerMoorePositionInfo*>(length); 2958 bitmaps_ = new(zone) ZoneGrowableArray<BoyerMoorePositionInfo*>(length);
2958 for (intptr_t i = 0; i < length; i++) { 2959 for (intptr_t i = 0; i < length; i++) {
2959 bitmaps_->Add(new(isolate) BoyerMoorePositionInfo(isolate)); 2960 bitmaps_->Add(new(zone) BoyerMoorePositionInfo(zone));
2960 } 2961 }
2961 } 2962 }
2962 2963
2963 2964
2964 // Find the longest range of lookahead that has the fewest number of different 2965 // Find the longest range of lookahead that has the fewest number of different
2965 // characters that can occur at a given position. Since we are optimizing two 2966 // characters that can occur at a given position. Since we are optimizing two
2966 // different parameters at once this is a tradeoff. 2967 // different parameters at once this is a tradeoff.
2967 bool BoyerMooreLookahead::FindWorthwhileInterval(intptr_t* from, intptr_t* to) { 2968 bool BoyerMooreLookahead::FindWorthwhileInterval(intptr_t* from, intptr_t* to) {
2968 intptr_t biggest_points = 0; 2969 intptr_t biggest_points = 0;
2969 // If more than 32 characters out of 128 can occur it is unlikely that we can 2970 // If more than 32 characters out of 128 can occur it is unlikely that we can
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
3114 } else { 3115 } else {
3115 masm->CheckCharacter(single_character, &cont); 3116 masm->CheckCharacter(single_character, &cont);
3116 } 3117 }
3117 masm->AdvanceCurrentPosition(lookahead_width); 3118 masm->AdvanceCurrentPosition(lookahead_width);
3118 masm->GoTo(&again); 3119 masm->GoTo(&again);
3119 masm->BindBlock(&cont); 3120 masm->BindBlock(&cont);
3120 return; 3121 return;
3121 } 3122 }
3122 3123
3123 const TypedData& boolean_skip_table = TypedData::ZoneHandle( 3124 const TypedData& boolean_skip_table = TypedData::ZoneHandle(
3124 compiler_->isolate(), 3125 compiler_->zone(),
3125 TypedData::New(kTypedDataUint8ArrayCid, kSize, Heap::kOld)); 3126 TypedData::New(kTypedDataUint8ArrayCid, kSize, Heap::kOld));
3126 intptr_t skip_distance = GetSkipTable( 3127 intptr_t skip_distance = GetSkipTable(
3127 min_lookahead, max_lookahead, boolean_skip_table); 3128 min_lookahead, max_lookahead, boolean_skip_table);
3128 ASSERT(skip_distance != 0); 3129 ASSERT(skip_distance != 0);
3129 3130
3130 BlockLabel cont, again; 3131 BlockLabel cont, again;
3131 3132
3132 masm->BindBlock(&again); 3133 masm->BindBlock(&again);
3133 masm->LoadCurrentCharacter(max_lookahead, &cont, true); 3134 masm->LoadCurrentCharacter(max_lookahead, &cont, true);
3134 masm->CheckBitInTable(boolean_skip_table, &cont); 3135 masm->CheckBitInTable(boolean_skip_table, &cont);
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after
3403 // and step forwards 3 if the character is not one of abc. Abc need 3404 // and step forwards 3 if the character is not one of abc. Abc need
3404 // not be atoms, they can be any reasonably limited character class or 3405 // not be atoms, they can be any reasonably limited character class or
3405 // small alternation. 3406 // small alternation.
3406 BoyerMooreLookahead* bm = bm_info(false); 3407 BoyerMooreLookahead* bm = bm_info(false);
3407 if (bm == NULL) { 3408 if (bm == NULL) {
3408 eats_at_least = Utils::Minimum(kMaxLookaheadForBoyerMoore, 3409 eats_at_least = Utils::Minimum(kMaxLookaheadForBoyerMoore,
3409 EatsAtLeast(kMaxLookaheadForBoyerMoore, 3410 EatsAtLeast(kMaxLookaheadForBoyerMoore,
3410 kRecursionBudget, 3411 kRecursionBudget,
3411 false)); 3412 false));
3412 if (eats_at_least >= 1) { 3413 if (eats_at_least >= 1) {
3413 bm = new(I) BoyerMooreLookahead(eats_at_least, compiler, I); 3414 bm = new(Z) BoyerMooreLookahead(eats_at_least, compiler, Z);
3414 GuardedAlternative alt0 = alternatives_->At(0); 3415 GuardedAlternative alt0 = alternatives_->At(0);
3415 alt0.node()->FillInBMInfo(0, kRecursionBudget, bm, false); 3416 alt0.node()->FillInBMInfo(0, kRecursionBudget, bm, false);
3416 } 3417 }
3417 } 3418 }
3418 if (bm != NULL) { 3419 if (bm != NULL) {
3419 bm->EmitSkipInstructions(macro_assembler); 3420 bm->EmitSkipInstructions(macro_assembler);
3420 } 3421 }
3421 return eats_at_least; 3422 return eats_at_least;
3422 } 3423 }
3423 3424
(...skipping 520 matching lines...) Expand 10 before | Expand all | Expand 10 after
3944 3945
3945 #endif // DEBUG 3946 #endif // DEBUG
3946 3947
3947 3948
3948 // ------------------------------------------------------------------- 3949 // -------------------------------------------------------------------
3949 // Tree to graph conversion 3950 // Tree to graph conversion
3950 3951
3951 RegExpNode* RegExpAtom::ToNode(RegExpCompiler* compiler, 3952 RegExpNode* RegExpAtom::ToNode(RegExpCompiler* compiler,
3952 RegExpNode* on_success) { 3953 RegExpNode* on_success) {
3953 ZoneGrowableArray<TextElement>* elms = 3954 ZoneGrowableArray<TextElement>* elms =
3954 new(CI) ZoneGrowableArray<TextElement>(1); 3955 new(CZ) ZoneGrowableArray<TextElement>(1);
3955 elms->Add(TextElement::Atom(this)); 3956 elms->Add(TextElement::Atom(this));
3956 return new(CI) TextNode(elms, on_success); 3957 return new(CZ) TextNode(elms, on_success);
3957 } 3958 }
3958 3959
3959 3960
3960 RegExpNode* RegExpText::ToNode(RegExpCompiler* compiler, 3961 RegExpNode* RegExpText::ToNode(RegExpCompiler* compiler,
3961 RegExpNode* on_success) { 3962 RegExpNode* on_success) {
3962 ZoneGrowableArray<TextElement>* elms = 3963 ZoneGrowableArray<TextElement>* elms =
3963 new(CI) ZoneGrowableArray<TextElement>(1); 3964 new(CZ) ZoneGrowableArray<TextElement>(1);
3964 for (intptr_t i = 0; i < elements()->length(); i++) { 3965 for (intptr_t i = 0; i < elements()->length(); i++) {
3965 elms->Add(elements()->At(i)); 3966 elms->Add(elements()->At(i));
3966 } 3967 }
3967 return new(CI) TextNode(elms, on_success); 3968 return new(CZ) TextNode(elms, on_success);
3968 } 3969 }
3969 3970
3970 3971
3971 static bool CompareInverseRanges(ZoneGrowableArray<CharacterRange>* ranges, 3972 static bool CompareInverseRanges(ZoneGrowableArray<CharacterRange>* ranges,
3972 const intptr_t* special_class, 3973 const intptr_t* special_class,
3973 intptr_t length) { 3974 intptr_t length) {
3974 length--; // Remove final 0x10000. 3975 length--; // Remove final 0x10000.
3975 ASSERT(special_class[length] == 0x10000); 3976 ASSERT(special_class[length] == 0x10000);
3976 ASSERT(ranges->length() != 0); 3977 ASSERT(ranges->length() != 0);
3977 ASSERT(length != 0); 3978 ASSERT(length != 0);
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
4054 if (CompareInverseRanges(set_.ranges(), kWordRanges, kWordRangeCount)) { 4055 if (CompareInverseRanges(set_.ranges(), kWordRanges, kWordRangeCount)) {
4055 set_.set_standard_set_type('W'); 4056 set_.set_standard_set_type('W');
4056 return true; 4057 return true;
4057 } 4058 }
4058 return false; 4059 return false;
4059 } 4060 }
4060 4061
4061 4062
4062 RegExpNode* RegExpCharacterClass::ToNode(RegExpCompiler* compiler, 4063 RegExpNode* RegExpCharacterClass::ToNode(RegExpCompiler* compiler,
4063 RegExpNode* on_success) { 4064 RegExpNode* on_success) {
4064 return new(CI) TextNode(this, on_success); 4065 return new(CZ) TextNode(this, on_success);
4065 } 4066 }
4066 4067
4067 4068
4068 RegExpNode* RegExpDisjunction::ToNode(RegExpCompiler* compiler, 4069 RegExpNode* RegExpDisjunction::ToNode(RegExpCompiler* compiler,
4069 RegExpNode* on_success) { 4070 RegExpNode* on_success) {
4070 ZoneGrowableArray<RegExpTree*>* alternatives = this->alternatives(); 4071 ZoneGrowableArray<RegExpTree*>* alternatives = this->alternatives();
4071 intptr_t length = alternatives->length(); 4072 intptr_t length = alternatives->length();
4072 ChoiceNode* result = 4073 ChoiceNode* result =
4073 new(CI) ChoiceNode(length, CI); 4074 new(CZ) ChoiceNode(length, CZ);
4074 for (intptr_t i = 0; i < length; i++) { 4075 for (intptr_t i = 0; i < length; i++) {
4075 GuardedAlternative alternative(alternatives->At(i)->ToNode(compiler, 4076 GuardedAlternative alternative(alternatives->At(i)->ToNode(compiler,
4076 on_success)); 4077 on_success));
4077 result->AddAlternative(alternative); 4078 result->AddAlternative(alternative);
4078 } 4079 }
4079 return result; 4080 return result;
4080 } 4081 }
4081 4082
4082 4083
4083 RegExpNode* RegExpQuantifier::ToNode(RegExpCompiler* compiler, 4084 RegExpNode* RegExpQuantifier::ToNode(RegExpCompiler* compiler,
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
4158 // this case. 4159 // this case.
4159 // Unroll (foo)+ and (foo){3,} 4160 // Unroll (foo)+ and (foo){3,}
4160 static const intptr_t kMaxUnrolledMinMatches = 3; 4161 static const intptr_t kMaxUnrolledMinMatches = 3;
4161 // Unroll (foo)? and (foo){x,3} 4162 // Unroll (foo)? and (foo){x,3}
4162 static const intptr_t kMaxUnrolledMaxMatches = 3; 4163 static const intptr_t kMaxUnrolledMaxMatches = 3;
4163 if (max == 0) return on_success; // This can happen due to recursion. 4164 if (max == 0) return on_success; // This can happen due to recursion.
4164 bool body_can_be_empty = (body->min_match() == 0); 4165 bool body_can_be_empty = (body->min_match() == 0);
4165 intptr_t body_start_reg = RegExpCompiler::kNoRegister; 4166 intptr_t body_start_reg = RegExpCompiler::kNoRegister;
4166 Interval capture_registers = body->CaptureRegisters(); 4167 Interval capture_registers = body->CaptureRegisters();
4167 bool needs_capture_clearing = !capture_registers.is_empty(); 4168 bool needs_capture_clearing = !capture_registers.is_empty();
4168 Isolate* isolate = compiler->isolate(); 4169 Zone* zone = compiler->zone();
4169 4170
4170 if (body_can_be_empty) { 4171 if (body_can_be_empty) {
4171 body_start_reg = compiler->AllocateRegister(); 4172 body_start_reg = compiler->AllocateRegister();
4172 } else if (kRegexpOptimization && !needs_capture_clearing) { 4173 } else if (kRegexpOptimization && !needs_capture_clearing) {
4173 // Only unroll if there are no captures and the body can't be 4174 // Only unroll if there are no captures and the body can't be
4174 // empty. 4175 // empty.
4175 { 4176 {
4176 RegExpExpansionLimiter limiter( 4177 RegExpExpansionLimiter limiter(
4177 compiler, min + ((max != min) ? 1 : 0)); 4178 compiler, min + ((max != min) ? 1 : 0));
4178 if (min > 0 && min <= kMaxUnrolledMinMatches && limiter.ok_to_expand()) { 4179 if (min > 0 && min <= kMaxUnrolledMinMatches && limiter.ok_to_expand()) {
(...skipping 11 matching lines...) Expand all
4190 return answer; 4191 return answer;
4191 } 4192 }
4192 } 4193 }
4193 if (max <= kMaxUnrolledMaxMatches && min == 0) { 4194 if (max <= kMaxUnrolledMaxMatches && min == 0) {
4194 ASSERT(max > 0); // Due to the 'if' above. 4195 ASSERT(max > 0); // Due to the 'if' above.
4195 RegExpExpansionLimiter limiter(compiler, max); 4196 RegExpExpansionLimiter limiter(compiler, max);
4196 if (limiter.ok_to_expand()) { 4197 if (limiter.ok_to_expand()) {
4197 // Unroll the optional matches up to max. 4198 // Unroll the optional matches up to max.
4198 RegExpNode* answer = on_success; 4199 RegExpNode* answer = on_success;
4199 for (intptr_t i = 0; i < max; i++) { 4200 for (intptr_t i = 0; i < max; i++) {
4200 ChoiceNode* alternation = new(isolate) ChoiceNode(2, isolate); 4201 ChoiceNode* alternation = new(zone) ChoiceNode(2, zone);
4201 if (is_greedy) { 4202 if (is_greedy) {
4202 alternation->AddAlternative( 4203 alternation->AddAlternative(
4203 GuardedAlternative(body->ToNode(compiler, answer))); 4204 GuardedAlternative(body->ToNode(compiler, answer)));
4204 alternation->AddAlternative(GuardedAlternative(on_success)); 4205 alternation->AddAlternative(GuardedAlternative(on_success));
4205 } else { 4206 } else {
4206 alternation->AddAlternative(GuardedAlternative(on_success)); 4207 alternation->AddAlternative(GuardedAlternative(on_success));
4207 alternation->AddAlternative( 4208 alternation->AddAlternative(
4208 GuardedAlternative(body->ToNode(compiler, answer))); 4209 GuardedAlternative(body->ToNode(compiler, answer)));
4209 } 4210 }
4210 answer = alternation; 4211 answer = alternation;
4211 if (not_at_start) alternation->set_not_at_start(); 4212 if (not_at_start) alternation->set_not_at_start();
4212 } 4213 }
4213 return answer; 4214 return answer;
4214 } 4215 }
4215 } 4216 }
4216 } 4217 }
4217 bool has_min = min > 0; 4218 bool has_min = min > 0;
4218 bool has_max = max < RegExpTree::kInfinity; 4219 bool has_max = max < RegExpTree::kInfinity;
4219 bool needs_counter = has_min || has_max; 4220 bool needs_counter = has_min || has_max;
4220 intptr_t reg_ctr = needs_counter 4221 intptr_t reg_ctr = needs_counter
4221 ? compiler->AllocateRegister() 4222 ? compiler->AllocateRegister()
4222 : RegExpCompiler::kNoRegister; 4223 : RegExpCompiler::kNoRegister;
4223 LoopChoiceNode* center = new(isolate) LoopChoiceNode(body->min_match() == 0, 4224 LoopChoiceNode* center = new(zone) LoopChoiceNode(body->min_match() == 0,
4224 isolate); 4225 zone);
4225 if (not_at_start) center->set_not_at_start(); 4226 if (not_at_start) center->set_not_at_start();
4226 RegExpNode* loop_return = needs_counter 4227 RegExpNode* loop_return = needs_counter
4227 ? static_cast<RegExpNode*>(ActionNode::IncrementRegister(reg_ctr, center)) 4228 ? static_cast<RegExpNode*>(ActionNode::IncrementRegister(reg_ctr, center))
4228 : static_cast<RegExpNode*>(center); 4229 : static_cast<RegExpNode*>(center);
4229 if (body_can_be_empty) { 4230 if (body_can_be_empty) {
4230 // If the body can be empty we need to check if it was and then 4231 // If the body can be empty we need to check if it was and then
4231 // backtrack. 4232 // backtrack.
4232 loop_return = ActionNode::EmptyMatchCheck(body_start_reg, 4233 loop_return = ActionNode::EmptyMatchCheck(body_start_reg,
4233 reg_ctr, 4234 reg_ctr,
4234 min, 4235 min,
4235 loop_return); 4236 loop_return);
4236 } 4237 }
4237 RegExpNode* body_node = body->ToNode(compiler, loop_return); 4238 RegExpNode* body_node = body->ToNode(compiler, loop_return);
4238 if (body_can_be_empty) { 4239 if (body_can_be_empty) {
4239 // If the body can be empty we need to store the start position 4240 // If the body can be empty we need to store the start position
4240 // so we can bail out if it was empty. 4241 // so we can bail out if it was empty.
4241 body_node = ActionNode::StorePosition(body_start_reg, false, body_node); 4242 body_node = ActionNode::StorePosition(body_start_reg, false, body_node);
4242 } 4243 }
4243 if (needs_capture_clearing) { 4244 if (needs_capture_clearing) {
4244 // Before entering the body of this loop we need to clear captures. 4245 // Before entering the body of this loop we need to clear captures.
4245 body_node = ActionNode::ClearCaptures(capture_registers, body_node); 4246 body_node = ActionNode::ClearCaptures(capture_registers, body_node);
4246 } 4247 }
4247 GuardedAlternative body_alt(body_node); 4248 GuardedAlternative body_alt(body_node);
4248 if (has_max) { 4249 if (has_max) {
4249 Guard* body_guard = 4250 Guard* body_guard =
4250 new(isolate) Guard(reg_ctr, Guard::LT, max); 4251 new(zone) Guard(reg_ctr, Guard::LT, max);
4251 body_alt.AddGuard(body_guard, isolate); 4252 body_alt.AddGuard(body_guard, zone);
4252 } 4253 }
4253 GuardedAlternative rest_alt(on_success); 4254 GuardedAlternative rest_alt(on_success);
4254 if (has_min) { 4255 if (has_min) {
4255 Guard* rest_guard = new(isolate) Guard(reg_ctr, Guard::GEQ, min); 4256 Guard* rest_guard = new(zone) Guard(reg_ctr, Guard::GEQ, min);
4256 rest_alt.AddGuard(rest_guard, isolate); 4257 rest_alt.AddGuard(rest_guard, zone);
4257 } 4258 }
4258 if (is_greedy) { 4259 if (is_greedy) {
4259 center->AddLoopAlternative(body_alt); 4260 center->AddLoopAlternative(body_alt);
4260 center->AddContinueAlternative(rest_alt); 4261 center->AddContinueAlternative(rest_alt);
4261 } else { 4262 } else {
4262 center->AddContinueAlternative(rest_alt); 4263 center->AddContinueAlternative(rest_alt);
4263 center->AddLoopAlternative(body_alt); 4264 center->AddLoopAlternative(body_alt);
4264 } 4265 }
4265 if (needs_counter) { 4266 if (needs_counter) {
4266 return ActionNode::SetRegister(reg_ctr, 0, center); 4267 return ActionNode::SetRegister(reg_ctr, 0, center);
(...skipping 16 matching lines...) Expand all
4283 return AssertionNode::AtNonBoundary(on_success); 4284 return AssertionNode::AtNonBoundary(on_success);
4284 case END_OF_INPUT: 4285 case END_OF_INPUT:
4285 return AssertionNode::AtEnd(on_success); 4286 return AssertionNode::AtEnd(on_success);
4286 case END_OF_LINE: { 4287 case END_OF_LINE: {
4287 // Compile $ in multiline regexps as an alternation with a positive 4288 // Compile $ in multiline regexps as an alternation with a positive
4288 // lookahead in one side and an end-of-input on the other side. 4289 // lookahead in one side and an end-of-input on the other side.
4289 // We need two registers for the lookahead. 4290 // We need two registers for the lookahead.
4290 intptr_t stack_pointer_register = compiler->AllocateRegister(); 4291 intptr_t stack_pointer_register = compiler->AllocateRegister();
4291 intptr_t position_register = compiler->AllocateRegister(); 4292 intptr_t position_register = compiler->AllocateRegister();
4292 // The ChoiceNode to distinguish between a newline and end-of-input. 4293 // The ChoiceNode to distinguish between a newline and end-of-input.
4293 ChoiceNode* result = new ChoiceNode(2, on_success->isolate()); 4294 ChoiceNode* result = new ChoiceNode(2, on_success->zone());
4294 // Create a newline atom. 4295 // Create a newline atom.
4295 ZoneGrowableArray<CharacterRange>* newline_ranges = 4296 ZoneGrowableArray<CharacterRange>* newline_ranges =
4296 new ZoneGrowableArray<CharacterRange>(3); 4297 new ZoneGrowableArray<CharacterRange>(3);
4297 CharacterRange::AddClassEscape('n', newline_ranges); 4298 CharacterRange::AddClassEscape('n', newline_ranges);
4298 RegExpCharacterClass* newline_atom = new RegExpCharacterClass('n'); 4299 RegExpCharacterClass* newline_atom = new RegExpCharacterClass('n');
4299 TextNode* newline_matcher = new TextNode( 4300 TextNode* newline_matcher = new TextNode(
4300 newline_atom, 4301 newline_atom,
4301 ActionNode::PositiveSubmatchSuccess(stack_pointer_register, 4302 ActionNode::PositiveSubmatchSuccess(stack_pointer_register,
4302 position_register, 4303 position_register,
4303 0, // No captures inside. 4304 0, // No captures inside.
(...skipping 13 matching lines...) Expand all
4317 } 4318 }
4318 default: 4319 default:
4319 UNREACHABLE(); 4320 UNREACHABLE();
4320 } 4321 }
4321 return on_success; 4322 return on_success;
4322 } 4323 }
4323 4324
4324 4325
4325 RegExpNode* RegExpBackReference::ToNode(RegExpCompiler* compiler, 4326 RegExpNode* RegExpBackReference::ToNode(RegExpCompiler* compiler,
4326 RegExpNode* on_success) { 4327 RegExpNode* on_success) {
4327 return new(CI) 4328 return new(CZ)
4328 BackReferenceNode(RegExpCapture::StartRegister(index()), 4329 BackReferenceNode(RegExpCapture::StartRegister(index()),
4329 RegExpCapture::EndRegister(index()), 4330 RegExpCapture::EndRegister(index()),
4330 on_success); 4331 on_success);
4331 } 4332 }
4332 4333
4333 4334
4334 RegExpNode* RegExpEmpty::ToNode(RegExpCompiler* compiler, 4335 RegExpNode* RegExpEmpty::ToNode(RegExpCompiler* compiler,
4335 RegExpNode* on_success) { 4336 RegExpNode* on_success) {
4336 return on_success; 4337 return on_success;
4337 } 4338 }
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
4369 // NegativeSubmatchSuccess will unwind the stack including everything the 4370 // NegativeSubmatchSuccess will unwind the stack including everything the
4370 // choice node set up and backtrack. If the first alternative fails then 4371 // choice node set up and backtrack. If the first alternative fails then
4371 // the second alternative is tried, which is exactly the desired result 4372 // the second alternative is tried, which is exactly the desired result
4372 // for a negative lookahead. The NegativeLookaheadChoiceNode is a special 4373 // for a negative lookahead. The NegativeLookaheadChoiceNode is a special
4373 // ChoiceNode that knows to ignore the first exit when calculating quick 4374 // ChoiceNode that knows to ignore the first exit when calculating quick
4374 // checks. 4375 // checks.
4375 4376
4376 GuardedAlternative body_alt( 4377 GuardedAlternative body_alt(
4377 body()->ToNode( 4378 body()->ToNode(
4378 compiler, 4379 compiler,
4379 success = new(CI) NegativeSubmatchSuccess(stack_pointer_register, 4380 success = new(CZ) NegativeSubmatchSuccess(stack_pointer_register,
4380 position_register, 4381 position_register,
4381 register_count, 4382 register_count,
4382 register_start, 4383 register_start,
4383 CI))); 4384 CZ)));
4384 ChoiceNode* choice_node = 4385 ChoiceNode* choice_node =
4385 new(CI) NegativeLookaheadChoiceNode(body_alt, 4386 new(CZ) NegativeLookaheadChoiceNode(body_alt,
4386 GuardedAlternative(on_success), 4387 GuardedAlternative(on_success),
4387 CI); 4388 CZ);
4388 return ActionNode::BeginSubmatch(stack_pointer_register, 4389 return ActionNode::BeginSubmatch(stack_pointer_register,
4389 position_register, 4390 position_register,
4390 choice_node); 4391 choice_node);
4391 } 4392 }
4392 } 4393 }
4393 4394
4394 4395
4395 RegExpNode* RegExpCapture::ToNode(RegExpCompiler* compiler, 4396 RegExpNode* RegExpCapture::ToNode(RegExpCompiler* compiler,
4396 RegExpNode* on_success) { 4397 RegExpNode* on_success) {
4397 return ToNode(body(), index(), compiler, on_success); 4398 return ToNode(body(), index(), compiler, on_success);
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
4492 break; 4493 break;
4493 default: 4494 default:
4494 UNREACHABLE(); 4495 UNREACHABLE();
4495 } 4496 }
4496 } 4497 }
4497 4498
4498 4499
4499 void CharacterRange::AddCaseEquivalents( 4500 void CharacterRange::AddCaseEquivalents(
4500 ZoneGrowableArray<CharacterRange>* ranges, 4501 ZoneGrowableArray<CharacterRange>* ranges,
4501 bool is_one_byte, 4502 bool is_one_byte,
4502 Isolate* isolate) { 4503 Zone* zone) {
4503 uint16_t bottom = from(); 4504 uint16_t bottom = from();
4504 uint16_t top = to(); 4505 uint16_t top = to();
4505 if (is_one_byte && !RangeContainsLatin1Equivalents(*this)) { 4506 if (is_one_byte && !RangeContainsLatin1Equivalents(*this)) {
4506 if (bottom > Symbols::kMaxOneCharCodeSymbol) return; 4507 if (bottom > Symbols::kMaxOneCharCodeSymbol) return;
4507 if (top > Symbols::kMaxOneCharCodeSymbol) { 4508 if (top > Symbols::kMaxOneCharCodeSymbol) {
4508 top = Symbols::kMaxOneCharCodeSymbol; 4509 top = Symbols::kMaxOneCharCodeSymbol;
4509 } 4510 }
4510 } 4511 }
4511 4512
4512 unibrow::Mapping<unibrow::Ecma262UnCanonicalize> jsregexp_uncanonicalize; 4513 unibrow::Mapping<unibrow::Ecma262UnCanonicalize> jsregexp_uncanonicalize;
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after
4746 unsigned value) { 4747 unsigned value) {
4747 for (intptr_t i = 0; i < array->length(); i++) { 4748 for (intptr_t i = 0; i < array->length(); i++) {
4748 if (array->At(i) == value) { 4749 if (array->At(i) == value) {
4749 return true; 4750 return true;
4750 } 4751 }
4751 } 4752 }
4752 return false; 4753 return false;
4753 } 4754 }
4754 4755
4755 4756
4756 void OutSet::Set(unsigned value, Isolate* isolate) { 4757 void OutSet::Set(unsigned value, Zone* zone) {
4757 if (value < kFirstLimit) { 4758 if (value < kFirstLimit) {
4758 first_ |= (1 << value); 4759 first_ |= (1 << value);
4759 } else { 4760 } else {
4760 if (remaining_ == NULL) 4761 if (remaining_ == NULL)
4761 remaining_ = new(isolate) ZoneGrowableArray<unsigned>(1); 4762 remaining_ = new(zone) ZoneGrowableArray<unsigned>(1);
4762 4763
4763 bool remaining_contains_value = ArrayContains(remaining_, value); 4764 bool remaining_contains_value = ArrayContains(remaining_, value);
4764 if (remaining_->is_empty() || !remaining_contains_value) { 4765 if (remaining_->is_empty() || !remaining_contains_value) {
4765 remaining_->Add(value); 4766 remaining_->Add(value);
4766 } 4767 }
4767 } 4768 }
4768 } 4769 }
4769 4770
4770 4771
4771 bool OutSet::Get(unsigned value) const { 4772 bool OutSet::Get(unsigned value) const {
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after
4970 bm, 4971 bm,
4971 true); // Not at start after a text node. 4972 true); // Not at start after a text node.
4972 if (initial_offset == 0) set_bm_info(not_at_start, bm); 4973 if (initial_offset == 0) set_bm_info(not_at_start, bm);
4973 } 4974 }
4974 4975
4975 4976
4976 RegExpEngine::CompilationResult RegExpEngine::Compile( 4977 RegExpEngine::CompilationResult RegExpEngine::Compile(
4977 RegExpCompileData* data, 4978 RegExpCompileData* data,
4978 const ParsedFunction* parsed_function, 4979 const ParsedFunction* parsed_function,
4979 const ZoneGrowableArray<const ICData*>& ic_data_array) { 4980 const ZoneGrowableArray<const ICData*>& ic_data_array) {
4980 Isolate* isolate = Isolate::Current(); 4981 Zone* zone = Thread::Current()->zone();
4981 4982
4982 const Function& function = parsed_function->function(); 4983 const Function& function = parsed_function->function();
4983 const intptr_t specialization_cid = function.regexp_cid(); 4984 const intptr_t specialization_cid = function.regexp_cid();
4984 const bool is_one_byte = (specialization_cid == kOneByteStringCid || 4985 const bool is_one_byte = (specialization_cid == kOneByteStringCid ||
4985 specialization_cid == kExternalOneByteStringCid); 4986 specialization_cid == kExternalOneByteStringCid);
4986 JSRegExp& regexp = JSRegExp::Handle(isolate, function.regexp()); 4987 JSRegExp& regexp = JSRegExp::Handle(zone, function.regexp());
4987 const String& pattern = String::Handle(isolate, regexp.pattern()); 4988 const String& pattern = String::Handle(zone, regexp.pattern());
4988 4989
4989 ASSERT(!regexp.IsNull()); 4990 ASSERT(!regexp.IsNull());
4990 ASSERT(!pattern.IsNull()); 4991 ASSERT(!pattern.IsNull());
4991 4992
4992 const bool ignore_case = regexp.is_ignore_case(); 4993 const bool ignore_case = regexp.is_ignore_case();
4993 const bool is_global = regexp.is_global(); 4994 const bool is_global = regexp.is_global();
4994 4995
4995 RegExpCompiler compiler(data->capture_count, ignore_case, specialization_cid); 4996 RegExpCompiler compiler(data->capture_count, ignore_case, specialization_cid);
4996 4997
4997 // TODO(zerny): Frequency sampling is currently disabled because of several 4998 // TODO(zerny): Frequency sampling is currently disabled because of several
(...skipping 15 matching lines...) Expand all
5013 bool is_end_anchored = data->tree->IsAnchoredAtEnd(); 5014 bool is_end_anchored = data->tree->IsAnchoredAtEnd();
5014 bool is_start_anchored = data->tree->IsAnchoredAtStart(); 5015 bool is_start_anchored = data->tree->IsAnchoredAtStart();
5015 intptr_t max_length = data->tree->max_match(); 5016 intptr_t max_length = data->tree->max_match();
5016 if (!is_start_anchored) { 5017 if (!is_start_anchored) {
5017 // Add a .*? at the beginning, outside the body capture, unless 5018 // Add a .*? at the beginning, outside the body capture, unless
5018 // this expression is anchored at the beginning. 5019 // this expression is anchored at the beginning.
5019 RegExpNode* loop_node = 5020 RegExpNode* loop_node =
5020 RegExpQuantifier::ToNode(0, 5021 RegExpQuantifier::ToNode(0,
5021 RegExpTree::kInfinity, 5022 RegExpTree::kInfinity,
5022 false, 5023 false,
5023 new(isolate) RegExpCharacterClass('*'), 5024 new(zone) RegExpCharacterClass('*'),
5024 &compiler, 5025 &compiler,
5025 captured_body, 5026 captured_body,
5026 data->contains_anchor); 5027 data->contains_anchor);
5027 5028
5028 if (data->contains_anchor) { 5029 if (data->contains_anchor) {
5029 // Unroll loop once, to take care of the case that might start 5030 // Unroll loop once, to take care of the case that might start
5030 // at the start of input. 5031 // at the start of input.
5031 ChoiceNode* first_step_node = new(isolate) ChoiceNode(2, isolate); 5032 ChoiceNode* first_step_node = new(zone) ChoiceNode(2, zone);
5032 first_step_node->AddAlternative(GuardedAlternative(captured_body)); 5033 first_step_node->AddAlternative(GuardedAlternative(captured_body));
5033 first_step_node->AddAlternative(GuardedAlternative( 5034 first_step_node->AddAlternative(GuardedAlternative(
5034 new(isolate) TextNode( 5035 new(zone) TextNode(
5035 new(isolate) RegExpCharacterClass('*'), loop_node))); 5036 new(zone) RegExpCharacterClass('*'), loop_node)));
5036 node = first_step_node; 5037 node = first_step_node;
5037 } else { 5038 } else {
5038 node = loop_node; 5039 node = loop_node;
5039 } 5040 }
5040 } 5041 }
5041 if (is_one_byte) { 5042 if (is_one_byte) {
5042 node = node->FilterOneByte(RegExpCompiler::kMaxRecursion, ignore_case); 5043 node = node->FilterOneByte(RegExpCompiler::kMaxRecursion, ignore_case);
5043 // Do it again to propagate the new nodes to places where they were not 5044 // Do it again to propagate the new nodes to places where they were not
5044 // put because they had not been calculated yet. 5045 // put because they had not been calculated yet.
5045 if (node != NULL) { 5046 if (node != NULL) {
5046 node = node->FilterOneByte(RegExpCompiler::kMaxRecursion, ignore_case); 5047 node = node->FilterOneByte(RegExpCompiler::kMaxRecursion, ignore_case);
5047 } 5048 }
5048 } 5049 }
5049 5050
5050 if (node == NULL) node = new(isolate) EndNode(EndNode::BACKTRACK, isolate); 5051 if (node == NULL) node = new(zone) EndNode(EndNode::BACKTRACK, zone);
5051 data->node = node; 5052 data->node = node;
5052 Analysis analysis(ignore_case, is_one_byte); 5053 Analysis analysis(ignore_case, is_one_byte);
5053 analysis.EnsureAnalyzed(node); 5054 analysis.EnsureAnalyzed(node);
5054 if (analysis.has_failed()) { 5055 if (analysis.has_failed()) {
5055 const char* error_message = analysis.error_message(); 5056 const char* error_message = analysis.error_message();
5056 return CompilationResult(error_message); 5057 return CompilationResult(error_message);
5057 } 5058 }
5058 5059
5059 // Native regexp implementation. 5060 // Native regexp implementation.
5060 5061
5061 IRRegExpMacroAssembler* macro_assembler = 5062 IRRegExpMacroAssembler* macro_assembler =
5062 new(isolate) IRRegExpMacroAssembler(specialization_cid, 5063 new(zone) IRRegExpMacroAssembler(specialization_cid,
5063 data->capture_count, 5064 data->capture_count,
5064 parsed_function, 5065 parsed_function,
5065 ic_data_array, 5066 ic_data_array,
5066 isolate); 5067 zone);
5067 5068
5068 // Inserted here, instead of in Assembler, because it depends on information 5069 // Inserted here, instead of in Assembler, because it depends on information
5069 // in the AST that isn't replicated in the Node structure. 5070 // in the AST that isn't replicated in the Node structure.
5070 static const intptr_t kMaxBacksearchLimit = 1024; 5071 static const intptr_t kMaxBacksearchLimit = 1024;
5071 if (is_end_anchored && 5072 if (is_end_anchored &&
5072 !is_start_anchored && 5073 !is_start_anchored &&
5073 max_length < kMaxBacksearchLimit) { 5074 max_length < kMaxBacksearchLimit) {
5074 macro_assembler->SetCurrentPositionFromEnd(max_length); 5075 macro_assembler->SetCurrentPositionFromEnd(max_length);
5075 } 5076 }
5076 5077
(...skipping 11 matching lines...) Expand all
5088 pattern); 5089 pattern);
5089 5090
5090 if (FLAG_trace_irregexp) { 5091 if (FLAG_trace_irregexp) {
5091 macro_assembler->PrintBlocks(); 5092 macro_assembler->PrintBlocks();
5092 } 5093 }
5093 5094
5094 return result; 5095 return result;
5095 } 5096 }
5096 5097
5097 5098
5098 static void CreateSpecializedFunction(Isolate* isolate, 5099 static void CreateSpecializedFunction(Zone* zone,
5099 const JSRegExp& regexp, 5100 const JSRegExp& regexp,
5100 intptr_t specialization_cid, 5101 intptr_t specialization_cid,
5101 const Object& owner) { 5102 const Object& owner) {
5102 const intptr_t kParamCount = RegExpMacroAssembler::kParamCount; 5103 const intptr_t kParamCount = RegExpMacroAssembler::kParamCount;
5103 5104
5104 Function& fn = Function::Handle(isolate, Function::New( 5105 Function& fn = Function::Handle(zone, Function::New(
5105 // Append the regexp pattern to the function name. 5106 // Append the regexp pattern to the function name.
5106 String::Handle(isolate, Symbols::New( 5107 String::Handle(zone, Symbols::New(
5107 String::Handle(isolate, String::Concat( 5108 String::Handle(zone, String::Concat(
5108 String::Handle(isolate, String::Concat( 5109 String::Handle(zone, String::Concat(
5109 Symbols::Irregexp(), 5110 Symbols::Irregexp(),
5110 Symbols::ColonSpace(), Heap::kOld)), 5111 Symbols::ColonSpace(), Heap::kOld)),
5111 String::Handle(regexp.pattern()), Heap::kOld)))), 5112 String::Handle(regexp.pattern()), Heap::kOld)))),
5112 RawFunction::kIrregexpFunction, 5113 RawFunction::kIrregexpFunction,
5113 true, // Static. 5114 true, // Static.
5114 false, // Not const. 5115 false, // Not const.
5115 false, // Not abstract. 5116 false, // Not abstract.
5116 false, // Not external. 5117 false, // Not external.
5117 false, // Not native. 5118 false, // Not native.
5118 owner, 5119 owner,
5119 0)); // No token position. 5120 0)); // No token position.
5120 5121
5121 // TODO(zerny): Share these arrays between all irregexp functions. 5122 // TODO(zerny): Share these arrays between all irregexp functions.
5122 fn.set_num_fixed_parameters(kParamCount); 5123 fn.set_num_fixed_parameters(kParamCount);
5123 fn.set_parameter_types(Array::Handle(isolate, Array::New(kParamCount, 5124 fn.set_parameter_types(Array::Handle(zone, Array::New(kParamCount,
5124 Heap::kOld))); 5125 Heap::kOld)));
5125 fn.set_parameter_names(Array::Handle(isolate, Array::New(kParamCount, 5126 fn.set_parameter_names(Array::Handle(zone, Array::New(kParamCount,
5126 Heap::kOld))); 5127 Heap::kOld)));
5127 fn.SetParameterTypeAt(0, Type::Handle(isolate, Type::DynamicType())); 5128 fn.SetParameterTypeAt(0, Type::Handle(zone, Type::DynamicType()));
5128 fn.SetParameterNameAt(0, Symbols::string_param()); 5129 fn.SetParameterNameAt(0, Symbols::string_param());
5129 fn.SetParameterTypeAt(1, Type::Handle(isolate, Type::DynamicType())); 5130 fn.SetParameterTypeAt(1, Type::Handle(zone, Type::DynamicType()));
5130 fn.SetParameterNameAt(1, Symbols::start_index_param()); 5131 fn.SetParameterNameAt(1, Symbols::start_index_param());
5131 fn.set_result_type(Type::Handle(isolate, Type::ArrayType())); 5132 fn.set_result_type(Type::Handle(zone, Type::ArrayType()));
5132 5133
5133 // Cache the result. 5134 // Cache the result.
5134 regexp.set_function(specialization_cid, fn); 5135 regexp.set_function(specialization_cid, fn);
5135 5136
5136 fn.set_regexp(regexp); 5137 fn.set_regexp(regexp);
5137 fn.set_regexp_cid(specialization_cid); 5138 fn.set_regexp_cid(specialization_cid);
5138 fn.set_is_debuggable(false); 5139 fn.set_is_debuggable(false);
5139 5140
5140 // The function is compiled lazily during the first call. 5141 // The function is compiled lazily during the first call.
5141 } 5142 }
5142 5143
5143 5144
5144 RawJSRegExp* RegExpEngine::CreateJSRegExp(Isolate* isolate, 5145 RawJSRegExp* RegExpEngine::CreateJSRegExp(Zone* zone,
5145 const String& pattern, 5146 const String& pattern,
5146 bool multi_line, 5147 bool multi_line,
5147 bool ignore_case) { 5148 bool ignore_case) {
5148 const JSRegExp& regexp = JSRegExp::Handle(JSRegExp::New(0)); 5149 const JSRegExp& regexp = JSRegExp::Handle(JSRegExp::New(0));
5149 5150
5150 regexp.set_pattern(pattern); 5151 regexp.set_pattern(pattern);
5151 5152
5152 if (multi_line) { 5153 if (multi_line) {
5153 regexp.set_is_multi_line(); 5154 regexp.set_is_multi_line();
5154 } 5155 }
5155 if (ignore_case) { 5156 if (ignore_case) {
5156 regexp.set_is_ignore_case(); 5157 regexp.set_is_ignore_case();
5157 } 5158 }
5158 5159
5159 // TODO(zerny): We might want to use normal string searching algorithms 5160 // TODO(zerny): We might want to use normal string searching algorithms
5160 // for simple patterns. 5161 // for simple patterns.
5161 regexp.set_is_complex(); 5162 regexp.set_is_complex();
5162 regexp.set_is_global(); // All dart regexps are global. 5163 regexp.set_is_global(); // All dart regexps are global.
5163 5164
5164 const Library& lib = Library::Handle(isolate, Library::CoreLibrary()); 5165 const Library& lib = Library::Handle(zone, Library::CoreLibrary());
5165 const Class& owner = Class::Handle( 5166 const Class& owner = Class::Handle(
5166 isolate, lib.LookupClass(Symbols::RegExp())); 5167 zone, lib.LookupClass(Symbols::RegExp()));
5167 5168
5168 CreateSpecializedFunction(isolate, regexp, kOneByteStringCid, owner); 5169 CreateSpecializedFunction(zone, regexp, kOneByteStringCid, owner);
5169 CreateSpecializedFunction(isolate, regexp, kTwoByteStringCid, owner); 5170 CreateSpecializedFunction(zone, regexp, kTwoByteStringCid, owner);
5170 CreateSpecializedFunction(isolate, regexp, kExternalOneByteStringCid, owner); 5171 CreateSpecializedFunction(zone, regexp, kExternalOneByteStringCid, owner);
5171 CreateSpecializedFunction(isolate, regexp, kExternalTwoByteStringCid, owner); 5172 CreateSpecializedFunction(zone, regexp, kExternalTwoByteStringCid, owner);
5172 5173
5173 return regexp.raw(); 5174 return regexp.raw();
5174 } 5175 }
5175 5176
5176 5177
5177 } // namespace dart 5178 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698