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

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

Powered by Google App Engine
This is Rietveld 408576698