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

Side by Side Diff: src/jsregexp.cc

Issue 7374002: Refactor allocation policies. Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 9 years, 5 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 | « src/jsregexp.h ('k') | src/list.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 2006-2009 the V8 project authors. All rights reserved. 1 // Copyright 2006-2009 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 778 matching lines...) Expand 10 before | Expand all | Expand 10 after
789 int TextElement::length() { 789 int TextElement::length() {
790 if (type == ATOM) { 790 if (type == ATOM) {
791 return data.u_atom->length(); 791 return data.u_atom->length();
792 } else { 792 } else {
793 ASSERT(type == CHAR_CLASS); 793 ASSERT(type == CHAR_CLASS);
794 return 1; 794 return 1;
795 } 795 }
796 } 796 }
797 797
798 798
799 DispatchTable* ChoiceNode::GetTable(bool ignore_case) { 799 DispatchTable* ChoiceNode::GetTable(Zone* zone, bool ignore_case) {
800 if (table_ == NULL) { 800 if (table_ == NULL) {
801 table_ = new DispatchTable(); 801 table_ = new DispatchTable(zone);
802 DispatchTableConstructor cons(table_, ignore_case); 802 DispatchTableConstructor cons(zone, table_, ignore_case);
803 cons.BuildTable(this); 803 cons.BuildTable(this);
804 } 804 }
805 return table_; 805 return table_;
806 } 806 }
807 807
808 808
809 class RegExpCompiler { 809 class RegExpCompiler {
810 public: 810 public:
811 RegExpCompiler(int capture_count, bool ignore_case, bool is_ascii); 811 RegExpCompiler(Isolate* isolate,
812 int capture_count,
813 bool ignore_case,
814 bool is_ascii);
815
816 Isolate* isolate() { return isolate_; }
817 Zone* zone() { return isolate()->zone(); }
812 818
813 int AllocateRegister() { 819 int AllocateRegister() {
814 if (next_register_ >= RegExpMacroAssembler::kMaxRegister) { 820 if (next_register_ >= RegExpMacroAssembler::kMaxRegister) {
815 reg_exp_too_big_ = true; 821 reg_exp_too_big_ = true;
816 return next_register_; 822 return next_register_;
817 } 823 }
818 return next_register_++; 824 return next_register_++;
819 } 825 }
820 826
821 RegExpEngine::CompilationResult Assemble(RegExpMacroAssembler* assembler, 827 RegExpEngine::CompilationResult Assemble(RegExpMacroAssembler* assembler,
(...skipping 21 matching lines...) Expand all
843 inline bool ascii() { return ascii_; } 849 inline bool ascii() { return ascii_; }
844 850
845 int current_expansion_factor() { return current_expansion_factor_; } 851 int current_expansion_factor() { return current_expansion_factor_; }
846 void set_current_expansion_factor(int value) { 852 void set_current_expansion_factor(int value) {
847 current_expansion_factor_ = value; 853 current_expansion_factor_ = value;
848 } 854 }
849 855
850 static const int kNoRegister = -1; 856 static const int kNoRegister = -1;
851 857
852 private: 858 private:
859 Isolate* isolate_;
853 EndNode* accept_; 860 EndNode* accept_;
854 int next_register_; 861 int next_register_;
855 List<RegExpNode*>* work_list_; 862 List<RegExpNode*>* work_list_;
856 int recursion_depth_; 863 int recursion_depth_;
857 RegExpMacroAssembler* macro_assembler_; 864 RegExpMacroAssembler* macro_assembler_;
858 bool ignore_case_; 865 bool ignore_case_;
859 bool ascii_; 866 bool ascii_;
860 bool reg_exp_too_big_; 867 bool reg_exp_too_big_;
861 int current_expansion_factor_; 868 int current_expansion_factor_;
862 }; 869 };
(...skipping 10 matching lines...) Expand all
873 }; 880 };
874 881
875 882
876 static RegExpEngine::CompilationResult IrregexpRegExpTooBig() { 883 static RegExpEngine::CompilationResult IrregexpRegExpTooBig() {
877 return RegExpEngine::CompilationResult("RegExp too big"); 884 return RegExpEngine::CompilationResult("RegExp too big");
878 } 885 }
879 886
880 887
881 // Attempts to compile the regexp using an Irregexp code generator. Returns 888 // Attempts to compile the regexp using an Irregexp code generator. Returns
882 // a fixed array or a null handle depending on whether it succeeded. 889 // a fixed array or a null handle depending on whether it succeeded.
883 RegExpCompiler::RegExpCompiler(int capture_count, bool ignore_case, bool ascii) 890 RegExpCompiler::RegExpCompiler(Isolate* isolate,
884 : next_register_(2 * (capture_count + 1)), 891 int capture_count,
892 bool ignore_case,
893 bool ascii)
894 : isolate_(isolate),
895 next_register_(2 * (capture_count + 1)),
885 work_list_(NULL), 896 work_list_(NULL),
886 recursion_depth_(0), 897 recursion_depth_(0),
887 ignore_case_(ignore_case), 898 ignore_case_(ignore_case),
888 ascii_(ascii), 899 ascii_(ascii),
889 reg_exp_too_big_(false), 900 reg_exp_too_big_(false),
890 current_expansion_factor_(1) { 901 current_expansion_factor_(1) {
891 accept_ = new EndNode(EndNode::ACCEPT); 902 accept_ = new EndNode(EndNode::ACCEPT);
892 ASSERT(next_register_ - 1 <= RegExpMacroAssembler::kMaxRegister); 903 ASSERT(next_register_ - 1 <= RegExpMacroAssembler::kMaxRegister);
893 } 904 }
894 905
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
977 return true; 988 return true;
978 } else { 989 } else {
979 return false; 990 return false;
980 } 991 }
981 } 992 }
982 } 993 }
983 return false; 994 return false;
984 } 995 }
985 996
986 997
987 int Trace::FindAffectedRegisters(OutSet* affected_registers) { 998 int Trace::FindAffectedRegisters(Zone* zone, OutSet* affected_registers) {
988 int max_register = RegExpCompiler::kNoRegister; 999 int max_register = RegExpCompiler::kNoRegister;
989 for (DeferredAction* action = actions_; 1000 for (DeferredAction* action = actions_;
990 action != NULL; 1001 action != NULL;
991 action = action->next()) { 1002 action = action->next()) {
992 if (action->type() == ActionNode::CLEAR_CAPTURES) { 1003 if (action->type() == ActionNode::CLEAR_CAPTURES) {
993 Interval range = static_cast<DeferredClearCaptures*>(action)->range(); 1004 Interval range = static_cast<DeferredClearCaptures*>(action)->range();
994 for (int i = range.from(); i <= range.to(); i++) 1005 for (int i = range.from(); i <= range.to(); i++) {
995 affected_registers->Set(i); 1006 affected_registers->Set(zone, i);
1007 }
996 if (range.to() > max_register) max_register = range.to(); 1008 if (range.to() > max_register) max_register = range.to();
997 } else { 1009 } else {
998 affected_registers->Set(action->reg()); 1010 affected_registers->Set(zone, action->reg());
999 if (action->reg() > max_register) max_register = action->reg(); 1011 if (action->reg() > max_register) max_register = action->reg();
1000 } 1012 }
1001 } 1013 }
1002 return max_register; 1014 return max_register;
1003 } 1015 }
1004 1016
1005 1017
1006 void Trace::RestoreAffectedRegisters(RegExpMacroAssembler* assembler, 1018 void Trace::RestoreAffectedRegisters(RegExpMacroAssembler* assembler,
1007 int max_register, 1019 int max_register,
1008 OutSet& registers_to_pop, 1020 OutSet& registers_to_pop,
1009 OutSet& registers_to_clear) { 1021 OutSet& registers_to_clear) {
1010 for (int reg = max_register; reg >= 0; reg--) { 1022 for (int reg = max_register; reg >= 0; reg--) {
1011 if (registers_to_pop.Get(reg)) assembler->PopRegister(reg); 1023 if (registers_to_pop.Get(reg)) assembler->PopRegister(reg);
1012 else if (registers_to_clear.Get(reg)) { 1024 else if (registers_to_clear.Get(reg)) {
1013 int clear_to = reg; 1025 int clear_to = reg;
1014 while (reg > 0 && registers_to_clear.Get(reg - 1)) { 1026 while (reg > 0 && registers_to_clear.Get(reg - 1)) {
1015 reg--; 1027 reg--;
1016 } 1028 }
1017 assembler->ClearRegisters(reg, clear_to); 1029 assembler->ClearRegisters(reg, clear_to);
1018 } 1030 }
1019 } 1031 }
1020 } 1032 }
1021 1033
1022 1034
1023 void Trace::PerformDeferredActions(RegExpMacroAssembler* assembler, 1035 void Trace::PerformDeferredActions(Zone* zone,
1036 RegExpMacroAssembler* assembler,
1024 int max_register, 1037 int max_register,
1025 OutSet& affected_registers, 1038 OutSet& affected_registers,
1026 OutSet* registers_to_pop, 1039 OutSet* registers_to_pop,
1027 OutSet* registers_to_clear) { 1040 OutSet* registers_to_clear) {
1028 // The "+1" is to avoid a push_limit of zero if stack_limit_slack() is 1. 1041 // The "+1" is to avoid a push_limit of zero if stack_limit_slack() is 1.
1029 const int push_limit = (assembler->stack_limit_slack() + 1) / 2; 1042 const int push_limit = (assembler->stack_limit_slack() + 1) / 2;
1030 1043
1031 // Count pushes performed to force a stack limit check occasionally. 1044 // Count pushes performed to force a stack limit check occasionally.
1032 int pushes = 0; 1045 int pushes = 0;
1033 1046
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
1123 if (undo_action == RESTORE) { 1136 if (undo_action == RESTORE) {
1124 pushes++; 1137 pushes++;
1125 RegExpMacroAssembler::StackCheckFlag stack_check = 1138 RegExpMacroAssembler::StackCheckFlag stack_check =
1126 RegExpMacroAssembler::kNoStackLimitCheck; 1139 RegExpMacroAssembler::kNoStackLimitCheck;
1127 if (pushes == push_limit) { 1140 if (pushes == push_limit) {
1128 stack_check = RegExpMacroAssembler::kCheckStackLimit; 1141 stack_check = RegExpMacroAssembler::kCheckStackLimit;
1129 pushes = 0; 1142 pushes = 0;
1130 } 1143 }
1131 1144
1132 assembler->PushRegister(reg, stack_check); 1145 assembler->PushRegister(reg, stack_check);
1133 registers_to_pop->Set(reg); 1146 registers_to_pop->Set(zone, reg);
1134 } else if (undo_action == CLEAR) { 1147 } else if (undo_action == CLEAR) {
1135 registers_to_clear->Set(reg); 1148 registers_to_clear->Set(zone, reg);
1136 } 1149 }
1137 // Perform the chronologically last action (or accumulated increment) 1150 // Perform the chronologically last action (or accumulated increment)
1138 // for the register. 1151 // for the register.
1139 if (store_position != -1) { 1152 if (store_position != -1) {
1140 assembler->WriteCurrentPositionToRegister(reg, store_position); 1153 assembler->WriteCurrentPositionToRegister(reg, store_position);
1141 } else if (clear) { 1154 } else if (clear) {
1142 assembler->ClearRegisters(reg, reg); 1155 assembler->ClearRegisters(reg, reg);
1143 } else if (absolute) { 1156 } else if (absolute) {
1144 assembler->SetRegister(reg, value); 1157 assembler->SetRegister(reg, value);
1145 } else if (value != 0) { 1158 } else if (value != 0) {
(...skipping 25 matching lines...) Expand all
1171 // Generate deferred actions here along with code to undo them again. 1184 // Generate deferred actions here along with code to undo them again.
1172 OutSet affected_registers; 1185 OutSet affected_registers;
1173 1186
1174 if (backtrack() != NULL) { 1187 if (backtrack() != NULL) {
1175 // Here we have a concrete backtrack location. These are set up by choice 1188 // Here we have a concrete backtrack location. These are set up by choice
1176 // nodes and so they indicate that we have a deferred save of the current 1189 // nodes and so they indicate that we have a deferred save of the current
1177 // position which we may need to emit here. 1190 // position which we may need to emit here.
1178 assembler->PushCurrentPosition(); 1191 assembler->PushCurrentPosition();
1179 } 1192 }
1180 1193
1181 int max_register = FindAffectedRegisters(&affected_registers); 1194 int max_register = FindAffectedRegisters(compiler->zone(),
1195 &affected_registers);
1182 OutSet registers_to_pop; 1196 OutSet registers_to_pop;
1183 OutSet registers_to_clear; 1197 OutSet registers_to_clear;
1184 PerformDeferredActions(assembler, 1198 PerformDeferredActions(compiler->zone(),
1199 assembler,
1185 max_register, 1200 max_register,
1186 affected_registers, 1201 affected_registers,
1187 &registers_to_pop, 1202 &registers_to_pop,
1188 &registers_to_clear); 1203 &registers_to_clear);
1189 if (cp_offset_ != 0) { 1204 if (cp_offset_ != 0) {
1190 assembler->AdvanceCurrentPosition(cp_offset_); 1205 assembler->AdvanceCurrentPosition(cp_offset_);
1191 } 1206 }
1192 1207
1193 // Create a new trivial state and generate the node with that. 1208 // Create a new trivial state and generate the node with that.
1194 Label undo; 1209 Label undo;
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
1255 assembler->GoTo(trace->backtrack()); 1270 assembler->GoTo(trace->backtrack());
1256 return; 1271 return;
1257 case NEGATIVE_SUBMATCH_SUCCESS: 1272 case NEGATIVE_SUBMATCH_SUCCESS:
1258 // This case is handled in a different virtual method. 1273 // This case is handled in a different virtual method.
1259 UNREACHABLE(); 1274 UNREACHABLE();
1260 } 1275 }
1261 UNIMPLEMENTED(); 1276 UNIMPLEMENTED();
1262 } 1277 }
1263 1278
1264 1279
1265 void GuardedAlternative::AddGuard(Guard* guard) { 1280 void GuardedAlternative::AddGuard(Zone* zone, Guard* guard) {
1266 if (guards_ == NULL) 1281 if (guards_ == NULL)
1267 guards_ = new ZoneList<Guard*>(1); 1282 guards_ = ZoneList<Guard*>::New(zone, 1);
1268 guards_->Add(guard); 1283 guards_->Add(guard);
1269 } 1284 }
1270 1285
1271 1286
1272 ActionNode* ActionNode::SetRegister(int reg, 1287 ActionNode* ActionNode::SetRegister(int reg,
1273 int val, 1288 int val,
1274 RegExpNode* on_success) { 1289 RegExpNode* on_success) {
1275 ActionNode* result = new ActionNode(SET_REGISTER, on_success); 1290 ActionNode* result = new ActionNode(SET_REGISTER, on_success);
1276 result->data_.u_store_register.reg = reg; 1291 result->data_.u_store_register.reg = reg;
1277 result->data_.u_store_register.value = val; 1292 result->data_.u_store_register.value = val;
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after
1549 macro_assembler->Bind(&ok); 1564 macro_assembler->Bind(&ok);
1550 break; 1565 break;
1551 default: 1566 default:
1552 UNREACHABLE(); 1567 UNREACHABLE();
1553 break; 1568 break;
1554 } 1569 }
1555 return true; 1570 return true;
1556 } 1571 }
1557 1572
1558 1573
1559 static void EmitCharClass(RegExpMacroAssembler* macro_assembler, 1574 static void EmitCharClass(Zone* zone,
1575 RegExpMacroAssembler* macro_assembler,
1560 RegExpCharacterClass* cc, 1576 RegExpCharacterClass* cc,
1561 bool ascii, 1577 bool ascii,
1562 Label* on_failure, 1578 Label* on_failure,
1563 int cp_offset, 1579 int cp_offset,
1564 bool check_offset, 1580 bool check_offset,
1565 bool preloaded) { 1581 bool preloaded) {
1566 ZoneList<CharacterRange>* ranges = cc->ranges(); 1582 ZoneList<CharacterRange>* ranges = cc->ranges(zone);
1567 int max_char; 1583 int max_char;
1568 if (ascii) { 1584 if (ascii) {
1569 max_char = String::kMaxAsciiCharCode; 1585 max_char = String::kMaxAsciiCharCode;
1570 } else { 1586 } else {
1571 max_char = String::kMaxUC16CharCode; 1587 max_char = String::kMaxUC16CharCode;
1572 } 1588 }
1573 1589
1574 Label success; 1590 Label success;
1575 1591
1576 Label* char_is_in_class = 1592 Label* char_is_in_class =
(...skipping 29 matching lines...) Expand all
1606 if (check_offset) { 1622 if (check_offset) {
1607 macro_assembler->CheckPosition(cp_offset, on_failure); 1623 macro_assembler->CheckPosition(cp_offset, on_failure);
1608 } 1624 }
1609 return; 1625 return;
1610 } 1626 }
1611 1627
1612 if (!preloaded) { 1628 if (!preloaded) {
1613 macro_assembler->LoadCurrentCharacter(cp_offset, on_failure, check_offset); 1629 macro_assembler->LoadCurrentCharacter(cp_offset, on_failure, check_offset);
1614 } 1630 }
1615 1631
1616 if (cc->is_standard() && 1632 if (cc->is_standard(zone) &&
1617 macro_assembler->CheckSpecialCharacterClass(cc->standard_type(), 1633 macro_assembler->CheckSpecialCharacterClass(cc->standard_type(),
1618 on_failure)) { 1634 on_failure)) {
1619 return; 1635 return;
1620 } 1636 }
1621 1637
1622 for (int i = 0; i < last_valid_range; i++) { 1638 for (int i = 0; i < last_valid_range; i++) {
1623 CharacterRange& range = ranges->at(i); 1639 CharacterRange& range = ranges->at(i);
1624 Label next_range; 1640 Label next_range;
1625 uc16 from = range.from(); 1641 uc16 from = range.from();
1626 uc16 to = range.to(); 1642 uc16 to = range.to();
1627 if (from > max_char) { 1643 if (from > max_char) {
1628 continue; 1644 continue;
(...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after
1947 // 1963 //
1948 // We iterate along the text object, building up for each character a 1964 // We iterate along the text object, building up for each character a
1949 // mask and value that can be used to test for a quick failure to match. 1965 // mask and value that can be used to test for a quick failure to match.
1950 // The masks and values for the positions will be combined into a single 1966 // The masks and values for the positions will be combined into a single
1951 // machine word for the current character width in order to be used in 1967 // machine word for the current character width in order to be used in
1952 // generating a quick check. 1968 // generating a quick check.
1953 void TextNode::GetQuickCheckDetails(QuickCheckDetails* details, 1969 void TextNode::GetQuickCheckDetails(QuickCheckDetails* details,
1954 RegExpCompiler* compiler, 1970 RegExpCompiler* compiler,
1955 int characters_filled_in, 1971 int characters_filled_in,
1956 bool not_at_start) { 1972 bool not_at_start) {
1957 Isolate* isolate = Isolate::Current(); 1973 Isolate* isolate = compiler->isolate();
1958 ASSERT(characters_filled_in < details->characters()); 1974 ASSERT(characters_filled_in < details->characters());
1959 int characters = details->characters(); 1975 int characters = details->characters();
1960 int char_mask; 1976 int char_mask;
1961 int char_shift; 1977 int char_shift;
1962 if (compiler->ascii()) { 1978 if (compiler->ascii()) {
1963 char_mask = String::kMaxAsciiCharCode; 1979 char_mask = String::kMaxAsciiCharCode;
1964 char_shift = 8; 1980 char_shift = 8;
1965 } else { 1981 } else {
1966 char_mask = String::kMaxUC16CharCode; 1982 char_mask = String::kMaxUC16CharCode;
1967 char_shift = 16; 1983 char_shift = 16;
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
2025 characters_filled_in++; 2041 characters_filled_in++;
2026 ASSERT(characters_filled_in <= details->characters()); 2042 ASSERT(characters_filled_in <= details->characters());
2027 if (characters_filled_in == details->characters()) { 2043 if (characters_filled_in == details->characters()) {
2028 return; 2044 return;
2029 } 2045 }
2030 } 2046 }
2031 } else { 2047 } else {
2032 QuickCheckDetails::Position* pos = 2048 QuickCheckDetails::Position* pos =
2033 details->positions(characters_filled_in); 2049 details->positions(characters_filled_in);
2034 RegExpCharacterClass* tree = elm.data.u_char_class; 2050 RegExpCharacterClass* tree = elm.data.u_char_class;
2035 ZoneList<CharacterRange>* ranges = tree->ranges(); 2051 ZoneList<CharacterRange>* ranges = tree->ranges(isolate->zone());
2036 if (tree->is_negated()) { 2052 if (tree->is_negated()) {
2037 // A quick check uses multi-character mask and compare. There is no 2053 // A quick check uses multi-character mask and compare. There is no
2038 // useful way to incorporate a negative char class into this scheme 2054 // useful way to incorporate a negative char class into this scheme
2039 // so we just conservatively create a mask and value that will always 2055 // so we just conservatively create a mask and value that will always
2040 // succeed. 2056 // succeed.
2041 pos->mask = 0; 2057 pos->mask = 0;
2042 pos->value = 0; 2058 pos->value = 0;
2043 } else { 2059 } else {
2044 int first_range = 0; 2060 int first_range = 0;
2045 while (ranges->at(first_range).from() > char_mask) { 2061 while (ranges->at(first_range).from() > char_mask) {
(...skipping 433 matching lines...) Expand 10 before | Expand all | Expand 10 after
2479 // loading characters, which means we do not need to recheck the bounds 2495 // loading characters, which means we do not need to recheck the bounds
2480 // up to the limit the quick check already checked. In addition the quick 2496 // up to the limit the quick check already checked. In addition the quick
2481 // check can have involved a mask and compare operation which may simplify 2497 // check can have involved a mask and compare operation which may simplify
2482 // or obviate the need for further checks at some character positions. 2498 // or obviate the need for further checks at some character positions.
2483 void TextNode::TextEmitPass(RegExpCompiler* compiler, 2499 void TextNode::TextEmitPass(RegExpCompiler* compiler,
2484 TextEmitPassType pass, 2500 TextEmitPassType pass,
2485 bool preloaded, 2501 bool preloaded,
2486 Trace* trace, 2502 Trace* trace,
2487 bool first_element_checked, 2503 bool first_element_checked,
2488 int* checked_up_to) { 2504 int* checked_up_to) {
2489 Isolate* isolate = Isolate::Current(); 2505 Isolate* isolate = compiler->isolate();
2490 RegExpMacroAssembler* assembler = compiler->macro_assembler(); 2506 RegExpMacroAssembler* assembler = compiler->macro_assembler();
2491 bool ascii = compiler->ascii(); 2507 bool ascii = compiler->ascii();
2492 Label* backtrack = trace->backtrack(); 2508 Label* backtrack = trace->backtrack();
2493 QuickCheckDetails* quick_check = trace->quick_check_performed(); 2509 QuickCheckDetails* quick_check = trace->quick_check_performed();
2494 int element_count = elms_->length(); 2510 int element_count = elms_->length();
2495 for (int i = preloaded ? 0 : element_count - 1; i >= 0; i--) { 2511 for (int i = preloaded ? 0 : element_count - 1; i >= 0; i--) {
2496 TextElement elm = elms_->at(i); 2512 TextElement elm = elms_->at(i);
2497 int cp_offset = trace->cp_offset() + elm.cp_offset; 2513 int cp_offset = trace->cp_offset() + elm.cp_offset;
2498 if (elm.type == TextElement::ATOM) { 2514 if (elm.type == TextElement::ATOM) {
2499 Vector<const uc16> quarks = elm.data.u_atom->data(); 2515 Vector<const uc16> quarks = elm.data.u_atom->data();
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
2531 preloaded); 2547 preloaded);
2532 if (bound_checked) UpdateBoundsCheck(cp_offset + j, checked_up_to); 2548 if (bound_checked) UpdateBoundsCheck(cp_offset + j, checked_up_to);
2533 } 2549 }
2534 } 2550 }
2535 } else { 2551 } else {
2536 ASSERT_EQ(elm.type, TextElement::CHAR_CLASS); 2552 ASSERT_EQ(elm.type, TextElement::CHAR_CLASS);
2537 if (pass == CHARACTER_CLASS_MATCH) { 2553 if (pass == CHARACTER_CLASS_MATCH) {
2538 if (first_element_checked && i == 0) continue; 2554 if (first_element_checked && i == 0) continue;
2539 if (DeterminedAlready(quick_check, elm.cp_offset)) continue; 2555 if (DeterminedAlready(quick_check, elm.cp_offset)) continue;
2540 RegExpCharacterClass* cc = elm.data.u_char_class; 2556 RegExpCharacterClass* cc = elm.data.u_char_class;
2541 EmitCharClass(assembler, 2557 EmitCharClass(compiler->zone(),
2558 assembler,
2542 cc, 2559 cc,
2543 ascii, 2560 ascii,
2544 backtrack, 2561 backtrack,
2545 cp_offset, 2562 cp_offset,
2546 *checked_up_to < cp_offset, 2563 *checked_up_to < cp_offset,
2547 preloaded); 2564 preloaded);
2548 UpdateBoundsCheck(cp_offset, checked_up_to); 2565 UpdateBoundsCheck(cp_offset, checked_up_to);
2549 } 2566 }
2550 } 2567 }
2551 } 2568 }
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
2650 quick_check_performed_.Advance(by, compiler->ascii()); 2667 quick_check_performed_.Advance(by, compiler->ascii());
2651 cp_offset_ += by; 2668 cp_offset_ += by;
2652 if (cp_offset_ > RegExpMacroAssembler::kMaxCPOffset) { 2669 if (cp_offset_ > RegExpMacroAssembler::kMaxCPOffset) {
2653 compiler->SetRegExpTooBig(); 2670 compiler->SetRegExpTooBig();
2654 cp_offset_ = 0; 2671 cp_offset_ = 0;
2655 } 2672 }
2656 bound_checked_up_to_ = Max(0, bound_checked_up_to_ - by); 2673 bound_checked_up_to_ = Max(0, bound_checked_up_to_ - by);
2657 } 2674 }
2658 2675
2659 2676
2660 void TextNode::MakeCaseIndependent(bool is_ascii) { 2677 void TextNode::MakeCaseIndependent(Zone* zone, bool is_ascii) {
2661 int element_count = elms_->length(); 2678 int element_count = elms_->length();
2662 for (int i = 0; i < element_count; i++) { 2679 for (int i = 0; i < element_count; i++) {
2663 TextElement elm = elms_->at(i); 2680 TextElement elm = elms_->at(i);
2664 if (elm.type == TextElement::CHAR_CLASS) { 2681 if (elm.type == TextElement::CHAR_CLASS) {
2665 RegExpCharacterClass* cc = elm.data.u_char_class; 2682 RegExpCharacterClass* cc = elm.data.u_char_class;
2666 // None of the standard character classses is different in the case 2683 // None of the standard character classses is different in the case
2667 // independent case and it slows us down if we don't know that. 2684 // independent case and it slows us down if we don't know that.
2668 if (cc->is_standard()) continue; 2685 if (cc->is_standard(zone)) continue;
2669 ZoneList<CharacterRange>* ranges = cc->ranges(); 2686 ZoneList<CharacterRange>* ranges = cc->ranges(zone);
2670 int range_count = ranges->length(); 2687 int range_count = ranges->length();
2671 for (int j = 0; j < range_count; j++) { 2688 for (int j = 0; j < range_count; j++) {
2672 ranges->at(j).AddCaseEquivalents(ranges, is_ascii); 2689 ranges->at(j).AddCaseEquivalents(ranges, is_ascii);
2673 } 2690 }
2674 } 2691 }
2675 } 2692 }
2676 } 2693 }
2677 2694
2678 2695
2679 int TextNode::GreedyLoopTextLength() { 2696 int TextNode::GreedyLoopTextLength() {
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
2781 bool expects_preload; 2798 bool expects_preload;
2782 Label after; 2799 Label after;
2783 QuickCheckDetails quick_check_details; 2800 QuickCheckDetails quick_check_details;
2784 }; 2801 };
2785 2802
2786 2803
2787 // Creates a list of AlternativeGenerations. If the list has a reasonable 2804 // Creates a list of AlternativeGenerations. If the list has a reasonable
2788 // size then it is on the stack, otherwise the excess is on the heap. 2805 // size then it is on the stack, otherwise the excess is on the heap.
2789 class AlternativeGenerationList { 2806 class AlternativeGenerationList {
2790 public: 2807 public:
2791 explicit AlternativeGenerationList(int count) 2808 AlternativeGenerationList(Zone* zone, int count)
2792 : alt_gens_(count) { 2809 : alt_gens_(zone, count) {
2793 for (int i = 0; i < count && i < kAFew; i++) { 2810 for (int i = 0; i < count && i < kAFew; i++) {
2794 alt_gens_.Add(a_few_alt_gens_ + i); 2811 alt_gens_.Add(a_few_alt_gens_ + i);
2795 } 2812 }
2796 for (int i = kAFew; i < count; i++) { 2813 for (int i = kAFew; i < count; i++) {
2797 alt_gens_.Add(new AlternativeGeneration()); 2814 alt_gens_.Add(new AlternativeGeneration());
2798 } 2815 }
2799 } 2816 }
2800 ~AlternativeGenerationList() { 2817 ~AlternativeGenerationList() {
2801 for (int i = kAFew; i < alt_gens_.length(); i++) { 2818 for (int i = kAFew; i < alt_gens_.length(); i++) {
2802 delete alt_gens_[i]; 2819 delete alt_gens_[i];
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
2958 2975
2959 int first_normal_choice = greedy_loop ? 1 : 0; 2976 int first_normal_choice = greedy_loop ? 1 : 0;
2960 2977
2961 int preload_characters = 2978 int preload_characters =
2962 CalculatePreloadCharacters(compiler, 2979 CalculatePreloadCharacters(compiler,
2963 current_trace->at_start() == Trace::FALSE); 2980 current_trace->at_start() == Trace::FALSE);
2964 bool preload_is_current = 2981 bool preload_is_current =
2965 (current_trace->characters_preloaded() == preload_characters); 2982 (current_trace->characters_preloaded() == preload_characters);
2966 bool preload_has_checked_bounds = preload_is_current; 2983 bool preload_has_checked_bounds = preload_is_current;
2967 2984
2968 AlternativeGenerationList alt_gens(choice_count); 2985 AlternativeGenerationList alt_gens(compiler->zone(), choice_count);
2969 2986
2970 // For now we just call all choices one after the other. The idea ultimately 2987 // For now we just call all choices one after the other. The idea ultimately
2971 // is to use the Dispatch table to try only the relevant ones. 2988 // is to use the Dispatch table to try only the relevant ones.
2972 for (int i = first_normal_choice; i < choice_count; i++) { 2989 for (int i = first_normal_choice; i < choice_count; i++) {
2973 GuardedAlternative alternative = alternatives_->at(i); 2990 GuardedAlternative alternative = alternatives_->at(i);
2974 AlternativeGeneration* alt_gen = alt_gens.at(i); 2991 AlternativeGeneration* alt_gen = alt_gens.at(i);
2975 alt_gen->quick_check_details.set_characters(preload_characters); 2992 alt_gen->quick_check_details.set_characters(preload_characters);
2976 ZoneList<Guard*>* guards = alternative.guards(); 2993 ZoneList<Guard*>* guards = alternative.guards();
2977 int guard_count = (guards == NULL) ? 0 : guards->length(); 2994 int guard_count = (guards == NULL) ? 0 : guards->length();
2978 Trace new_trace(*current_trace); 2995 Trace new_trace(*current_trace);
(...skipping 439 matching lines...) Expand 10 before | Expand all | Expand 10 after
3418 stream()->Add(" a%p -> n%p [style=dashed, color=grey, " 3435 stream()->Add(" a%p -> n%p [style=dashed, color=grey, "
3419 "arrowhead=none];\n", that, that); 3436 "arrowhead=none];\n", that, that);
3420 } 3437 }
3421 3438
3422 3439
3423 static const bool kPrintDispatchTable = false; 3440 static const bool kPrintDispatchTable = false;
3424 void DotPrinter::VisitChoice(ChoiceNode* that) { 3441 void DotPrinter::VisitChoice(ChoiceNode* that) {
3425 if (kPrintDispatchTable) { 3442 if (kPrintDispatchTable) {
3426 stream()->Add(" n%p [shape=Mrecord, label=\"", that); 3443 stream()->Add(" n%p [shape=Mrecord, label=\"", that);
3427 TableEntryHeaderPrinter header_printer(stream()); 3444 TableEntryHeaderPrinter header_printer(stream());
3428 that->GetTable(ignore_case_)->ForEach(&header_printer); 3445 that->GetTable(ZONE, ignore_case_)->ForEach(&header_printer);
3429 stream()->Add("\"]\n", that); 3446 stream()->Add("\"]\n", that);
3430 PrintAttributes(that); 3447 PrintAttributes(that);
3431 TableEntryBodyPrinter body_printer(stream(), that); 3448 TableEntryBodyPrinter body_printer(stream(), that);
3432 that->GetTable(ignore_case_)->ForEach(&body_printer); 3449 that->GetTable(ZONE, ignore_case_)->ForEach(&body_printer);
3433 } else { 3450 } else {
3434 stream()->Add(" n%p [shape=Mrecord, label=\"?\"];\n", that); 3451 stream()->Add(" n%p [shape=Mrecord, label=\"?\"];\n", that);
3435 for (int i = 0; i < that->alternatives()->length(); i++) { 3452 for (int i = 0; i < that->alternatives()->length(); i++) {
3436 GuardedAlternative alt = that->alternatives()->at(i); 3453 GuardedAlternative alt = that->alternatives()->at(i);
3437 stream()->Add(" n%p -> n%p;\n", that, alt.node()); 3454 stream()->Add(" n%p -> n%p;\n", that, alt.node());
3438 } 3455 }
3439 } 3456 }
3440 for (int i = 0; i < that->alternatives()->length(); i++) { 3457 for (int i = 0; i < that->alternatives()->length(); i++) {
3441 GuardedAlternative alt = that->alternatives()->at(i); 3458 GuardedAlternative alt = that->alternatives()->at(i);
3442 alt.node()->Accept(this); 3459 alt.node()->Accept(this);
3443 } 3460 }
3444 } 3461 }
3445 3462
3446 3463
3447 void DotPrinter::VisitText(TextNode* that) { 3464 void DotPrinter::VisitText(TextNode* that) {
3448 stream()->Add(" n%p [label=\"", that); 3465 stream()->Add(" n%p [label=\"", that);
3449 for (int i = 0; i < that->elements()->length(); i++) { 3466 for (int i = 0; i < that->elements()->length(); i++) {
3450 if (i > 0) stream()->Add(" "); 3467 if (i > 0) stream()->Add(" ");
3451 TextElement elm = that->elements()->at(i); 3468 TextElement elm = that->elements()->at(i);
3452 switch (elm.type) { 3469 switch (elm.type) {
3453 case TextElement::ATOM: { 3470 case TextElement::ATOM: {
3454 stream()->Add("'%w'", elm.data.u_atom->data()); 3471 stream()->Add("'%w'", elm.data.u_atom->data());
3455 break; 3472 break;
3456 } 3473 }
3457 case TextElement::CHAR_CLASS: { 3474 case TextElement::CHAR_CLASS: {
3458 RegExpCharacterClass* node = elm.data.u_char_class; 3475 RegExpCharacterClass* node = elm.data.u_char_class;
3459 stream()->Add("["); 3476 stream()->Add("[");
3460 if (node->is_negated()) 3477 if (node->is_negated())
3461 stream()->Add("^"); 3478 stream()->Add("^");
3462 for (int j = 0; j < node->ranges()->length(); j++) { 3479 Zone* zone = ZONE;
3463 CharacterRange range = node->ranges()->at(j); 3480 for (int j = 0; j < node->ranges(zone)->length(); j++) {
3481 CharacterRange range = node->ranges(zone)->at(j);
3464 stream()->Add("%k-%k", range.from(), range.to()); 3482 stream()->Add("%k-%k", range.from(), range.to());
3465 } 3483 }
3466 stream()->Add("]"); 3484 stream()->Add("]");
3467 break; 3485 break;
3468 } 3486 }
3469 default: 3487 default:
3470 UNREACHABLE(); 3488 UNREACHABLE();
3471 } 3489 }
3472 } 3490 }
3473 stream()->Add("\", shape=box, peripheries=2];\n"); 3491 stream()->Add("\", shape=box, peripheries=2];\n");
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
3634 3652
3635 static const int kDigitRangeCount = 2; 3653 static const int kDigitRangeCount = 2;
3636 static const uc16 kDigitRanges[kDigitRangeCount] = { '0', '9' }; 3654 static const uc16 kDigitRanges[kDigitRangeCount] = { '0', '9' };
3637 3655
3638 static const int kLineTerminatorRangeCount = 6; 3656 static const int kLineTerminatorRangeCount = 6;
3639 static const uc16 kLineTerminatorRanges[kLineTerminatorRangeCount] = { 0x000A, 3657 static const uc16 kLineTerminatorRanges[kLineTerminatorRangeCount] = { 0x000A,
3640 0x000A, 0x000D, 0x000D, 0x2028, 0x2029 }; 3658 0x000A, 0x000D, 0x000D, 0x2028, 0x2029 };
3641 3659
3642 RegExpNode* RegExpAtom::ToNode(RegExpCompiler* compiler, 3660 RegExpNode* RegExpAtom::ToNode(RegExpCompiler* compiler,
3643 RegExpNode* on_success) { 3661 RegExpNode* on_success) {
3644 ZoneList<TextElement>* elms = new ZoneList<TextElement>(1); 3662 ZoneList<TextElement>* elms = ZoneList<TextElement>::New(compiler->zone(), 1);
3645 elms->Add(TextElement::Atom(this)); 3663 elms->Add(TextElement::Atom(this));
3646 return new TextNode(elms, on_success); 3664 return new TextNode(elms, on_success);
3647 } 3665 }
3648 3666
3649 3667
3650 RegExpNode* RegExpText::ToNode(RegExpCompiler* compiler, 3668 RegExpNode* RegExpText::ToNode(RegExpCompiler* compiler,
3651 RegExpNode* on_success) { 3669 RegExpNode* on_success) {
3652 return new TextNode(elements(), on_success); 3670 return new TextNode(elements(), on_success);
3653 } 3671 }
3654 3672
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
3690 for (int i = 0; i < length; i += 2) { 3708 for (int i = 0; i < length; i += 2) {
3691 CharacterRange range = ranges->at(i >> 1); 3709 CharacterRange range = ranges->at(i >> 1);
3692 if (range.from() != special_class[i] || range.to() != special_class[i+1]) { 3710 if (range.from() != special_class[i] || range.to() != special_class[i+1]) {
3693 return false; 3711 return false;
3694 } 3712 }
3695 } 3713 }
3696 return true; 3714 return true;
3697 } 3715 }
3698 3716
3699 3717
3700 bool RegExpCharacterClass::is_standard() { 3718 bool RegExpCharacterClass::is_standard(Zone* zone) {
3701 // TODO(lrn): Remove need for this function, by not throwing away information 3719 // TODO(lrn): Remove need for this function, by not throwing away information
3702 // along the way. 3720 // along the way.
3703 if (is_negated_) { 3721 if (is_negated_) {
3704 return false; 3722 return false;
3705 } 3723 }
3706 if (set_.is_standard()) { 3724 if (set_.is_standard()) {
3707 return true; 3725 return true;
3708 } 3726 }
3709 if (CompareRanges(set_.ranges(), kSpaceRanges, kSpaceRangeCount)) { 3727 if (CompareRanges(set_.ranges(zone), kSpaceRanges, kSpaceRangeCount)) {
3710 set_.set_standard_set_type('s'); 3728 set_.set_standard_set_type('s');
3711 return true; 3729 return true;
3712 } 3730 }
3713 if (CompareInverseRanges(set_.ranges(), kSpaceRanges, kSpaceRangeCount)) { 3731 if (CompareInverseRanges(set_.ranges(zone), kSpaceRanges, kSpaceRangeCount)) {
3714 set_.set_standard_set_type('S'); 3732 set_.set_standard_set_type('S');
3715 return true; 3733 return true;
3716 } 3734 }
3717 if (CompareInverseRanges(set_.ranges(), 3735 if (CompareInverseRanges(set_.ranges(zone),
3718 kLineTerminatorRanges, 3736 kLineTerminatorRanges,
3719 kLineTerminatorRangeCount)) { 3737 kLineTerminatorRangeCount)) {
3720 set_.set_standard_set_type('.'); 3738 set_.set_standard_set_type('.');
3721 return true; 3739 return true;
3722 } 3740 }
3723 if (CompareRanges(set_.ranges(), 3741 if (CompareRanges(set_.ranges(zone),
3724 kLineTerminatorRanges, 3742 kLineTerminatorRanges,
3725 kLineTerminatorRangeCount)) { 3743 kLineTerminatorRangeCount)) {
3726 set_.set_standard_set_type('n'); 3744 set_.set_standard_set_type('n');
3727 return true; 3745 return true;
3728 } 3746 }
3729 if (CompareRanges(set_.ranges(), kWordRanges, kWordRangeCount)) { 3747 if (CompareRanges(set_.ranges(zone), kWordRanges, kWordRangeCount)) {
3730 set_.set_standard_set_type('w'); 3748 set_.set_standard_set_type('w');
3731 return true; 3749 return true;
3732 } 3750 }
3733 if (CompareInverseRanges(set_.ranges(), kWordRanges, kWordRangeCount)) { 3751 if (CompareInverseRanges(set_.ranges(zone), kWordRanges, kWordRangeCount)) {
3734 set_.set_standard_set_type('W'); 3752 set_.set_standard_set_type('W');
3735 return true; 3753 return true;
3736 } 3754 }
3737 return false; 3755 return false;
3738 } 3756 }
3739 3757
3740 3758
3741 RegExpNode* RegExpCharacterClass::ToNode(RegExpCompiler* compiler, 3759 RegExpNode* RegExpCharacterClass::ToNode(RegExpCompiler* compiler,
3742 RegExpNode* on_success) { 3760 RegExpNode* on_success) {
3743 return new TextNode(this, on_success); 3761 return new TextNode(compiler->zone(), this, on_success);
3744 } 3762 }
3745 3763
3746 3764
3747 RegExpNode* RegExpDisjunction::ToNode(RegExpCompiler* compiler, 3765 RegExpNode* RegExpDisjunction::ToNode(RegExpCompiler* compiler,
3748 RegExpNode* on_success) { 3766 RegExpNode* on_success) {
3749 ZoneList<RegExpTree*>* alternatives = this->alternatives(); 3767 ZoneList<RegExpTree*>* alternatives = this->alternatives();
3750 int length = alternatives->length(); 3768 int length = alternatives->length();
3751 ChoiceNode* result = new ChoiceNode(length); 3769 ChoiceNode* result = new ChoiceNode(compiler->zone(), length);
3752 for (int i = 0; i < length; i++) { 3770 for (int i = 0; i < length; i++) {
3753 GuardedAlternative alternative(alternatives->at(i)->ToNode(compiler, 3771 GuardedAlternative alternative(alternatives->at(i)->ToNode(compiler,
3754 on_success)); 3772 on_success));
3755 result->AddAlternative(alternative); 3773 result->AddAlternative(alternative);
3756 } 3774 }
3757 return result; 3775 return result;
3758 } 3776 }
3759 3777
3760 3778
3761 RegExpNode* RegExpQuantifier::ToNode(RegExpCompiler* compiler, 3779 RegExpNode* RegExpQuantifier::ToNode(RegExpCompiler* compiler,
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
3864 return answer; 3882 return answer;
3865 } 3883 }
3866 } 3884 }
3867 if (max <= kMaxUnrolledMaxMatches && min == 0) { 3885 if (max <= kMaxUnrolledMaxMatches && min == 0) {
3868 ASSERT(max > 0); // Due to the 'if' above. 3886 ASSERT(max > 0); // Due to the 'if' above.
3869 RegExpExpansionLimiter limiter(compiler, max); 3887 RegExpExpansionLimiter limiter(compiler, max);
3870 if (limiter.ok_to_expand()) { 3888 if (limiter.ok_to_expand()) {
3871 // Unroll the optional matches up to max. 3889 // Unroll the optional matches up to max.
3872 RegExpNode* answer = on_success; 3890 RegExpNode* answer = on_success;
3873 for (int i = 0; i < max; i++) { 3891 for (int i = 0; i < max; i++) {
3874 ChoiceNode* alternation = new ChoiceNode(2); 3892 ChoiceNode* alternation = new ChoiceNode(compiler->zone(), 2);
3875 if (is_greedy) { 3893 if (is_greedy) {
3876 alternation->AddAlternative( 3894 alternation->AddAlternative(
3877 GuardedAlternative(body->ToNode(compiler, answer))); 3895 GuardedAlternative(body->ToNode(compiler, answer)));
3878 alternation->AddAlternative(GuardedAlternative(on_success)); 3896 alternation->AddAlternative(GuardedAlternative(on_success));
3879 } else { 3897 } else {
3880 alternation->AddAlternative(GuardedAlternative(on_success)); 3898 alternation->AddAlternative(GuardedAlternative(on_success));
3881 alternation->AddAlternative( 3899 alternation->AddAlternative(
3882 GuardedAlternative(body->ToNode(compiler, answer))); 3900 GuardedAlternative(body->ToNode(compiler, answer)));
3883 } 3901 }
3884 answer = alternation; 3902 answer = alternation;
3885 if (not_at_start) alternation->set_not_at_start(); 3903 if (not_at_start) alternation->set_not_at_start();
3886 } 3904 }
3887 return answer; 3905 return answer;
3888 } 3906 }
3889 } 3907 }
3890 } 3908 }
3891 bool has_min = min > 0; 3909 bool has_min = min > 0;
3892 bool has_max = max < RegExpTree::kInfinity; 3910 bool has_max = max < RegExpTree::kInfinity;
3893 bool needs_counter = has_min || has_max; 3911 bool needs_counter = has_min || has_max;
3894 int reg_ctr = needs_counter 3912 int reg_ctr = needs_counter
3895 ? compiler->AllocateRegister() 3913 ? compiler->AllocateRegister()
3896 : RegExpCompiler::kNoRegister; 3914 : RegExpCompiler::kNoRegister;
3897 LoopChoiceNode* center = new LoopChoiceNode(body->min_match() == 0); 3915 LoopChoiceNode* center = new LoopChoiceNode(compiler->zone(),
3916 body->min_match() == 0);
3898 if (not_at_start) center->set_not_at_start(); 3917 if (not_at_start) center->set_not_at_start();
3899 RegExpNode* loop_return = needs_counter 3918 RegExpNode* loop_return = needs_counter
3900 ? static_cast<RegExpNode*>(ActionNode::IncrementRegister(reg_ctr, center)) 3919 ? static_cast<RegExpNode*>(ActionNode::IncrementRegister(reg_ctr, center))
3901 : static_cast<RegExpNode*>(center); 3920 : static_cast<RegExpNode*>(center);
3902 if (body_can_be_empty) { 3921 if (body_can_be_empty) {
3903 // If the body can be empty we need to check if it was and then 3922 // If the body can be empty we need to check if it was and then
3904 // backtrack. 3923 // backtrack.
3905 loop_return = ActionNode::EmptyMatchCheck(body_start_reg, 3924 loop_return = ActionNode::EmptyMatchCheck(body_start_reg,
3906 reg_ctr, 3925 reg_ctr,
3907 min, 3926 min,
3908 loop_return); 3927 loop_return);
3909 } 3928 }
3910 RegExpNode* body_node = body->ToNode(compiler, loop_return); 3929 RegExpNode* body_node = body->ToNode(compiler, loop_return);
3911 if (body_can_be_empty) { 3930 if (body_can_be_empty) {
3912 // If the body can be empty we need to store the start position 3931 // If the body can be empty we need to store the start position
3913 // so we can bail out if it was empty. 3932 // so we can bail out if it was empty.
3914 body_node = ActionNode::StorePosition(body_start_reg, false, body_node); 3933 body_node = ActionNode::StorePosition(body_start_reg, false, body_node);
3915 } 3934 }
3916 if (needs_capture_clearing) { 3935 if (needs_capture_clearing) {
3917 // Before entering the body of this loop we need to clear captures. 3936 // Before entering the body of this loop we need to clear captures.
3918 body_node = ActionNode::ClearCaptures(capture_registers, body_node); 3937 body_node = ActionNode::ClearCaptures(capture_registers, body_node);
3919 } 3938 }
3920 GuardedAlternative body_alt(body_node); 3939 GuardedAlternative body_alt(body_node);
3921 if (has_max) { 3940 if (has_max) {
3922 Guard* body_guard = new Guard(reg_ctr, Guard::LT, max); 3941 Guard* body_guard = new Guard(reg_ctr, Guard::LT, max);
3923 body_alt.AddGuard(body_guard); 3942 body_alt.AddGuard(compiler->zone(), body_guard);
3924 } 3943 }
3925 GuardedAlternative rest_alt(on_success); 3944 GuardedAlternative rest_alt(on_success);
3926 if (has_min) { 3945 if (has_min) {
3927 Guard* rest_guard = new Guard(reg_ctr, Guard::GEQ, min); 3946 Guard* rest_guard = new Guard(reg_ctr, Guard::GEQ, min);
3928 rest_alt.AddGuard(rest_guard); 3947 rest_alt.AddGuard(compiler->zone(), rest_guard);
3929 } 3948 }
3930 if (is_greedy) { 3949 if (is_greedy) {
3931 center->AddLoopAlternative(body_alt); 3950 center->AddLoopAlternative(body_alt);
3932 center->AddContinueAlternative(rest_alt); 3951 center->AddContinueAlternative(rest_alt);
3933 } else { 3952 } else {
3934 center->AddContinueAlternative(rest_alt); 3953 center->AddContinueAlternative(rest_alt);
3935 center->AddLoopAlternative(body_alt); 3954 center->AddLoopAlternative(body_alt);
3936 } 3955 }
3937 if (needs_counter) { 3956 if (needs_counter) {
3938 return ActionNode::SetRegister(reg_ctr, 0, center); 3957 return ActionNode::SetRegister(reg_ctr, 0, center);
(...skipping 17 matching lines...) Expand all
3956 return AssertionNode::AtNonBoundary(on_success); 3975 return AssertionNode::AtNonBoundary(on_success);
3957 case END_OF_INPUT: 3976 case END_OF_INPUT:
3958 return AssertionNode::AtEnd(on_success); 3977 return AssertionNode::AtEnd(on_success);
3959 case END_OF_LINE: { 3978 case END_OF_LINE: {
3960 // Compile $ in multiline regexps as an alternation with a positive 3979 // Compile $ in multiline regexps as an alternation with a positive
3961 // lookahead in one side and an end-of-input on the other side. 3980 // lookahead in one side and an end-of-input on the other side.
3962 // We need two registers for the lookahead. 3981 // We need two registers for the lookahead.
3963 int stack_pointer_register = compiler->AllocateRegister(); 3982 int stack_pointer_register = compiler->AllocateRegister();
3964 int position_register = compiler->AllocateRegister(); 3983 int position_register = compiler->AllocateRegister();
3965 // The ChoiceNode to distinguish between a newline and end-of-input. 3984 // The ChoiceNode to distinguish between a newline and end-of-input.
3966 ChoiceNode* result = new ChoiceNode(2); 3985 ChoiceNode* result = new ChoiceNode(compiler->zone(), 2);
3967 // Create a newline atom. 3986 // Create a newline atom.
3968 ZoneList<CharacterRange>* newline_ranges = 3987 ZoneList<CharacterRange>* newline_ranges =
3969 new ZoneList<CharacterRange>(3); 3988 ZoneList<CharacterRange>::New(compiler->zone(), 3);
3970 CharacterRange::AddClassEscape('n', newline_ranges); 3989 CharacterRange::AddClassEscape('n', newline_ranges);
3971 RegExpCharacterClass* newline_atom = new RegExpCharacterClass('n'); 3990 RegExpCharacterClass* newline_atom = new RegExpCharacterClass('n');
3972 TextNode* newline_matcher = new TextNode( 3991 TextNode* newline_matcher = new TextNode(
3973 newline_atom, 3992 compiler->zone(),
3974 ActionNode::PositiveSubmatchSuccess(stack_pointer_register, 3993 newline_atom,
3975 position_register, 3994 ActionNode::PositiveSubmatchSuccess(stack_pointer_register,
3976 0, // No captures inside. 3995 position_register,
3977 -1, // Ignored if no captures. 3996 0, // No captures inside.
3978 on_success)); 3997 -1, // Ignored if no captures.
3998 on_success));
3979 // Create an end-of-input matcher. 3999 // Create an end-of-input matcher.
3980 RegExpNode* end_of_line = ActionNode::BeginSubmatch( 4000 RegExpNode* end_of_line = ActionNode::BeginSubmatch(
3981 stack_pointer_register, 4001 stack_pointer_register,
3982 position_register, 4002 position_register,
3983 newline_matcher); 4003 newline_matcher);
3984 // Add the two alternatives to the ChoiceNode. 4004 // Add the two alternatives to the ChoiceNode.
3985 GuardedAlternative eol_alternative(end_of_line); 4005 GuardedAlternative eol_alternative(end_of_line);
3986 result->AddAlternative(eol_alternative); 4006 result->AddAlternative(eol_alternative);
3987 GuardedAlternative end_alternative(AssertionNode::AtEnd(on_success)); 4007 GuardedAlternative end_alternative(AssertionNode::AtEnd(on_success));
3988 result->AddAlternative(end_alternative); 4008 result->AddAlternative(end_alternative);
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
4045 // ChoiceNode that knows to ignore the first exit when calculating quick 4065 // ChoiceNode that knows to ignore the first exit when calculating quick
4046 // checks. 4066 // checks.
4047 GuardedAlternative body_alt( 4067 GuardedAlternative body_alt(
4048 body()->ToNode( 4068 body()->ToNode(
4049 compiler, 4069 compiler,
4050 success = new NegativeSubmatchSuccess(stack_pointer_register, 4070 success = new NegativeSubmatchSuccess(stack_pointer_register,
4051 position_register, 4071 position_register,
4052 register_count, 4072 register_count,
4053 register_start))); 4073 register_start)));
4054 ChoiceNode* choice_node = 4074 ChoiceNode* choice_node =
4055 new NegativeLookaheadChoiceNode(body_alt, 4075 new NegativeLookaheadChoiceNode(compiler->zone(),
4076 body_alt,
4056 GuardedAlternative(on_success)); 4077 GuardedAlternative(on_success));
4057 return ActionNode::BeginSubmatch(stack_pointer_register, 4078 return ActionNode::BeginSubmatch(stack_pointer_register,
4058 position_register, 4079 position_register,
4059 choice_node); 4080 choice_node);
4060 } 4081 }
4061 } 4082 }
4062 4083
4063 4084
4064 RegExpNode* RegExpCapture::ToNode(RegExpCompiler* compiler, 4085 RegExpNode* RegExpCapture::ToNode(RegExpCompiler* compiler,
4065 RegExpNode* on_success) { 4086 RegExpNode* on_success) {
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
4161 } 4182 }
4162 4183
4163 4184
4164 Vector<const uc16> CharacterRange::GetWordBounds() { 4185 Vector<const uc16> CharacterRange::GetWordBounds() {
4165 return Vector<const uc16>(kWordRanges, kWordRangeCount); 4186 return Vector<const uc16>(kWordRanges, kWordRangeCount);
4166 } 4187 }
4167 4188
4168 4189
4169 class CharacterRangeSplitter { 4190 class CharacterRangeSplitter {
4170 public: 4191 public:
4171 CharacterRangeSplitter(ZoneList<CharacterRange>** included, 4192 CharacterRangeSplitter(Zone* zone,
4172 ZoneList<CharacterRange>** excluded) 4193 ZoneList<CharacterRange>** included,
4173 : included_(included), 4194 ZoneList<CharacterRange>** excluded)
4195 : zone_(zone),
4196 included_(included),
4174 excluded_(excluded) { } 4197 excluded_(excluded) { }
4175 void Call(uc16 from, DispatchTable::Entry entry); 4198 void Call(uc16 from, DispatchTable::Entry entry);
4176 4199
4177 static const int kInBase = 0; 4200 static const int kInBase = 0;
4178 static const int kInOverlay = 1; 4201 static const int kInOverlay = 1;
4179 4202
4180 private: 4203 private:
4204 Zone* zone_;
4181 ZoneList<CharacterRange>** included_; 4205 ZoneList<CharacterRange>** included_;
4182 ZoneList<CharacterRange>** excluded_; 4206 ZoneList<CharacterRange>** excluded_;
4183 }; 4207 };
4184 4208
4185 4209
4186 void CharacterRangeSplitter::Call(uc16 from, DispatchTable::Entry entry) { 4210 void CharacterRangeSplitter::Call(uc16 from,
4211 DispatchTable::Entry entry) {
4187 if (!entry.out_set()->Get(kInBase)) return; 4212 if (!entry.out_set()->Get(kInBase)) return;
4188 ZoneList<CharacterRange>** target = entry.out_set()->Get(kInOverlay) 4213 ZoneList<CharacterRange>** target = entry.out_set()->Get(kInOverlay)
4189 ? included_ 4214 ? included_
4190 : excluded_; 4215 : excluded_;
4191 if (*target == NULL) *target = new ZoneList<CharacterRange>(2); 4216 if (*target == NULL) *target = ZoneList<CharacterRange>::New(zone_, 2);
4192 (*target)->Add(CharacterRange(entry.from(), entry.to())); 4217 (*target)->Add(CharacterRange(entry.from(), entry.to()));
4193 } 4218 }
4194 4219
4195 4220
4196 void CharacterRange::Split(ZoneList<CharacterRange>* base, 4221 void CharacterRange::Split(Zone* zone,
4222 ZoneList<CharacterRange>* base,
4197 Vector<const uc16> overlay, 4223 Vector<const uc16> overlay,
4198 ZoneList<CharacterRange>** included, 4224 ZoneList<CharacterRange>** included,
4199 ZoneList<CharacterRange>** excluded) { 4225 ZoneList<CharacterRange>** excluded) {
4200 ASSERT_EQ(NULL, *included); 4226 ASSERT_EQ(NULL, *included);
4201 ASSERT_EQ(NULL, *excluded); 4227 ASSERT_EQ(NULL, *excluded);
4202 DispatchTable table; 4228 DispatchTable table(zone);
4203 for (int i = 0; i < base->length(); i++) 4229 for (int i = 0; i < base->length(); i++)
4204 table.AddRange(base->at(i), CharacterRangeSplitter::kInBase); 4230 table.AddRange(base->at(i), CharacterRangeSplitter::kInBase);
4205 for (int i = 0; i < overlay.length(); i += 2) { 4231 for (int i = 0; i < overlay.length(); i += 2) {
4206 table.AddRange(CharacterRange(overlay[i], overlay[i+1]), 4232 table.AddRange(CharacterRange(overlay[i], overlay[i+1]),
4207 CharacterRangeSplitter::kInOverlay); 4233 CharacterRangeSplitter::kInOverlay);
4208 } 4234 }
4209 CharacterRangeSplitter callback(included, excluded); 4235 CharacterRangeSplitter callback(zone, included, excluded);
4210 table.ForEach(&callback); 4236 table.ForEach(&callback);
4211 } 4237 }
4212 4238
4213 4239
4214 void CharacterRange::AddCaseEquivalents(ZoneList<CharacterRange>* ranges, 4240 void CharacterRange::AddCaseEquivalents(ZoneList<CharacterRange>* ranges,
4215 bool is_ascii) { 4241 bool is_ascii) {
4216 Isolate* isolate = Isolate::Current(); 4242 Isolate* isolate = Isolate::Current();
4217 uc16 bottom = from(); 4243 uc16 bottom = from();
4218 uc16 top = to(); 4244 uc16 top = to();
4219 if (is_ascii) { 4245 if (is_ascii) {
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
4364 result.SetElementsInSecondSet(); 4390 result.SetElementsInSecondSet();
4365 } else if (j < range->length()) { 4391 } else if (j < range->length()) {
4366 // Argument range contains something not in word range. 4392 // Argument range contains something not in word range.
4367 result.SetElementsInFirstSet(); 4393 result.SetElementsInFirstSet();
4368 } 4394 }
4369 4395
4370 return result; 4396 return result;
4371 } 4397 }
4372 4398
4373 4399
4374 ZoneList<CharacterRange>* CharacterSet::ranges() { 4400 ZoneList<CharacterRange>* CharacterSet::ranges(Zone* zone) {
4375 if (ranges_ == NULL) { 4401 if (ranges_ == NULL) {
4376 ranges_ = new ZoneList<CharacterRange>(2); 4402 ranges_ = ZoneList<CharacterRange>::New(zone, 2);
4377 CharacterRange::AddClassEscape(standard_set_type_, ranges_); 4403 CharacterRange::AddClassEscape(standard_set_type_, ranges_);
4378 } 4404 }
4379 return ranges_; 4405 return ranges_;
4380 } 4406 }
4381 4407
4382 4408
4383 // Move a number of elements in a zonelist to another position 4409 // Move a number of elements in a zonelist to another position
4384 // in the same list. Handles overlapping source and target areas. 4410 // in the same list. Handles overlapping source and target areas.
4385 static void MoveRanges(ZoneList<CharacterRange>* list, 4411 static void MoveRanges(ZoneList<CharacterRange>* list,
4386 int from, 4412 int from,
(...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after
4672 RegExpNode* RegExpNode::TryGetSibling(NodeInfo* info) { 4698 RegExpNode* RegExpNode::TryGetSibling(NodeInfo* info) {
4673 for (int i = 0; i < siblings_.length(); i++) { 4699 for (int i = 0; i < siblings_.length(); i++) {
4674 RegExpNode* sibling = siblings_.Get(i); 4700 RegExpNode* sibling = siblings_.Get(i);
4675 if (sibling->info()->Matches(info)) 4701 if (sibling->info()->Matches(info))
4676 return sibling; 4702 return sibling;
4677 } 4703 }
4678 return NULL; 4704 return NULL;
4679 } 4705 }
4680 4706
4681 4707
4682 RegExpNode* RegExpNode::EnsureSibling(NodeInfo* info, bool* cloned) { 4708 RegExpNode* RegExpNode::EnsureSibling(Zone* zone,
4709 NodeInfo* info,
4710 bool* cloned) {
4683 ASSERT_EQ(false, *cloned); 4711 ASSERT_EQ(false, *cloned);
4684 siblings_.Ensure(this); 4712 siblings_.Ensure(zone, this);
4685 RegExpNode* result = TryGetSibling(info); 4713 RegExpNode* result = TryGetSibling(info);
4686 if (result != NULL) return result; 4714 if (result != NULL) return result;
4687 result = this->Clone(); 4715 result = this->Clone();
4688 NodeInfo* new_info = result->info(); 4716 NodeInfo* new_info = result->info();
4689 new_info->ResetCompilationState(); 4717 new_info->ResetCompilationState();
4690 new_info->AddFromPreceding(info); 4718 new_info->AddFromPreceding(info);
4691 AddSibling(result); 4719 AddSibling(result);
4692 *cloned = true; 4720 *cloned = true;
4693 return result; 4721 return result;
4694 } 4722 }
4695 4723
4696 4724
4697 template <class C> 4725 template <class C>
4698 static RegExpNode* PropagateToEndpoint(C* node, NodeInfo* info) { 4726 static RegExpNode* PropagateToEndpoint(C* node, NodeInfo* info) {
4699 NodeInfo full_info(*node->info()); 4727 NodeInfo full_info(*node->info());
4700 full_info.AddFromPreceding(info); 4728 full_info.AddFromPreceding(info);
4701 bool cloned = false; 4729 bool cloned = false;
4702 return RegExpNode::EnsureSibling(node, &full_info, &cloned); 4730 return RegExpNode::EnsureSibling(node, &full_info, &cloned);
4703 } 4731 }
4704 4732
4705 4733
4706 // ------------------------------------------------------------------- 4734 // -------------------------------------------------------------------
4707 // Splay tree 4735 // Splay tree
4708 4736
4709 4737
4710 OutSet* OutSet::Extend(unsigned value) { 4738 OutSet* OutSet::Extend(Zone* zone, unsigned value) {
4711 if (Get(value)) 4739 if (Get(value))
4712 return this; 4740 return this;
4713 if (successors() != NULL) { 4741 if (successors() != NULL) {
4714 for (int i = 0; i < successors()->length(); i++) { 4742 for (int i = 0; i < successors()->length(); i++) {
4715 OutSet* successor = successors()->at(i); 4743 OutSet* successor = successors()->at(i);
4716 if (successor->Get(value)) 4744 if (successor->Get(value))
4717 return successor; 4745 return successor;
4718 } 4746 }
4719 } else { 4747 } else {
4720 successors_ = new ZoneList<OutSet*>(2); 4748 successors_ = ZoneList<OutSet*>::New(zone, 2);
4721 } 4749 }
4722 OutSet* result = new OutSet(first_, remaining_); 4750 OutSet* result = new(zone) OutSet(first_, remaining_);
4723 result->Set(value); 4751 result->Set(zone, value);
4724 successors()->Add(result); 4752 successors()->Add(result);
4725 return result; 4753 return result;
4726 } 4754 }
4727 4755
4728 4756
4729 void OutSet::Set(unsigned value) { 4757 void OutSet::Set(Zone* zone, unsigned value) {
4730 if (value < kFirstLimit) { 4758 if (value < kFirstLimit) {
4731 first_ |= (1 << value); 4759 first_ |= (1 << value);
4732 } else { 4760 } else {
4733 if (remaining_ == NULL) 4761 if (remaining_ == NULL)
4734 remaining_ = new ZoneList<unsigned>(1); 4762 remaining_ = ZoneList<unsigned>::New(zone, 1);
4735 if (remaining_->is_empty() || !remaining_->Contains(value)) 4763 if (remaining_->is_empty() || !remaining_->Contains(value))
4736 remaining_->Add(value); 4764 remaining_->Add(value);
4737 } 4765 }
4738 } 4766 }
4739 4767
4740 4768
4741 bool OutSet::Get(unsigned value) { 4769 bool OutSet::Get(unsigned value) {
4742 if (value < kFirstLimit) { 4770 if (value < kFirstLimit) {
4743 return (first_ & (1 << value)) != 0; 4771 return (first_ & (1 << value)) != 0;
4744 } else if (remaining_ == NULL) { 4772 } else if (remaining_ == NULL) {
4745 return false; 4773 return false;
4746 } else { 4774 } else {
4747 return remaining_->Contains(value); 4775 return remaining_->Contains(value);
4748 } 4776 }
4749 } 4777 }
4750 4778
4751 4779
4752 const uc16 DispatchTable::Config::kNoKey = unibrow::Utf8::kBadChar; 4780 const uc16 DispatchTable::Config::kNoKey = unibrow::Utf8::kBadChar;
4753 const DispatchTable::Entry DispatchTable::Config::kNoValue; 4781 const DispatchTable::Entry DispatchTable::Config::kNoValue;
4754 4782
4755 4783
4756 void DispatchTable::AddRange(CharacterRange full_range, int value) { 4784 void DispatchTable::AddRange(CharacterRange full_range, int value) {
4757 CharacterRange current = full_range; 4785 CharacterRange current = full_range;
4758 if (tree()->is_empty()) { 4786 if (tree()->is_empty()) {
4759 // If this is the first range we just insert into the table. 4787 // If this is the first range we just insert into the table.
4760 ZoneSplayTree<Config>::Locator loc; 4788 ZoneSplayTree<Config>::Locator loc;
4761 ASSERT_RESULT(tree()->Insert(current.from(), &loc)); 4789 ASSERT_RESULT(tree()->Insert(current.from(), &loc));
4762 loc.set_value(Entry(current.from(), current.to(), empty()->Extend(value))); 4790 loc.set_value(Entry(current.from(),
4791 current.to(),
4792 empty()->Extend(zone_, value)));
4763 return; 4793 return;
4764 } 4794 }
4765 // First see if there is a range to the left of this one that 4795 // First see if there is a range to the left of this one that
4766 // overlaps. 4796 // overlaps.
4767 ZoneSplayTree<Config>::Locator loc; 4797 ZoneSplayTree<Config>::Locator loc;
4768 if (tree()->FindGreatestLessThan(current.from(), &loc)) { 4798 if (tree()->FindGreatestLessThan(current.from(), &loc)) {
4769 Entry* entry = &loc.value(); 4799 Entry* entry = &loc.value();
4770 // If we've found a range that overlaps with this one, and it 4800 // If we've found a range that overlaps with this one, and it
4771 // starts strictly to the left of this one, we have to fix it 4801 // starts strictly to the left of this one, we have to fix it
4772 // because the following code only handles ranges that start on 4802 // because the following code only handles ranges that start on
(...skipping 22 matching lines...) Expand all
4795 (loc.value().to() >= current.from())) { 4825 (loc.value().to() >= current.from())) {
4796 Entry* entry = &loc.value(); 4826 Entry* entry = &loc.value();
4797 // We have overlap. If there is space between the start point of 4827 // We have overlap. If there is space between the start point of
4798 // the range we're adding and where the overlapping range starts 4828 // the range we're adding and where the overlapping range starts
4799 // then we have to add a range covering just that space. 4829 // then we have to add a range covering just that space.
4800 if (current.from() < entry->from()) { 4830 if (current.from() < entry->from()) {
4801 ZoneSplayTree<Config>::Locator ins; 4831 ZoneSplayTree<Config>::Locator ins;
4802 ASSERT_RESULT(tree()->Insert(current.from(), &ins)); 4832 ASSERT_RESULT(tree()->Insert(current.from(), &ins));
4803 ins.set_value(Entry(current.from(), 4833 ins.set_value(Entry(current.from(),
4804 entry->from() - 1, 4834 entry->from() - 1,
4805 empty()->Extend(value))); 4835 empty()->Extend(zone_, value)));
4806 current.set_from(entry->from()); 4836 current.set_from(entry->from());
4807 } 4837 }
4808 ASSERT_EQ(current.from(), entry->from()); 4838 ASSERT_EQ(current.from(), entry->from());
4809 // If the overlapping range extends beyond the one we want to add 4839 // If the overlapping range extends beyond the one we want to add
4810 // we have to snap the right part off and add it separately. 4840 // we have to snap the right part off and add it separately.
4811 if (entry->to() > current.to()) { 4841 if (entry->to() > current.to()) {
4812 ZoneSplayTree<Config>::Locator ins; 4842 ZoneSplayTree<Config>::Locator ins;
4813 ASSERT_RESULT(tree()->Insert(current.to() + 1, &ins)); 4843 ASSERT_RESULT(tree()->Insert(current.to() + 1, &ins));
4814 ins.set_value(Entry(current.to() + 1, 4844 ins.set_value(Entry(current.to() + 1,
4815 entry->to(), 4845 entry->to(),
4816 entry->out_set())); 4846 entry->out_set()));
4817 entry->set_to(current.to()); 4847 entry->set_to(current.to());
4818 } 4848 }
4819 ASSERT(entry->to() <= current.to()); 4849 ASSERT(entry->to() <= current.to());
4820 // The overlapping range is now completely contained by the range 4850 // The overlapping range is now completely contained by the range
4821 // we're adding so we can just update it and move the start point 4851 // we're adding so we can just update it and move the start point
4822 // of the range we're adding just past it. 4852 // of the range we're adding just past it.
4823 entry->AddValue(value); 4853 entry->AddValue(zone_, value);
4824 // Bail out if the last interval ended at 0xFFFF since otherwise 4854 // Bail out if the last interval ended at 0xFFFF since otherwise
4825 // adding 1 will wrap around to 0. 4855 // adding 1 will wrap around to 0.
4826 if (entry->to() == String::kMaxUC16CharCode) 4856 if (entry->to() == String::kMaxUC16CharCode)
4827 break; 4857 break;
4828 ASSERT(entry->to() + 1 > current.from()); 4858 ASSERT(entry->to() + 1 > current.from());
4829 current.set_from(entry->to() + 1); 4859 current.set_from(entry->to() + 1);
4830 } else { 4860 } else {
4831 // There is no overlap so we can just add the range 4861 // There is no overlap so we can just add the range
4832 ZoneSplayTree<Config>::Locator ins; 4862 ZoneSplayTree<Config>::Locator ins;
4833 ASSERT_RESULT(tree()->Insert(current.from(), &ins)); 4863 ASSERT_RESULT(tree()->Insert(current.from(), &ins));
4834 ins.set_value(Entry(current.from(), 4864 ins.set_value(Entry(current.from(),
4835 current.to(), 4865 current.to(),
4836 empty()->Extend(value))); 4866 empty()->Extend(zone_, value)));
4837 break; 4867 break;
4838 } 4868 }
4839 } 4869 }
4840 } 4870 }
4841 4871
4842 4872
4843 OutSet* DispatchTable::Get(uc16 value) { 4873 OutSet* DispatchTable::Get(uc16 value) {
4844 ZoneSplayTree<Config>::Locator loc; 4874 ZoneSplayTree<Config>::Locator loc;
4845 if (!tree()->FindGreatestLessThan(value, &loc)) 4875 if (!tree()->FindGreatestLessThan(value, &loc))
4846 return empty(); 4876 return empty();
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
4889 } else { 4919 } else {
4890 cp_offset++; 4920 cp_offset++;
4891 Vector<const uc16> quarks = elm.data.u_atom->data(); 4921 Vector<const uc16> quarks = elm.data.u_atom->data();
4892 } 4922 }
4893 } 4923 }
4894 } 4924 }
4895 4925
4896 4926
4897 void Analysis::VisitText(TextNode* that) { 4927 void Analysis::VisitText(TextNode* that) {
4898 if (ignore_case_) { 4928 if (ignore_case_) {
4899 that->MakeCaseIndependent(is_ascii_); 4929 that->MakeCaseIndependent(zone_, is_ascii_);
4900 } 4930 }
4901 EnsureAnalyzed(that->on_success()); 4931 EnsureAnalyzed(that->on_success());
4902 if (!has_failed()) { 4932 if (!has_failed()) {
4903 that->CalculateOffsets(); 4933 that->CalculateOffsets();
4904 } 4934 }
4905 } 4935 }
4906 4936
4907 4937
4908 void Analysis::VisitAction(ActionNode* that) { 4938 void Analysis::VisitAction(ActionNode* that) {
4909 RegExpNode* target = that->on_success(); 4939 RegExpNode* target = that->on_success();
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
4953 } 4983 }
4954 4984
4955 4985
4956 void Analysis::VisitAssertion(AssertionNode* that) { 4986 void Analysis::VisitAssertion(AssertionNode* that) {
4957 EnsureAnalyzed(that->on_success()); 4987 EnsureAnalyzed(that->on_success());
4958 AssertionNode::AssertionNodeType type = that->type(); 4988 AssertionNode::AssertionNodeType type = that->type();
4959 if (type == AssertionNode::AT_BOUNDARY || 4989 if (type == AssertionNode::AT_BOUNDARY ||
4960 type == AssertionNode::AT_NON_BOUNDARY) { 4990 type == AssertionNode::AT_NON_BOUNDARY) {
4961 // Check if the following character is known to be a word character 4991 // Check if the following character is known to be a word character
4962 // or known to not be a word character. 4992 // or known to not be a word character.
4963 ZoneList<CharacterRange>* following_chars = that->FirstCharacterSet(); 4993 ZoneList<CharacterRange>* following_chars = that->FirstCharacterSet(zone_);
4964 4994
4965 CharacterRange::Canonicalize(following_chars); 4995 CharacterRange::Canonicalize(following_chars);
4966 4996
4967 SetRelation word_relation = 4997 SetRelation word_relation =
4968 CharacterRange::WordCharacterRelation(following_chars); 4998 CharacterRange::WordCharacterRelation(following_chars);
4969 if (word_relation.Disjoint()) { 4999 if (word_relation.Disjoint()) {
4970 // Includes the case where following_chars is empty (e.g., end-of-input). 5000 // Includes the case where following_chars is empty (e.g., end-of-input).
4971 // Following character is definitely *not* a word character. 5001 // Following character is definitely *not* a word character.
4972 type = (type == AssertionNode::AT_BOUNDARY) ? 5002 type = (type == AssertionNode::AT_BOUNDARY) ?
4973 AssertionNode::AFTER_WORD_CHARACTER : 5003 AssertionNode::AFTER_WORD_CHARACTER :
4974 AssertionNode::AFTER_NONWORD_CHARACTER; 5004 AssertionNode::AFTER_NONWORD_CHARACTER;
4975 that->set_type(type); 5005 that->set_type(type);
4976 } else if (word_relation.ContainedIn()) { 5006 } else if (word_relation.ContainedIn()) {
4977 // Following character is definitely a word character. 5007 // Following character is definitely a word character.
4978 type = (type == AssertionNode::AT_BOUNDARY) ? 5008 type = (type == AssertionNode::AT_BOUNDARY) ?
4979 AssertionNode::AFTER_NONWORD_CHARACTER : 5009 AssertionNode::AFTER_NONWORD_CHARACTER :
4980 AssertionNode::AFTER_WORD_CHARACTER; 5010 AssertionNode::AFTER_WORD_CHARACTER;
4981 that->set_type(type); 5011 that->set_type(type);
4982 } 5012 }
4983 } 5013 }
4984 } 5014 }
4985 5015
4986 5016
4987 ZoneList<CharacterRange>* RegExpNode::FirstCharacterSet() { 5017 ZoneList<CharacterRange>* RegExpNode::FirstCharacterSet(Zone* zone) {
4988 if (first_character_set_ == NULL) { 5018 if (first_character_set_ == NULL) {
4989 if (ComputeFirstCharacterSet(kFirstCharBudget) < 0) { 5019 if (ComputeFirstCharacterSet(zone, kFirstCharBudget) < 0) {
4990 // If we can't find an exact solution within the budget, we 5020 // If we can't find an exact solution within the budget, we
4991 // set the value to the set of every character, i.e., all characters 5021 // set the value to the set of every character, i.e., all characters
4992 // are possible. 5022 // are possible.
4993 ZoneList<CharacterRange>* all_set = new ZoneList<CharacterRange>(1); 5023 ZoneList<CharacterRange>* all_set =
5024 ZoneList<CharacterRange>::New(zone, 1);
4994 all_set->Add(CharacterRange::Everything()); 5025 all_set->Add(CharacterRange::Everything());
4995 first_character_set_ = all_set; 5026 first_character_set_ = all_set;
4996 } 5027 }
4997 } 5028 }
4998 return first_character_set_; 5029 return first_character_set_;
4999 } 5030 }
5000 5031
5001 5032
5002 int RegExpNode::ComputeFirstCharacterSet(int budget) { 5033 int RegExpNode::ComputeFirstCharacterSet(Zone* zone, int budget) {
5003 // Default behavior is to not be able to determine the first character. 5034 // Default behavior is to not be able to determine the first character.
5004 return kComputeFirstCharacterSetFail; 5035 return kComputeFirstCharacterSetFail;
5005 } 5036 }
5006 5037
5007 5038
5008 int LoopChoiceNode::ComputeFirstCharacterSet(int budget) { 5039 int LoopChoiceNode::ComputeFirstCharacterSet(Zone* zone, int budget) {
5009 budget--; 5040 budget--;
5010 if (budget >= 0) { 5041 if (budget >= 0) {
5011 // Find loop min-iteration. It's the value of the guarded choice node 5042 // Find loop min-iteration. It's the value of the guarded choice node
5012 // with a GEQ guard, if any. 5043 // with a GEQ guard, if any.
5013 int min_repetition = 0; 5044 int min_repetition = 0;
5014 5045
5015 for (int i = 0; i <= 1; i++) { 5046 for (int i = 0; i <= 1; i++) {
5016 GuardedAlternative alternative = alternatives()->at(i); 5047 GuardedAlternative alternative = alternatives()->at(i);
5017 ZoneList<Guard*>* guards = alternative.guards(); 5048 ZoneList<Guard*>* guards = alternative.guards();
5018 if (guards != NULL && guards->length() > 0) { 5049 if (guards != NULL && guards->length() > 0) {
5019 Guard* guard = guards->at(0); 5050 Guard* guard = guards->at(0);
5020 if (guard->op() == Guard::GEQ) { 5051 if (guard->op() == Guard::GEQ) {
5021 min_repetition = guard->value(); 5052 min_repetition = guard->value();
5022 break; 5053 break;
5023 } 5054 }
5024 } 5055 }
5025 } 5056 }
5026 5057
5027 budget = loop_node()->ComputeFirstCharacterSet(budget); 5058 budget = loop_node()->ComputeFirstCharacterSet(zone, budget);
5028 if (budget >= 0) { 5059 if (budget >= 0) {
5029 ZoneList<CharacterRange>* character_set = 5060 ZoneList<CharacterRange>* character_set =
5030 loop_node()->first_character_set(); 5061 loop_node()->first_character_set();
5031 if (body_can_be_zero_length() || min_repetition == 0) { 5062 if (body_can_be_zero_length() || min_repetition == 0) {
5032 budget = continue_node()->ComputeFirstCharacterSet(budget); 5063 budget = continue_node()->ComputeFirstCharacterSet(zone, budget);
5033 if (budget < 0) return budget; 5064 if (budget < 0) return budget;
5034 ZoneList<CharacterRange>* body_set = 5065 ZoneList<CharacterRange>* body_set =
5035 continue_node()->first_character_set(); 5066 continue_node()->first_character_set();
5036 ZoneList<CharacterRange>* union_set = 5067 ZoneList<CharacterRange>* union_set =
5037 new ZoneList<CharacterRange>(Max(character_set->length(), 5068 ZoneList<CharacterRange>::New(zone,
5038 body_set->length())); 5069 Max(character_set->length(),
5070 body_set->length()));
5039 CharacterRange::Merge(character_set, 5071 CharacterRange::Merge(character_set,
5040 body_set, 5072 body_set,
5041 union_set, 5073 union_set,
5042 union_set, 5074 union_set,
5043 union_set); 5075 union_set);
5044 character_set = union_set; 5076 character_set = union_set;
5045 } 5077 }
5046 set_first_character_set(character_set); 5078 set_first_character_set(character_set);
5047 } 5079 }
5048 } 5080 }
5049 return budget; 5081 return budget;
5050 } 5082 }
5051 5083
5052 5084
5053 int NegativeLookaheadChoiceNode::ComputeFirstCharacterSet(int budget) { 5085 int NegativeLookaheadChoiceNode::ComputeFirstCharacterSet(Zone* zone,
5086 int budget) {
5054 budget--; 5087 budget--;
5055 if (budget >= 0) { 5088 if (budget >= 0) {
5056 GuardedAlternative successor = this->alternatives()->at(1); 5089 GuardedAlternative successor = this->alternatives()->at(1);
5057 RegExpNode* successor_node = successor.node(); 5090 RegExpNode* successor_node = successor.node();
5058 budget = successor_node->ComputeFirstCharacterSet(budget); 5091 budget = successor_node->ComputeFirstCharacterSet(zone, budget);
5059 if (budget >= 0) { 5092 if (budget >= 0) {
5060 set_first_character_set(successor_node->first_character_set()); 5093 set_first_character_set(successor_node->first_character_set());
5061 } 5094 }
5062 } 5095 }
5063 return budget; 5096 return budget;
5064 } 5097 }
5065 5098
5066 5099
5067 // The first character set of an EndNode is unknowable. Just use the 5100 // The first character set of an EndNode is unknowable. Just use the
5068 // default implementation that fails and returns all characters as possible. 5101 // default implementation that fails and returns all characters as possible.
5069 5102
5070 5103
5071 int AssertionNode::ComputeFirstCharacterSet(int budget) { 5104 int AssertionNode::ComputeFirstCharacterSet(Zone* zone, int budget) {
5072 budget -= 1; 5105 budget -= 1;
5073 if (budget >= 0) { 5106 if (budget >= 0) {
5074 switch (type_) { 5107 switch (type_) {
5075 case AT_END: { 5108 case AT_END: {
5076 set_first_character_set(new ZoneList<CharacterRange>(0)); 5109 set_first_character_set(ZoneList<CharacterRange>::New(zone, 0));
5077 break; 5110 break;
5078 } 5111 }
5079 case AT_START: 5112 case AT_START:
5080 case AT_BOUNDARY: 5113 case AT_BOUNDARY:
5081 case AT_NON_BOUNDARY: 5114 case AT_NON_BOUNDARY:
5082 case AFTER_NEWLINE: 5115 case AFTER_NEWLINE:
5083 case AFTER_NONWORD_CHARACTER: 5116 case AFTER_NONWORD_CHARACTER:
5084 case AFTER_WORD_CHARACTER: { 5117 case AFTER_WORD_CHARACTER: {
5085 ASSERT_NOT_NULL(on_success()); 5118 ASSERT_NOT_NULL(on_success());
5086 budget = on_success()->ComputeFirstCharacterSet(budget); 5119 budget = on_success()->ComputeFirstCharacterSet(zone, budget);
5087 if (budget >= 0) { 5120 if (budget >= 0) {
5088 set_first_character_set(on_success()->first_character_set()); 5121 set_first_character_set(on_success()->first_character_set());
5089 } 5122 }
5090 break; 5123 break;
5091 } 5124 }
5092 } 5125 }
5093 } 5126 }
5094 return budget; 5127 return budget;
5095 } 5128 }
5096 5129
5097 5130
5098 int ActionNode::ComputeFirstCharacterSet(int budget) { 5131 int ActionNode::ComputeFirstCharacterSet(Zone* zone, int budget) {
5099 if (type_ == POSITIVE_SUBMATCH_SUCCESS) return kComputeFirstCharacterSetFail; 5132 if (type_ == POSITIVE_SUBMATCH_SUCCESS) return kComputeFirstCharacterSetFail;
5100 budget--; 5133 budget--;
5101 if (budget >= 0) { 5134 if (budget >= 0) {
5102 ASSERT_NOT_NULL(on_success()); 5135 ASSERT_NOT_NULL(on_success());
5103 budget = on_success()->ComputeFirstCharacterSet(budget); 5136 budget = on_success()->ComputeFirstCharacterSet(zone, budget);
5104 if (budget >= 0) { 5137 if (budget >= 0) {
5105 set_first_character_set(on_success()->first_character_set()); 5138 set_first_character_set(on_success()->first_character_set());
5106 } 5139 }
5107 } 5140 }
5108 return budget; 5141 return budget;
5109 } 5142 }
5110 5143
5111 5144
5112 int BackReferenceNode::ComputeFirstCharacterSet(int budget) { 5145 int BackReferenceNode::ComputeFirstCharacterSet(Zone* zone, int budget) {
5113 // We don't know anything about the first character of a backreference 5146 // We don't know anything about the first character of a backreference
5114 // at this point. 5147 // at this point.
5115 // The potential first characters are the first characters of the capture, 5148 // The potential first characters are the first characters of the capture,
5116 // and the first characters of the on_success node, depending on whether the 5149 // and the first characters of the on_success node, depending on whether the
5117 // capture can be empty and whether it is known to be participating or known 5150 // capture can be empty and whether it is known to be participating or known
5118 // not to be. 5151 // not to be.
5119 return kComputeFirstCharacterSetFail; 5152 return kComputeFirstCharacterSetFail;
5120 } 5153 }
5121 5154
5122 5155
5123 int TextNode::ComputeFirstCharacterSet(int budget) { 5156 int TextNode::ComputeFirstCharacterSet(Zone* zone, int budget) {
5124 budget--; 5157 budget--;
5125 if (budget >= 0) { 5158 if (budget >= 0) {
5126 ASSERT_NE(0, elements()->length()); 5159 ASSERT_NE(0, elements()->length());
5127 TextElement text = elements()->at(0); 5160 TextElement text = elements()->at(0);
5128 if (text.type == TextElement::ATOM) { 5161 if (text.type == TextElement::ATOM) {
5129 RegExpAtom* atom = text.data.u_atom; 5162 RegExpAtom* atom = text.data.u_atom;
5130 ASSERT_NE(0, atom->length()); 5163 ASSERT_NE(0, atom->length());
5131 uc16 first_char = atom->data()[0]; 5164 uc16 first_char = atom->data()[0];
5132 ZoneList<CharacterRange>* range = new ZoneList<CharacterRange>(1); 5165 ZoneList<CharacterRange>* range = ZoneList<CharacterRange>::New(zone, 1);
5133 range->Add(CharacterRange(first_char, first_char)); 5166 range->Add(CharacterRange(first_char, first_char));
5134 set_first_character_set(range); 5167 set_first_character_set(range);
5135 } else { 5168 } else {
5136 ASSERT(text.type == TextElement::CHAR_CLASS); 5169 ASSERT(text.type == TextElement::CHAR_CLASS);
5137 RegExpCharacterClass* char_class = text.data.u_char_class; 5170 RegExpCharacterClass* char_class = text.data.u_char_class;
5138 ZoneList<CharacterRange>* ranges = char_class->ranges(); 5171 ZoneList<CharacterRange>* ranges = char_class->ranges(zone);
5139 // TODO(lrn): Canonicalize ranges when they are created 5172 // TODO(lrn): Canonicalize ranges when they are created
5140 // instead of waiting until now. 5173 // instead of waiting until now.
5141 CharacterRange::Canonicalize(ranges); 5174 CharacterRange::Canonicalize(ranges);
5142 if (char_class->is_negated()) { 5175 if (char_class->is_negated()) {
5143 int length = ranges->length(); 5176 int length = ranges->length();
5144 int new_length = length + 1; 5177 int new_length = length + 1;
5145 if (length > 0) { 5178 if (length > 0) {
5146 if (ranges->at(0).from() == 0) new_length--; 5179 if (ranges->at(0).from() == 0) new_length--;
5147 if (ranges->at(length - 1).to() == String::kMaxUC16CharCode) { 5180 if (ranges->at(length - 1).to() == String::kMaxUC16CharCode) {
5148 new_length--; 5181 new_length--;
5149 } 5182 }
5150 } 5183 }
5151 ZoneList<CharacterRange>* negated_ranges = 5184 ZoneList<CharacterRange>* negated_ranges =
5152 new ZoneList<CharacterRange>(new_length); 5185 ZoneList<CharacterRange>::New(zone, new_length);
5153 CharacterRange::Negate(ranges, negated_ranges); 5186 CharacterRange::Negate(ranges, negated_ranges);
5154 set_first_character_set(negated_ranges); 5187 set_first_character_set(negated_ranges);
5155 } else { 5188 } else {
5156 set_first_character_set(ranges); 5189 set_first_character_set(ranges);
5157 } 5190 }
5158 } 5191 }
5159 } 5192 }
5160 return budget; 5193 return budget;
5161 } 5194 }
5162 5195
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
5194 5227
5195 void AddDispatchRange::Call(uc32 from, DispatchTable::Entry entry) { 5228 void AddDispatchRange::Call(uc32 from, DispatchTable::Entry entry) {
5196 CharacterRange range(from, entry.to()); 5229 CharacterRange range(from, entry.to());
5197 constructor_->AddRange(range); 5230 constructor_->AddRange(range);
5198 } 5231 }
5199 5232
5200 5233
5201 void DispatchTableConstructor::VisitChoice(ChoiceNode* node) { 5234 void DispatchTableConstructor::VisitChoice(ChoiceNode* node) {
5202 if (node->being_calculated()) 5235 if (node->being_calculated())
5203 return; 5236 return;
5204 DispatchTable* table = node->GetTable(ignore_case_); 5237 DispatchTable* table = node->GetTable(zone_, ignore_case_);
5205 AddDispatchRange adder(this); 5238 AddDispatchRange adder(this);
5206 table->ForEach(&adder); 5239 table->ForEach(&adder);
5207 } 5240 }
5208 5241
5209 5242
5210 void DispatchTableConstructor::VisitBackReference(BackReferenceNode* that) { 5243 void DispatchTableConstructor::VisitBackReference(BackReferenceNode* that) {
5211 // TODO(160): Find the node that we refer back to and propagate its start 5244 // TODO(160): Find the node that we refer back to and propagate its start
5212 // set back to here. For now we just accept anything. 5245 // set back to here. For now we just accept anything.
5213 AddRange(CharacterRange::Everything()); 5246 AddRange(CharacterRange::Everything());
5214 } 5247 }
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
5248 void DispatchTableConstructor::VisitText(TextNode* that) { 5281 void DispatchTableConstructor::VisitText(TextNode* that) {
5249 TextElement elm = that->elements()->at(0); 5282 TextElement elm = that->elements()->at(0);
5250 switch (elm.type) { 5283 switch (elm.type) {
5251 case TextElement::ATOM: { 5284 case TextElement::ATOM: {
5252 uc16 c = elm.data.u_atom->data()[0]; 5285 uc16 c = elm.data.u_atom->data()[0];
5253 AddRange(CharacterRange(c, c)); 5286 AddRange(CharacterRange(c, c));
5254 break; 5287 break;
5255 } 5288 }
5256 case TextElement::CHAR_CLASS: { 5289 case TextElement::CHAR_CLASS: {
5257 RegExpCharacterClass* tree = elm.data.u_char_class; 5290 RegExpCharacterClass* tree = elm.data.u_char_class;
5258 ZoneList<CharacterRange>* ranges = tree->ranges(); 5291 ZoneList<CharacterRange>* ranges = tree->ranges(zone_);
5259 if (tree->is_negated()) { 5292 if (tree->is_negated()) {
5260 AddInverse(ranges); 5293 AddInverse(ranges);
5261 } else { 5294 } else {
5262 for (int i = 0; i < ranges->length(); i++) 5295 for (int i = 0; i < ranges->length(); i++)
5263 AddRange(ranges->at(i)); 5296 AddRange(ranges->at(i));
5264 } 5297 }
5265 break; 5298 break;
5266 } 5299 }
5267 default: { 5300 default: {
5268 UNIMPLEMENTED(); 5301 UNIMPLEMENTED();
5269 } 5302 }
5270 } 5303 }
5271 } 5304 }
5272 5305
5273 5306
5274 void DispatchTableConstructor::VisitAction(ActionNode* that) { 5307 void DispatchTableConstructor::VisitAction(ActionNode* that) {
5275 RegExpNode* target = that->on_success(); 5308 RegExpNode* target = that->on_success();
5276 target->Accept(this); 5309 target->Accept(this);
5277 } 5310 }
5278 5311
5279 5312
5280 RegExpEngine::CompilationResult RegExpEngine::Compile(RegExpCompileData* data, 5313 RegExpEngine::CompilationResult RegExpEngine::Compile(RegExpCompileData* data,
5281 bool ignore_case, 5314 bool ignore_case,
5282 bool is_multiline, 5315 bool is_multiline,
5283 Handle<String> pattern, 5316 Handle<String> pattern,
5284 bool is_ascii) { 5317 bool is_ascii) {
5318 Isolate* isolate = pattern->GetIsolate();
5285 if ((data->capture_count + 1) * 2 - 1 > RegExpMacroAssembler::kMaxRegister) { 5319 if ((data->capture_count + 1) * 2 - 1 > RegExpMacroAssembler::kMaxRegister) {
5286 return IrregexpRegExpTooBig(); 5320 return IrregexpRegExpTooBig();
5287 } 5321 }
5288 RegExpCompiler compiler(data->capture_count, ignore_case, is_ascii); 5322 RegExpCompiler compiler(isolate, data->capture_count, ignore_case, is_ascii);
5289 // Wrap the body of the regexp in capture #0. 5323 // Wrap the body of the regexp in capture #0.
5290 RegExpNode* captured_body = RegExpCapture::ToNode(data->tree, 5324 RegExpNode* captured_body = RegExpCapture::ToNode(data->tree,
5291 0, 5325 0,
5292 &compiler, 5326 &compiler,
5293 compiler.accept()); 5327 compiler.accept());
5294 RegExpNode* node = captured_body; 5328 RegExpNode* node = captured_body;
5295 bool is_end_anchored = data->tree->IsAnchoredAtEnd(); 5329 bool is_end_anchored = data->tree->IsAnchoredAtEnd();
5296 bool is_start_anchored = data->tree->IsAnchoredAtStart(); 5330 bool is_start_anchored = data->tree->IsAnchoredAtStart();
5297 int max_length = data->tree->max_match(); 5331 int max_length = data->tree->max_match();
5298 if (!is_start_anchored) { 5332 if (!is_start_anchored) {
5299 // Add a .*? at the beginning, outside the body capture, unless 5333 // Add a .*? at the beginning, outside the body capture, unless
5300 // this expression is anchored at the beginning. 5334 // this expression is anchored at the beginning.
5301 RegExpNode* loop_node = 5335 RegExpNode* loop_node =
5302 RegExpQuantifier::ToNode(0, 5336 RegExpQuantifier::ToNode(0,
5303 RegExpTree::kInfinity, 5337 RegExpTree::kInfinity,
5304 false, 5338 false,
5305 new RegExpCharacterClass('*'), 5339 new RegExpCharacterClass('*'),
5306 &compiler, 5340 &compiler,
5307 captured_body, 5341 captured_body,
5308 data->contains_anchor); 5342 data->contains_anchor);
5309 5343
5310 if (data->contains_anchor) { 5344 if (data->contains_anchor) {
5311 // Unroll loop once, to take care of the case that might start 5345 // Unroll loop once, to take care of the case that might start
5312 // at the start of input. 5346 // at the start of input.
5313 ChoiceNode* first_step_node = new ChoiceNode(2); 5347 ChoiceNode* first_step_node = new ChoiceNode(isolate->zone(), 2);
5314 first_step_node->AddAlternative(GuardedAlternative(captured_body)); 5348 first_step_node->AddAlternative(GuardedAlternative(captured_body));
5315 first_step_node->AddAlternative(GuardedAlternative( 5349 first_step_node->AddAlternative(GuardedAlternative(
5316 new TextNode(new RegExpCharacterClass('*'), loop_node))); 5350 new TextNode(isolate->zone(),
5351 new RegExpCharacterClass('*'), loop_node)));
5317 node = first_step_node; 5352 node = first_step_node;
5318 } else { 5353 } else {
5319 node = loop_node; 5354 node = loop_node;
5320 } 5355 }
5321 } 5356 }
5322 data->node = node; 5357 data->node = node;
5323 Analysis analysis(ignore_case, is_ascii); 5358 Analysis analysis(isolate->zone(), ignore_case, is_ascii);
5324 analysis.EnsureAnalyzed(node); 5359 analysis.EnsureAnalyzed(node);
5325 if (analysis.has_failed()) { 5360 if (analysis.has_failed()) {
5326 const char* error_message = analysis.error_message(); 5361 const char* error_message = analysis.error_message();
5327 return CompilationResult(error_message); 5362 return CompilationResult(error_message);
5328 } 5363 }
5329 5364
5330 NodeInfo info = *node->info(); 5365 NodeInfo info = *node->info();
5331 5366
5332 // Create the correct assembler for the architecture. 5367 // Create the correct assembler for the architecture.
5333 #ifndef V8_INTERPRETED_REGEXP 5368 #ifndef V8_INTERPRETED_REGEXP
(...skipping 29 matching lines...) Expand all
5363 } 5398 }
5364 5399
5365 return compiler.Assemble(&macro_assembler, 5400 return compiler.Assemble(&macro_assembler,
5366 node, 5401 node,
5367 data->capture_count, 5402 data->capture_count,
5368 pattern); 5403 pattern);
5369 } 5404 }
5370 5405
5371 5406
5372 }} // namespace v8::internal 5407 }} // namespace v8::internal
OLDNEW
« no previous file with comments | « src/jsregexp.h ('k') | src/list.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698