| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 ®isters_to_pop, | 1202 ®isters_to_pop, |
| 1188 ®isters_to_clear); | 1203 ®isters_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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 5363 } | 5398 } |
| 5364 | 5399 |
| 5365 return compiler.Assemble(¯o_assembler, | 5400 return compiler.Assemble(¯o_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 |
| OLD | NEW |