OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 ®isters_to_pop, | 652 ®isters_to_pop, |
653 ®isters_to_clear, | 653 ®isters_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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |