| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 802 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 813 // to that trace. The code generator therefore has the ability to generate | 813 // to that trace. The code generator therefore has the ability to generate |
| 814 // code for each node several times. In order to limit the size of the | 814 // code for each node several times. In order to limit the size of the |
| 815 // generated code there is an arbitrary limit on how many specialized sets of | 815 // generated code there is an arbitrary limit on how many specialized sets of |
| 816 // code may be generated for a given node. If the limit is reached, the | 816 // code may be generated for a given node. If the limit is reached, the |
| 817 // trace is flushed and a generic version of the code for a node is emitted. | 817 // trace is flushed and a generic version of the code for a node is emitted. |
| 818 // This is subsequently used for that node. The code emitted for non-generic | 818 // This is subsequently used for that node. The code emitted for non-generic |
| 819 // trace is not recorded in the node and so it cannot currently be reused in | 819 // trace is not recorded in the node and so it cannot currently be reused in |
| 820 // the event that code generation is requested for an identical trace. | 820 // the event that code generation is requested for an identical trace. |
| 821 | 821 |
| 822 | 822 |
| 823 void RegExpTree::AppendToText(RegExpText* text) { | 823 void RegExpTree::AppendToText(RegExpText* text, Zone* zone) { |
| 824 UNREACHABLE(); | 824 UNREACHABLE(); |
| 825 } | 825 } |
| 826 | 826 |
| 827 | 827 |
| 828 void RegExpAtom::AppendToText(RegExpText* text) { | 828 void RegExpAtom::AppendToText(RegExpText* text, Zone* zone) { |
| 829 text->AddElement(TextElement::Atom(this)); | 829 text->AddElement(TextElement::Atom(this), zone); |
| 830 } | 830 } |
| 831 | 831 |
| 832 | 832 |
| 833 void RegExpCharacterClass::AppendToText(RegExpText* text) { | 833 void RegExpCharacterClass::AppendToText(RegExpText* text, Zone* zone) { |
| 834 text->AddElement(TextElement::CharClass(this)); | 834 text->AddElement(TextElement::CharClass(this), zone); |
| 835 } | 835 } |
| 836 | 836 |
| 837 | 837 |
| 838 void RegExpText::AppendToText(RegExpText* text) { | 838 void RegExpText::AppendToText(RegExpText* text, Zone* zone) { |
| 839 for (int i = 0; i < elements()->length(); i++) | 839 for (int i = 0; i < elements()->length(); i++) |
| 840 text->AddElement(elements()->at(i)); | 840 text->AddElement(elements()->at(i), zone); |
| 841 } | 841 } |
| 842 | 842 |
| 843 | 843 |
| 844 TextElement TextElement::Atom(RegExpAtom* atom) { | 844 TextElement TextElement::Atom(RegExpAtom* atom) { |
| 845 TextElement result = TextElement(ATOM); | 845 TextElement result = TextElement(ATOM); |
| 846 result.data.u_atom = atom; | 846 result.data.u_atom = atom; |
| 847 return result; | 847 return result; |
| 848 } | 848 } |
| 849 | 849 |
| 850 | 850 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 861 return data.u_atom->length(); | 861 return data.u_atom->length(); |
| 862 } else { | 862 } else { |
| 863 ASSERT(type == CHAR_CLASS); | 863 ASSERT(type == CHAR_CLASS); |
| 864 return 1; | 864 return 1; |
| 865 } | 865 } |
| 866 } | 866 } |
| 867 | 867 |
| 868 | 868 |
| 869 DispatchTable* ChoiceNode::GetTable(bool ignore_case) { | 869 DispatchTable* ChoiceNode::GetTable(bool ignore_case) { |
| 870 if (table_ == NULL) { | 870 if (table_ == NULL) { |
| 871 table_ = new DispatchTable(); | 871 table_ = new(zone()) DispatchTable(zone()); |
| 872 DispatchTableConstructor cons(table_, ignore_case); | 872 DispatchTableConstructor cons(table_, ignore_case, zone()); |
| 873 cons.BuildTable(this); | 873 cons.BuildTable(this); |
| 874 } | 874 } |
| 875 return table_; | 875 return table_; |
| 876 } | 876 } |
| 877 | 877 |
| 878 | 878 |
| 879 class FrequencyCollator { | 879 class FrequencyCollator { |
| 880 public: | 880 public: |
| 881 FrequencyCollator() : total_samples_(0) { | 881 FrequencyCollator() : total_samples_(0) { |
| 882 for (int i = 0; i < RegExpMacroAssembler::kTableSize; i++) { | 882 for (int i = 0; i < RegExpMacroAssembler::kTableSize; i++) { |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 959 | 959 |
| 960 inline bool ignore_case() { return ignore_case_; } | 960 inline bool ignore_case() { return ignore_case_; } |
| 961 inline bool ascii() { return ascii_; } | 961 inline bool ascii() { return ascii_; } |
| 962 FrequencyCollator* frequency_collator() { return &frequency_collator_; } | 962 FrequencyCollator* frequency_collator() { return &frequency_collator_; } |
| 963 | 963 |
| 964 int current_expansion_factor() { return current_expansion_factor_; } | 964 int current_expansion_factor() { return current_expansion_factor_; } |
| 965 void set_current_expansion_factor(int value) { | 965 void set_current_expansion_factor(int value) { |
| 966 current_expansion_factor_ = value; | 966 current_expansion_factor_ = value; |
| 967 } | 967 } |
| 968 | 968 |
| 969 Zone* zone() { return zone_; } | 969 Zone* zone() const { return zone_; } |
| 970 | 970 |
| 971 static const int kNoRegister = -1; | 971 static const int kNoRegister = -1; |
| 972 | 972 |
| 973 private: | 973 private: |
| 974 EndNode* accept_; | 974 EndNode* accept_; |
| 975 int next_register_; | 975 int next_register_; |
| 976 List<RegExpNode*>* work_list_; | 976 List<RegExpNode*>* work_list_; |
| 977 int recursion_depth_; | 977 int recursion_depth_; |
| 978 RegExpMacroAssembler* macro_assembler_; | 978 RegExpMacroAssembler* macro_assembler_; |
| 979 bool ignore_case_; | 979 bool ignore_case_; |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1007 Zone* zone) | 1007 Zone* zone) |
| 1008 : next_register_(2 * (capture_count + 1)), | 1008 : next_register_(2 * (capture_count + 1)), |
| 1009 work_list_(NULL), | 1009 work_list_(NULL), |
| 1010 recursion_depth_(0), | 1010 recursion_depth_(0), |
| 1011 ignore_case_(ignore_case), | 1011 ignore_case_(ignore_case), |
| 1012 ascii_(ascii), | 1012 ascii_(ascii), |
| 1013 reg_exp_too_big_(false), | 1013 reg_exp_too_big_(false), |
| 1014 current_expansion_factor_(1), | 1014 current_expansion_factor_(1), |
| 1015 frequency_collator_(), | 1015 frequency_collator_(), |
| 1016 zone_(zone) { | 1016 zone_(zone) { |
| 1017 accept_ = new EndNode(EndNode::ACCEPT, zone); | 1017 accept_ = new(zone) EndNode(EndNode::ACCEPT, zone); |
| 1018 ASSERT(next_register_ - 1 <= RegExpMacroAssembler::kMaxRegister); | 1018 ASSERT(next_register_ - 1 <= RegExpMacroAssembler::kMaxRegister); |
| 1019 } | 1019 } |
| 1020 | 1020 |
| 1021 | 1021 |
| 1022 RegExpEngine::CompilationResult RegExpCompiler::Assemble( | 1022 RegExpEngine::CompilationResult RegExpCompiler::Assemble( |
| 1023 RegExpMacroAssembler* macro_assembler, | 1023 RegExpMacroAssembler* macro_assembler, |
| 1024 RegExpNode* start, | 1024 RegExpNode* start, |
| 1025 int capture_count, | 1025 int capture_count, |
| 1026 Handle<String> pattern) { | 1026 Handle<String> pattern) { |
| 1027 Heap* heap = pattern->GetHeap(); | 1027 Heap* heap = pattern->GetHeap(); |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1103 return true; | 1103 return true; |
| 1104 } else { | 1104 } else { |
| 1105 return false; | 1105 return false; |
| 1106 } | 1106 } |
| 1107 } | 1107 } |
| 1108 } | 1108 } |
| 1109 return false; | 1109 return false; |
| 1110 } | 1110 } |
| 1111 | 1111 |
| 1112 | 1112 |
| 1113 int Trace::FindAffectedRegisters(OutSet* affected_registers) { | 1113 int Trace::FindAffectedRegisters(OutSet* affected_registers, |
| 1114 Zone* zone) { |
| 1114 int max_register = RegExpCompiler::kNoRegister; | 1115 int max_register = RegExpCompiler::kNoRegister; |
| 1115 for (DeferredAction* action = actions_; | 1116 for (DeferredAction* action = actions_; |
| 1116 action != NULL; | 1117 action != NULL; |
| 1117 action = action->next()) { | 1118 action = action->next()) { |
| 1118 if (action->type() == ActionNode::CLEAR_CAPTURES) { | 1119 if (action->type() == ActionNode::CLEAR_CAPTURES) { |
| 1119 Interval range = static_cast<DeferredClearCaptures*>(action)->range(); | 1120 Interval range = static_cast<DeferredClearCaptures*>(action)->range(); |
| 1120 for (int i = range.from(); i <= range.to(); i++) | 1121 for (int i = range.from(); i <= range.to(); i++) |
| 1121 affected_registers->Set(i); | 1122 affected_registers->Set(i, zone); |
| 1122 if (range.to() > max_register) max_register = range.to(); | 1123 if (range.to() > max_register) max_register = range.to(); |
| 1123 } else { | 1124 } else { |
| 1124 affected_registers->Set(action->reg()); | 1125 affected_registers->Set(action->reg(), zone); |
| 1125 if (action->reg() > max_register) max_register = action->reg(); | 1126 if (action->reg() > max_register) max_register = action->reg(); |
| 1126 } | 1127 } |
| 1127 } | 1128 } |
| 1128 return max_register; | 1129 return max_register; |
| 1129 } | 1130 } |
| 1130 | 1131 |
| 1131 | 1132 |
| 1132 void Trace::RestoreAffectedRegisters(RegExpMacroAssembler* assembler, | 1133 void Trace::RestoreAffectedRegisters(RegExpMacroAssembler* assembler, |
| 1133 int max_register, | 1134 int max_register, |
| 1134 OutSet& registers_to_pop, | 1135 OutSet& registers_to_pop, |
| 1135 OutSet& registers_to_clear) { | 1136 OutSet& registers_to_clear) { |
| 1136 for (int reg = max_register; reg >= 0; reg--) { | 1137 for (int reg = max_register; reg >= 0; reg--) { |
| 1137 if (registers_to_pop.Get(reg)) assembler->PopRegister(reg); | 1138 if (registers_to_pop.Get(reg)) assembler->PopRegister(reg); |
| 1138 else if (registers_to_clear.Get(reg)) { | 1139 else if (registers_to_clear.Get(reg)) { |
| 1139 int clear_to = reg; | 1140 int clear_to = reg; |
| 1140 while (reg > 0 && registers_to_clear.Get(reg - 1)) { | 1141 while (reg > 0 && registers_to_clear.Get(reg - 1)) { |
| 1141 reg--; | 1142 reg--; |
| 1142 } | 1143 } |
| 1143 assembler->ClearRegisters(reg, clear_to); | 1144 assembler->ClearRegisters(reg, clear_to); |
| 1144 } | 1145 } |
| 1145 } | 1146 } |
| 1146 } | 1147 } |
| 1147 | 1148 |
| 1148 | 1149 |
| 1149 void Trace::PerformDeferredActions(RegExpMacroAssembler* assembler, | 1150 void Trace::PerformDeferredActions(RegExpMacroAssembler* assembler, |
| 1150 int max_register, | 1151 int max_register, |
| 1151 OutSet& affected_registers, | 1152 OutSet& affected_registers, |
| 1152 OutSet* registers_to_pop, | 1153 OutSet* registers_to_pop, |
| 1153 OutSet* registers_to_clear) { | 1154 OutSet* registers_to_clear, |
| 1155 Zone* zone) { |
| 1154 // The "+1" is to avoid a push_limit of zero if stack_limit_slack() is 1. | 1156 // The "+1" is to avoid a push_limit of zero if stack_limit_slack() is 1. |
| 1155 const int push_limit = (assembler->stack_limit_slack() + 1) / 2; | 1157 const int push_limit = (assembler->stack_limit_slack() + 1) / 2; |
| 1156 | 1158 |
| 1157 // Count pushes performed to force a stack limit check occasionally. | 1159 // Count pushes performed to force a stack limit check occasionally. |
| 1158 int pushes = 0; | 1160 int pushes = 0; |
| 1159 | 1161 |
| 1160 for (int reg = 0; reg <= max_register; reg++) { | 1162 for (int reg = 0; reg <= max_register; reg++) { |
| 1161 if (!affected_registers.Get(reg)) { | 1163 if (!affected_registers.Get(reg)) { |
| 1162 continue; | 1164 continue; |
| 1163 } | 1165 } |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1249 if (undo_action == RESTORE) { | 1251 if (undo_action == RESTORE) { |
| 1250 pushes++; | 1252 pushes++; |
| 1251 RegExpMacroAssembler::StackCheckFlag stack_check = | 1253 RegExpMacroAssembler::StackCheckFlag stack_check = |
| 1252 RegExpMacroAssembler::kNoStackLimitCheck; | 1254 RegExpMacroAssembler::kNoStackLimitCheck; |
| 1253 if (pushes == push_limit) { | 1255 if (pushes == push_limit) { |
| 1254 stack_check = RegExpMacroAssembler::kCheckStackLimit; | 1256 stack_check = RegExpMacroAssembler::kCheckStackLimit; |
| 1255 pushes = 0; | 1257 pushes = 0; |
| 1256 } | 1258 } |
| 1257 | 1259 |
| 1258 assembler->PushRegister(reg, stack_check); | 1260 assembler->PushRegister(reg, stack_check); |
| 1259 registers_to_pop->Set(reg); | 1261 registers_to_pop->Set(reg, zone); |
| 1260 } else if (undo_action == CLEAR) { | 1262 } else if (undo_action == CLEAR) { |
| 1261 registers_to_clear->Set(reg); | 1263 registers_to_clear->Set(reg, zone); |
| 1262 } | 1264 } |
| 1263 // Perform the chronologically last action (or accumulated increment) | 1265 // Perform the chronologically last action (or accumulated increment) |
| 1264 // for the register. | 1266 // for the register. |
| 1265 if (store_position != -1) { | 1267 if (store_position != -1) { |
| 1266 assembler->WriteCurrentPositionToRegister(reg, store_position); | 1268 assembler->WriteCurrentPositionToRegister(reg, store_position); |
| 1267 } else if (clear) { | 1269 } else if (clear) { |
| 1268 assembler->ClearRegisters(reg, reg); | 1270 assembler->ClearRegisters(reg, reg); |
| 1269 } else if (absolute) { | 1271 } else if (absolute) { |
| 1270 assembler->SetRegister(reg, value); | 1272 assembler->SetRegister(reg, value); |
| 1271 } else if (value != 0) { | 1273 } else if (value != 0) { |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1297 // Generate deferred actions here along with code to undo them again. | 1299 // Generate deferred actions here along with code to undo them again. |
| 1298 OutSet affected_registers; | 1300 OutSet affected_registers; |
| 1299 | 1301 |
| 1300 if (backtrack() != NULL) { | 1302 if (backtrack() != NULL) { |
| 1301 // Here we have a concrete backtrack location. These are set up by choice | 1303 // Here we have a concrete backtrack location. These are set up by choice |
| 1302 // nodes and so they indicate that we have a deferred save of the current | 1304 // nodes and so they indicate that we have a deferred save of the current |
| 1303 // position which we may need to emit here. | 1305 // position which we may need to emit here. |
| 1304 assembler->PushCurrentPosition(); | 1306 assembler->PushCurrentPosition(); |
| 1305 } | 1307 } |
| 1306 | 1308 |
| 1307 int max_register = FindAffectedRegisters(&affected_registers); | 1309 int max_register = FindAffectedRegisters(&affected_registers, |
| 1310 compiler->zone()); |
| 1308 OutSet registers_to_pop; | 1311 OutSet registers_to_pop; |
| 1309 OutSet registers_to_clear; | 1312 OutSet registers_to_clear; |
| 1310 PerformDeferredActions(assembler, | 1313 PerformDeferredActions(assembler, |
| 1311 max_register, | 1314 max_register, |
| 1312 affected_registers, | 1315 affected_registers, |
| 1313 ®isters_to_pop, | 1316 ®isters_to_pop, |
| 1314 ®isters_to_clear); | 1317 ®isters_to_clear, |
| 1318 compiler->zone()); |
| 1315 if (cp_offset_ != 0) { | 1319 if (cp_offset_ != 0) { |
| 1316 assembler->AdvanceCurrentPosition(cp_offset_); | 1320 assembler->AdvanceCurrentPosition(cp_offset_); |
| 1317 } | 1321 } |
| 1318 | 1322 |
| 1319 // Create a new trivial state and generate the node with that. | 1323 // Create a new trivial state and generate the node with that. |
| 1320 Label undo; | 1324 Label undo; |
| 1321 assembler->PushBacktrack(&undo); | 1325 assembler->PushBacktrack(&undo); |
| 1322 Trace new_state; | 1326 Trace new_state; |
| 1323 successor->Emit(compiler, &new_state); | 1327 successor->Emit(compiler, &new_state); |
| 1324 | 1328 |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1381 assembler->GoTo(trace->backtrack()); | 1385 assembler->GoTo(trace->backtrack()); |
| 1382 return; | 1386 return; |
| 1383 case NEGATIVE_SUBMATCH_SUCCESS: | 1387 case NEGATIVE_SUBMATCH_SUCCESS: |
| 1384 // This case is handled in a different virtual method. | 1388 // This case is handled in a different virtual method. |
| 1385 UNREACHABLE(); | 1389 UNREACHABLE(); |
| 1386 } | 1390 } |
| 1387 UNIMPLEMENTED(); | 1391 UNIMPLEMENTED(); |
| 1388 } | 1392 } |
| 1389 | 1393 |
| 1390 | 1394 |
| 1391 void GuardedAlternative::AddGuard(Guard* guard) { | 1395 void GuardedAlternative::AddGuard(Guard* guard, Zone* zone) { |
| 1392 if (guards_ == NULL) | 1396 if (guards_ == NULL) |
| 1393 guards_ = new ZoneList<Guard*>(1); | 1397 guards_ = new(zone) ZoneList<Guard*>(1, zone); |
| 1394 guards_->Add(guard); | 1398 guards_->Add(guard, zone); |
| 1395 } | 1399 } |
| 1396 | 1400 |
| 1397 | 1401 |
| 1398 ActionNode* ActionNode::SetRegister(int reg, | 1402 ActionNode* ActionNode::SetRegister(int reg, |
| 1399 int val, | 1403 int val, |
| 1400 RegExpNode* on_success) { | 1404 RegExpNode* on_success) { |
| 1401 ActionNode* result = new ActionNode(SET_REGISTER, on_success); | 1405 ActionNode* result = |
| 1406 new(on_success->zone()) ActionNode(SET_REGISTER, on_success); |
| 1402 result->data_.u_store_register.reg = reg; | 1407 result->data_.u_store_register.reg = reg; |
| 1403 result->data_.u_store_register.value = val; | 1408 result->data_.u_store_register.value = val; |
| 1404 return result; | 1409 return result; |
| 1405 } | 1410 } |
| 1406 | 1411 |
| 1407 | 1412 |
| 1408 ActionNode* ActionNode::IncrementRegister(int reg, RegExpNode* on_success) { | 1413 ActionNode* ActionNode::IncrementRegister(int reg, RegExpNode* on_success) { |
| 1409 ActionNode* result = new ActionNode(INCREMENT_REGISTER, on_success); | 1414 ActionNode* result = |
| 1415 new(on_success->zone()) ActionNode(INCREMENT_REGISTER, on_success); |
| 1410 result->data_.u_increment_register.reg = reg; | 1416 result->data_.u_increment_register.reg = reg; |
| 1411 return result; | 1417 return result; |
| 1412 } | 1418 } |
| 1413 | 1419 |
| 1414 | 1420 |
| 1415 ActionNode* ActionNode::StorePosition(int reg, | 1421 ActionNode* ActionNode::StorePosition(int reg, |
| 1416 bool is_capture, | 1422 bool is_capture, |
| 1417 RegExpNode* on_success) { | 1423 RegExpNode* on_success) { |
| 1418 ActionNode* result = new ActionNode(STORE_POSITION, on_success); | 1424 ActionNode* result = |
| 1425 new(on_success->zone()) ActionNode(STORE_POSITION, on_success); |
| 1419 result->data_.u_position_register.reg = reg; | 1426 result->data_.u_position_register.reg = reg; |
| 1420 result->data_.u_position_register.is_capture = is_capture; | 1427 result->data_.u_position_register.is_capture = is_capture; |
| 1421 return result; | 1428 return result; |
| 1422 } | 1429 } |
| 1423 | 1430 |
| 1424 | 1431 |
| 1425 ActionNode* ActionNode::ClearCaptures(Interval range, | 1432 ActionNode* ActionNode::ClearCaptures(Interval range, |
| 1426 RegExpNode* on_success) { | 1433 RegExpNode* on_success) { |
| 1427 ActionNode* result = new ActionNode(CLEAR_CAPTURES, on_success); | 1434 ActionNode* result = |
| 1435 new(on_success->zone()) ActionNode(CLEAR_CAPTURES, on_success); |
| 1428 result->data_.u_clear_captures.range_from = range.from(); | 1436 result->data_.u_clear_captures.range_from = range.from(); |
| 1429 result->data_.u_clear_captures.range_to = range.to(); | 1437 result->data_.u_clear_captures.range_to = range.to(); |
| 1430 return result; | 1438 return result; |
| 1431 } | 1439 } |
| 1432 | 1440 |
| 1433 | 1441 |
| 1434 ActionNode* ActionNode::BeginSubmatch(int stack_reg, | 1442 ActionNode* ActionNode::BeginSubmatch(int stack_reg, |
| 1435 int position_reg, | 1443 int position_reg, |
| 1436 RegExpNode* on_success) { | 1444 RegExpNode* on_success) { |
| 1437 ActionNode* result = new ActionNode(BEGIN_SUBMATCH, on_success); | 1445 ActionNode* result = |
| 1446 new(on_success->zone()) ActionNode(BEGIN_SUBMATCH, on_success); |
| 1438 result->data_.u_submatch.stack_pointer_register = stack_reg; | 1447 result->data_.u_submatch.stack_pointer_register = stack_reg; |
| 1439 result->data_.u_submatch.current_position_register = position_reg; | 1448 result->data_.u_submatch.current_position_register = position_reg; |
| 1440 return result; | 1449 return result; |
| 1441 } | 1450 } |
| 1442 | 1451 |
| 1443 | 1452 |
| 1444 ActionNode* ActionNode::PositiveSubmatchSuccess(int stack_reg, | 1453 ActionNode* ActionNode::PositiveSubmatchSuccess(int stack_reg, |
| 1445 int position_reg, | 1454 int position_reg, |
| 1446 int clear_register_count, | 1455 int clear_register_count, |
| 1447 int clear_register_from, | 1456 int clear_register_from, |
| 1448 RegExpNode* on_success) { | 1457 RegExpNode* on_success) { |
| 1449 ActionNode* result = new ActionNode(POSITIVE_SUBMATCH_SUCCESS, on_success); | 1458 ActionNode* result = |
| 1459 new(on_success->zone()) ActionNode(POSITIVE_SUBMATCH_SUCCESS, on_success); |
| 1450 result->data_.u_submatch.stack_pointer_register = stack_reg; | 1460 result->data_.u_submatch.stack_pointer_register = stack_reg; |
| 1451 result->data_.u_submatch.current_position_register = position_reg; | 1461 result->data_.u_submatch.current_position_register = position_reg; |
| 1452 result->data_.u_submatch.clear_register_count = clear_register_count; | 1462 result->data_.u_submatch.clear_register_count = clear_register_count; |
| 1453 result->data_.u_submatch.clear_register_from = clear_register_from; | 1463 result->data_.u_submatch.clear_register_from = clear_register_from; |
| 1454 return result; | 1464 return result; |
| 1455 } | 1465 } |
| 1456 | 1466 |
| 1457 | 1467 |
| 1458 ActionNode* ActionNode::EmptyMatchCheck(int start_register, | 1468 ActionNode* ActionNode::EmptyMatchCheck(int start_register, |
| 1459 int repetition_register, | 1469 int repetition_register, |
| 1460 int repetition_limit, | 1470 int repetition_limit, |
| 1461 RegExpNode* on_success) { | 1471 RegExpNode* on_success) { |
| 1462 ActionNode* result = new ActionNode(EMPTY_MATCH_CHECK, on_success); | 1472 ActionNode* result = |
| 1473 new(on_success->zone()) ActionNode(EMPTY_MATCH_CHECK, on_success); |
| 1463 result->data_.u_empty_match_check.start_register = start_register; | 1474 result->data_.u_empty_match_check.start_register = start_register; |
| 1464 result->data_.u_empty_match_check.repetition_register = repetition_register; | 1475 result->data_.u_empty_match_check.repetition_register = repetition_register; |
| 1465 result->data_.u_empty_match_check.repetition_limit = repetition_limit; | 1476 result->data_.u_empty_match_check.repetition_limit = repetition_limit; |
| 1466 return result; | 1477 return result; |
| 1467 } | 1478 } |
| 1468 | 1479 |
| 1469 | 1480 |
| 1470 #define DEFINE_ACCEPT(Type) \ | 1481 #define DEFINE_ACCEPT(Type) \ |
| 1471 void Type##Node::Accept(NodeVisitor* visitor) { \ | 1482 void Type##Node::Accept(NodeVisitor* visitor) { \ |
| 1472 visitor->Visit##Type(this); \ | 1483 visitor->Visit##Type(this); \ |
| (...skipping 559 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2032 } | 2043 } |
| 2033 } | 2044 } |
| 2034 | 2045 |
| 2035 | 2046 |
| 2036 static void EmitCharClass(RegExpMacroAssembler* macro_assembler, | 2047 static void EmitCharClass(RegExpMacroAssembler* macro_assembler, |
| 2037 RegExpCharacterClass* cc, | 2048 RegExpCharacterClass* cc, |
| 2038 bool ascii, | 2049 bool ascii, |
| 2039 Label* on_failure, | 2050 Label* on_failure, |
| 2040 int cp_offset, | 2051 int cp_offset, |
| 2041 bool check_offset, | 2052 bool check_offset, |
| 2042 bool preloaded) { | 2053 bool preloaded, |
| 2043 ZoneList<CharacterRange>* ranges = cc->ranges(); | 2054 Zone* zone) { |
| 2055 ZoneList<CharacterRange>* ranges = cc->ranges(zone); |
| 2044 if (!CharacterRange::IsCanonical(ranges)) { | 2056 if (!CharacterRange::IsCanonical(ranges)) { |
| 2045 CharacterRange::Canonicalize(ranges); | 2057 CharacterRange::Canonicalize(ranges); |
| 2046 } | 2058 } |
| 2047 | 2059 |
| 2048 int max_char; | 2060 int max_char; |
| 2049 if (ascii) { | 2061 if (ascii) { |
| 2050 max_char = String::kMaxAsciiCharCode; | 2062 max_char = String::kMaxAsciiCharCode; |
| 2051 } else { | 2063 } else { |
| 2052 max_char = String::kMaxUtf16CodeUnit; | 2064 max_char = String::kMaxUtf16CodeUnit; |
| 2053 } | 2065 } |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2092 if (check_offset) { | 2104 if (check_offset) { |
| 2093 macro_assembler->CheckPosition(cp_offset, on_failure); | 2105 macro_assembler->CheckPosition(cp_offset, on_failure); |
| 2094 } | 2106 } |
| 2095 return; | 2107 return; |
| 2096 } | 2108 } |
| 2097 | 2109 |
| 2098 if (!preloaded) { | 2110 if (!preloaded) { |
| 2099 macro_assembler->LoadCurrentCharacter(cp_offset, on_failure, check_offset); | 2111 macro_assembler->LoadCurrentCharacter(cp_offset, on_failure, check_offset); |
| 2100 } | 2112 } |
| 2101 | 2113 |
| 2102 if (cc->is_standard() && | 2114 if (cc->is_standard(zone) && |
| 2103 macro_assembler->CheckSpecialCharacterClass(cc->standard_type(), | 2115 macro_assembler->CheckSpecialCharacterClass(cc->standard_type(), |
| 2104 on_failure)) { | 2116 on_failure)) { |
| 2105 return; | 2117 return; |
| 2106 } | 2118 } |
| 2107 | 2119 |
| 2108 | 2120 |
| 2109 // A new list with ascending entries. Each entry is a code unit | 2121 // A new list with ascending entries. Each entry is a code unit |
| 2110 // where there is a boundary between code units that are part of | 2122 // where there is a boundary between code units that are part of |
| 2111 // the class and code units that are not. Normally we insert an | 2123 // the class and code units that are not. Normally we insert an |
| 2112 // entry at zero which goes to the failure label, but if there | 2124 // entry at zero which goes to the failure label, but if there |
| 2113 // was already one there we fall through for success on that entry. | 2125 // was already one there we fall through for success on that entry. |
| 2114 // Subsequent entries have alternating meaning (success/failure). | 2126 // Subsequent entries have alternating meaning (success/failure). |
| 2115 ZoneList<int>* range_boundaries = new ZoneList<int>(last_valid_range); | 2127 ZoneList<int>* range_boundaries = |
| 2128 new(zone) ZoneList<int>(last_valid_range, zone); |
| 2116 | 2129 |
| 2117 bool zeroth_entry_is_failure = !cc->is_negated(); | 2130 bool zeroth_entry_is_failure = !cc->is_negated(); |
| 2118 | 2131 |
| 2119 for (int i = 0; i <= last_valid_range; i++) { | 2132 for (int i = 0; i <= last_valid_range; i++) { |
| 2120 CharacterRange& range = ranges->at(i); | 2133 CharacterRange& range = ranges->at(i); |
| 2121 if (range.from() == 0) { | 2134 if (range.from() == 0) { |
| 2122 ASSERT_EQ(i, 0); | 2135 ASSERT_EQ(i, 0); |
| 2123 zeroth_entry_is_failure = !zeroth_entry_is_failure; | 2136 zeroth_entry_is_failure = !zeroth_entry_is_failure; |
| 2124 } else { | 2137 } else { |
| 2125 range_boundaries->Add(range.from()); | 2138 range_boundaries->Add(range.from(), zone); |
| 2126 } | 2139 } |
| 2127 range_boundaries->Add(range.to() + 1); | 2140 range_boundaries->Add(range.to() + 1, zone); |
| 2128 } | 2141 } |
| 2129 int end_index = range_boundaries->length() - 1; | 2142 int end_index = range_boundaries->length() - 1; |
| 2130 if (range_boundaries->at(end_index) > max_char) { | 2143 if (range_boundaries->at(end_index) > max_char) { |
| 2131 end_index--; | 2144 end_index--; |
| 2132 } | 2145 } |
| 2133 | 2146 |
| 2134 Label fall_through; | 2147 Label fall_through; |
| 2135 GenerateBranches(macro_assembler, | 2148 GenerateBranches(macro_assembler, |
| 2136 range_boundaries, | 2149 range_boundaries, |
| 2137 0, // start_index. | 2150 0, // start_index. |
| (...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2515 characters_filled_in++; | 2528 characters_filled_in++; |
| 2516 ASSERT(characters_filled_in <= details->characters()); | 2529 ASSERT(characters_filled_in <= details->characters()); |
| 2517 if (characters_filled_in == details->characters()) { | 2530 if (characters_filled_in == details->characters()) { |
| 2518 return; | 2531 return; |
| 2519 } | 2532 } |
| 2520 } | 2533 } |
| 2521 } else { | 2534 } else { |
| 2522 QuickCheckDetails::Position* pos = | 2535 QuickCheckDetails::Position* pos = |
| 2523 details->positions(characters_filled_in); | 2536 details->positions(characters_filled_in); |
| 2524 RegExpCharacterClass* tree = elm.data.u_char_class; | 2537 RegExpCharacterClass* tree = elm.data.u_char_class; |
| 2525 ZoneList<CharacterRange>* ranges = tree->ranges(); | 2538 ZoneList<CharacterRange>* ranges = tree->ranges(zone()); |
| 2526 if (tree->is_negated()) { | 2539 if (tree->is_negated()) { |
| 2527 // A quick check uses multi-character mask and compare. There is no | 2540 // A quick check uses multi-character mask and compare. There is no |
| 2528 // useful way to incorporate a negative char class into this scheme | 2541 // useful way to incorporate a negative char class into this scheme |
| 2529 // so we just conservatively create a mask and value that will always | 2542 // so we just conservatively create a mask and value that will always |
| 2530 // succeed. | 2543 // succeed. |
| 2531 pos->mask = 0; | 2544 pos->mask = 0; |
| 2532 pos->value = 0; | 2545 pos->value = 0; |
| 2533 } else { | 2546 } else { |
| 2534 int first_range = 0; | 2547 int first_range = 0; |
| 2535 while (ranges->at(first_range).from() > char_mask) { | 2548 while (ranges->at(first_range).from() > char_mask) { |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2700 // We don't need special handling for case independence | 2713 // We don't need special handling for case independence |
| 2701 // because of the rule that case independence cannot make | 2714 // because of the rule that case independence cannot make |
| 2702 // a non-ASCII character match an ASCII character. | 2715 // a non-ASCII character match an ASCII character. |
| 2703 if (quarks[j] > String::kMaxAsciiCharCode) { | 2716 if (quarks[j] > String::kMaxAsciiCharCode) { |
| 2704 return set_replacement(NULL); | 2717 return set_replacement(NULL); |
| 2705 } | 2718 } |
| 2706 } | 2719 } |
| 2707 } else { | 2720 } else { |
| 2708 ASSERT(elm.type == TextElement::CHAR_CLASS); | 2721 ASSERT(elm.type == TextElement::CHAR_CLASS); |
| 2709 RegExpCharacterClass* cc = elm.data.u_char_class; | 2722 RegExpCharacterClass* cc = elm.data.u_char_class; |
| 2710 ZoneList<CharacterRange>* ranges = cc->ranges(); | 2723 ZoneList<CharacterRange>* ranges = cc->ranges(zone()); |
| 2711 if (!CharacterRange::IsCanonical(ranges)) { | 2724 if (!CharacterRange::IsCanonical(ranges)) { |
| 2712 CharacterRange::Canonicalize(ranges); | 2725 CharacterRange::Canonicalize(ranges); |
| 2713 } | 2726 } |
| 2714 // Now they are in order so we only need to look at the first. | 2727 // Now they are in order so we only need to look at the first. |
| 2715 int range_count = ranges->length(); | 2728 int range_count = ranges->length(); |
| 2716 if (cc->is_negated()) { | 2729 if (cc->is_negated()) { |
| 2717 if (range_count != 0 && | 2730 if (range_count != 0 && |
| 2718 ranges->at(0).from() == 0 && | 2731 ranges->at(0).from() == 0 && |
| 2719 ranges->at(0).to() >= String::kMaxAsciiCharCode) { | 2732 ranges->at(0).to() >= String::kMaxAsciiCharCode) { |
| 2720 return set_replacement(NULL); | 2733 return set_replacement(NULL); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2768 } | 2781 } |
| 2769 if (surviving < 2) return set_replacement(survivor); | 2782 if (surviving < 2) return set_replacement(survivor); |
| 2770 | 2783 |
| 2771 set_replacement(this); | 2784 set_replacement(this); |
| 2772 if (surviving == choice_count) { | 2785 if (surviving == choice_count) { |
| 2773 return this; | 2786 return this; |
| 2774 } | 2787 } |
| 2775 // Only some of the nodes survived the filtering. We need to rebuild the | 2788 // Only some of the nodes survived the filtering. We need to rebuild the |
| 2776 // alternatives list. | 2789 // alternatives list. |
| 2777 ZoneList<GuardedAlternative>* new_alternatives = | 2790 ZoneList<GuardedAlternative>* new_alternatives = |
| 2778 new ZoneList<GuardedAlternative>(surviving); | 2791 new(zone()) ZoneList<GuardedAlternative>(surviving, zone()); |
| 2779 for (int i = 0; i < choice_count; i++) { | 2792 for (int i = 0; i < choice_count; i++) { |
| 2780 RegExpNode* replacement = | 2793 RegExpNode* replacement = |
| 2781 alternatives_->at(i).node()->FilterASCII(depth - 1); | 2794 alternatives_->at(i).node()->FilterASCII(depth - 1); |
| 2782 if (replacement != NULL) { | 2795 if (replacement != NULL) { |
| 2783 alternatives_->at(i).set_node(replacement); | 2796 alternatives_->at(i).set_node(replacement); |
| 2784 new_alternatives->Add(alternatives_->at(i)); | 2797 new_alternatives->Add(alternatives_->at(i), zone()); |
| 2785 } | 2798 } |
| 2786 } | 2799 } |
| 2787 alternatives_ = new_alternatives; | 2800 alternatives_ = new_alternatives; |
| 2788 return this; | 2801 return this; |
| 2789 } | 2802 } |
| 2790 | 2803 |
| 2791 | 2804 |
| 2792 RegExpNode* NegativeLookaheadChoiceNode::FilterASCII(int depth) { | 2805 RegExpNode* NegativeLookaheadChoiceNode::FilterASCII(int depth) { |
| 2793 if (info()->replacement_calculated) return replacement(); | 2806 if (info()->replacement_calculated) return replacement(); |
| 2794 if (depth < 0) return this; | 2807 if (depth < 0) return this; |
| (...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2931 RegExpMacroAssembler* assembler = compiler->macro_assembler(); | 2944 RegExpMacroAssembler* assembler = compiler->macro_assembler(); |
| 2932 Trace::TriBool next_is_word_character = Trace::UNKNOWN; | 2945 Trace::TriBool next_is_word_character = Trace::UNKNOWN; |
| 2933 bool not_at_start = (trace->at_start() == Trace::FALSE); | 2946 bool not_at_start = (trace->at_start() == Trace::FALSE); |
| 2934 BoyerMooreLookahead* lookahead = bm_info(not_at_start); | 2947 BoyerMooreLookahead* lookahead = bm_info(not_at_start); |
| 2935 if (lookahead == NULL) { | 2948 if (lookahead == NULL) { |
| 2936 int eats_at_least = | 2949 int eats_at_least = |
| 2937 Min(kMaxLookaheadForBoyerMoore, | 2950 Min(kMaxLookaheadForBoyerMoore, |
| 2938 EatsAtLeast(kMaxLookaheadForBoyerMoore, 0, not_at_start)); | 2951 EatsAtLeast(kMaxLookaheadForBoyerMoore, 0, not_at_start)); |
| 2939 if (eats_at_least >= 1) { | 2952 if (eats_at_least >= 1) { |
| 2940 BoyerMooreLookahead* bm = | 2953 BoyerMooreLookahead* bm = |
| 2941 new BoyerMooreLookahead(eats_at_least, compiler, zone()); | 2954 new(zone()) BoyerMooreLookahead(eats_at_least, compiler, zone()); |
| 2942 FillInBMInfo(0, 0, kFillInBMBudget, bm, not_at_start); | 2955 FillInBMInfo(0, 0, kFillInBMBudget, bm, not_at_start); |
| 2943 if (bm->at(0)->is_non_word()) next_is_word_character = Trace::FALSE; | 2956 if (bm->at(0)->is_non_word()) next_is_word_character = Trace::FALSE; |
| 2944 if (bm->at(0)->is_word()) next_is_word_character = Trace::TRUE; | 2957 if (bm->at(0)->is_word()) next_is_word_character = Trace::TRUE; |
| 2945 } | 2958 } |
| 2946 } else { | 2959 } else { |
| 2947 if (lookahead->at(0)->is_non_word()) next_is_word_character = Trace::FALSE; | 2960 if (lookahead->at(0)->is_non_word()) next_is_word_character = Trace::FALSE; |
| 2948 if (lookahead->at(0)->is_word()) next_is_word_character = Trace::TRUE; | 2961 if (lookahead->at(0)->is_word()) next_is_word_character = Trace::TRUE; |
| 2949 } | 2962 } |
| 2950 bool at_boundary = (type_ == AssertionNode::AT_BOUNDARY); | 2963 bool at_boundary = (type_ == AssertionNode::AT_BOUNDARY); |
| 2951 if (next_is_word_character == Trace::UNKNOWN) { | 2964 if (next_is_word_character == Trace::UNKNOWN) { |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3158 if (pass == CHARACTER_CLASS_MATCH) { | 3171 if (pass == CHARACTER_CLASS_MATCH) { |
| 3159 if (first_element_checked && i == 0) continue; | 3172 if (first_element_checked && i == 0) continue; |
| 3160 if (DeterminedAlready(quick_check, elm.cp_offset)) continue; | 3173 if (DeterminedAlready(quick_check, elm.cp_offset)) continue; |
| 3161 RegExpCharacterClass* cc = elm.data.u_char_class; | 3174 RegExpCharacterClass* cc = elm.data.u_char_class; |
| 3162 EmitCharClass(assembler, | 3175 EmitCharClass(assembler, |
| 3163 cc, | 3176 cc, |
| 3164 ascii, | 3177 ascii, |
| 3165 backtrack, | 3178 backtrack, |
| 3166 cp_offset, | 3179 cp_offset, |
| 3167 *checked_up_to < cp_offset, | 3180 *checked_up_to < cp_offset, |
| 3168 preloaded); | 3181 preloaded, |
| 3182 zone()); |
| 3169 UpdateBoundsCheck(cp_offset, checked_up_to); | 3183 UpdateBoundsCheck(cp_offset, checked_up_to); |
| 3170 } | 3184 } |
| 3171 } | 3185 } |
| 3172 } | 3186 } |
| 3173 } | 3187 } |
| 3174 | 3188 |
| 3175 | 3189 |
| 3176 int TextNode::Length() { | 3190 int TextNode::Length() { |
| 3177 TextElement elm = elms_->last(); | 3191 TextElement elm = elms_->last(); |
| 3178 ASSERT(elm.cp_offset >= 0); | 3192 ASSERT(elm.cp_offset >= 0); |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3279 | 3293 |
| 3280 | 3294 |
| 3281 void TextNode::MakeCaseIndependent(bool is_ascii) { | 3295 void TextNode::MakeCaseIndependent(bool is_ascii) { |
| 3282 int element_count = elms_->length(); | 3296 int element_count = elms_->length(); |
| 3283 for (int i = 0; i < element_count; i++) { | 3297 for (int i = 0; i < element_count; i++) { |
| 3284 TextElement elm = elms_->at(i); | 3298 TextElement elm = elms_->at(i); |
| 3285 if (elm.type == TextElement::CHAR_CLASS) { | 3299 if (elm.type == TextElement::CHAR_CLASS) { |
| 3286 RegExpCharacterClass* cc = elm.data.u_char_class; | 3300 RegExpCharacterClass* cc = elm.data.u_char_class; |
| 3287 // None of the standard character classes is different in the case | 3301 // None of the standard character classes is different in the case |
| 3288 // independent case and it slows us down if we don't know that. | 3302 // independent case and it slows us down if we don't know that. |
| 3289 if (cc->is_standard()) continue; | 3303 if (cc->is_standard(zone())) continue; |
| 3290 ZoneList<CharacterRange>* ranges = cc->ranges(); | 3304 ZoneList<CharacterRange>* ranges = cc->ranges(zone()); |
| 3291 int range_count = ranges->length(); | 3305 int range_count = ranges->length(); |
| 3292 for (int j = 0; j < range_count; j++) { | 3306 for (int j = 0; j < range_count; j++) { |
| 3293 ranges->at(j).AddCaseEquivalents(ranges, is_ascii); | 3307 ranges->at(j).AddCaseEquivalents(ranges, is_ascii, zone()); |
| 3294 } | 3308 } |
| 3295 } | 3309 } |
| 3296 } | 3310 } |
| 3297 } | 3311 } |
| 3298 | 3312 |
| 3299 | 3313 |
| 3300 int TextNode::GreedyLoopTextLength() { | 3314 int TextNode::GreedyLoopTextLength() { |
| 3301 TextElement elm = elms_->at(elms_->length() - 1); | 3315 TextElement elm = elms_->at(elms_->length() - 1); |
| 3302 if (elm.type == TextElement::CHAR_CLASS) { | 3316 if (elm.type == TextElement::CHAR_CLASS) { |
| 3303 return elm.cp_offset + 1; | 3317 return elm.cp_offset + 1; |
| 3304 } else { | 3318 } else { |
| 3305 return elm.cp_offset + elm.data.u_atom->data().length(); | 3319 return elm.cp_offset + elm.data.u_atom->data().length(); |
| 3306 } | 3320 } |
| 3307 } | 3321 } |
| 3308 | 3322 |
| 3309 | 3323 |
| 3310 RegExpNode* TextNode::GetSuccessorOfOmnivorousTextNode( | 3324 RegExpNode* TextNode::GetSuccessorOfOmnivorousTextNode( |
| 3311 RegExpCompiler* compiler) { | 3325 RegExpCompiler* compiler) { |
| 3312 if (elms_->length() != 1) return NULL; | 3326 if (elms_->length() != 1) return NULL; |
| 3313 TextElement elm = elms_->at(0); | 3327 TextElement elm = elms_->at(0); |
| 3314 if (elm.type != TextElement::CHAR_CLASS) return NULL; | 3328 if (elm.type != TextElement::CHAR_CLASS) return NULL; |
| 3315 RegExpCharacterClass* node = elm.data.u_char_class; | 3329 RegExpCharacterClass* node = elm.data.u_char_class; |
| 3316 ZoneList<CharacterRange>* ranges = node->ranges(); | 3330 ZoneList<CharacterRange>* ranges = node->ranges(zone()); |
| 3317 if (!CharacterRange::IsCanonical(ranges)) { | 3331 if (!CharacterRange::IsCanonical(ranges)) { |
| 3318 CharacterRange::Canonicalize(ranges); | 3332 CharacterRange::Canonicalize(ranges); |
| 3319 } | 3333 } |
| 3320 if (node->is_negated()) { | 3334 if (node->is_negated()) { |
| 3321 return ranges->length() == 0 ? on_success() : NULL; | 3335 return ranges->length() == 0 ? on_success() : NULL; |
| 3322 } | 3336 } |
| 3323 if (ranges->length() != 1) return NULL; | 3337 if (ranges->length() != 1) return NULL; |
| 3324 uint32_t max_char; | 3338 uint32_t max_char; |
| 3325 if (compiler->ascii()) { | 3339 if (compiler->ascii()) { |
| 3326 max_char = String::kMaxAsciiCharCode; | 3340 max_char = String::kMaxAsciiCharCode; |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3428 bool expects_preload; | 3442 bool expects_preload; |
| 3429 Label after; | 3443 Label after; |
| 3430 QuickCheckDetails quick_check_details; | 3444 QuickCheckDetails quick_check_details; |
| 3431 }; | 3445 }; |
| 3432 | 3446 |
| 3433 | 3447 |
| 3434 // Creates a list of AlternativeGenerations. If the list has a reasonable | 3448 // Creates a list of AlternativeGenerations. If the list has a reasonable |
| 3435 // size then it is on the stack, otherwise the excess is on the heap. | 3449 // size then it is on the stack, otherwise the excess is on the heap. |
| 3436 class AlternativeGenerationList { | 3450 class AlternativeGenerationList { |
| 3437 public: | 3451 public: |
| 3438 explicit AlternativeGenerationList(int count) | 3452 AlternativeGenerationList(int count, Zone* zone) |
| 3439 : alt_gens_(count) { | 3453 : alt_gens_(count, zone) { |
| 3440 for (int i = 0; i < count && i < kAFew; i++) { | 3454 for (int i = 0; i < count && i < kAFew; i++) { |
| 3441 alt_gens_.Add(a_few_alt_gens_ + i); | 3455 alt_gens_.Add(a_few_alt_gens_ + i, zone); |
| 3442 } | 3456 } |
| 3443 for (int i = kAFew; i < count; i++) { | 3457 for (int i = kAFew; i < count; i++) { |
| 3444 alt_gens_.Add(new AlternativeGeneration()); | 3458 alt_gens_.Add(new AlternativeGeneration(), zone); |
| 3445 } | 3459 } |
| 3446 } | 3460 } |
| 3447 ~AlternativeGenerationList() { | 3461 ~AlternativeGenerationList() { |
| 3448 for (int i = kAFew; i < alt_gens_.length(); i++) { | 3462 for (int i = kAFew; i < alt_gens_.length(); i++) { |
| 3449 delete alt_gens_[i]; | 3463 delete alt_gens_[i]; |
| 3450 alt_gens_[i] = NULL; | 3464 alt_gens_[i] = NULL; |
| 3451 } | 3465 } |
| 3452 } | 3466 } |
| 3453 | 3467 |
| 3454 AlternativeGeneration* at(int i) { | 3468 AlternativeGeneration* at(int i) { |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3520 | 3534 |
| 3521 BoyerMooreLookahead::BoyerMooreLookahead( | 3535 BoyerMooreLookahead::BoyerMooreLookahead( |
| 3522 int length, RegExpCompiler* compiler, Zone* zone) | 3536 int length, RegExpCompiler* compiler, Zone* zone) |
| 3523 : length_(length), | 3537 : length_(length), |
| 3524 compiler_(compiler) { | 3538 compiler_(compiler) { |
| 3525 if (compiler->ascii()) { | 3539 if (compiler->ascii()) { |
| 3526 max_char_ = String::kMaxAsciiCharCode; | 3540 max_char_ = String::kMaxAsciiCharCode; |
| 3527 } else { | 3541 } else { |
| 3528 max_char_ = String::kMaxUtf16CodeUnit; | 3542 max_char_ = String::kMaxUtf16CodeUnit; |
| 3529 } | 3543 } |
| 3530 bitmaps_ = new ZoneList<BoyerMoorePositionInfo*>(length); | 3544 bitmaps_ = new(zone) ZoneList<BoyerMoorePositionInfo*>(length, zone); |
| 3531 for (int i = 0; i < length; i++) { | 3545 for (int i = 0; i < length; i++) { |
| 3532 bitmaps_->Add(new BoyerMoorePositionInfo(zone)); | 3546 bitmaps_->Add(new(zone) BoyerMoorePositionInfo(zone), zone); |
| 3533 } | 3547 } |
| 3534 } | 3548 } |
| 3535 | 3549 |
| 3536 | 3550 |
| 3537 // Find the longest range of lookahead that has the fewest number of different | 3551 // Find the longest range of lookahead that has the fewest number of different |
| 3538 // characters that can occur at a given position. Since we are optimizing two | 3552 // characters that can occur at a given position. Since we are optimizing two |
| 3539 // different parameters at once this is a tradeoff. | 3553 // different parameters at once this is a tradeoff. |
| 3540 bool BoyerMooreLookahead::FindWorthwhileInterval(int* from, int* to) { | 3554 bool BoyerMooreLookahead::FindWorthwhileInterval(int* from, int* to) { |
| 3541 int biggest_points = 0; | 3555 int biggest_points = 0; |
| 3542 // If more than 32 characters out of 128 can occur it is unlikely that we can | 3556 // If more than 32 characters out of 128 can occur it is unlikely that we can |
| (...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3868 // not be atoms, they can be any reasonably limited character class or | 3882 // not be atoms, they can be any reasonably limited character class or |
| 3869 // small alternation. | 3883 // small alternation. |
| 3870 ASSERT(trace->is_trivial()); // This is the case on LoopChoiceNodes. | 3884 ASSERT(trace->is_trivial()); // This is the case on LoopChoiceNodes. |
| 3871 BoyerMooreLookahead* lookahead = bm_info(not_at_start); | 3885 BoyerMooreLookahead* lookahead = bm_info(not_at_start); |
| 3872 if (lookahead == NULL) { | 3886 if (lookahead == NULL) { |
| 3873 eats_at_least = | 3887 eats_at_least = |
| 3874 Min(kMaxLookaheadForBoyerMoore, | 3888 Min(kMaxLookaheadForBoyerMoore, |
| 3875 EatsAtLeast(kMaxLookaheadForBoyerMoore, 0, not_at_start)); | 3889 EatsAtLeast(kMaxLookaheadForBoyerMoore, 0, not_at_start)); |
| 3876 if (eats_at_least >= 1) { | 3890 if (eats_at_least >= 1) { |
| 3877 BoyerMooreLookahead* bm = | 3891 BoyerMooreLookahead* bm = |
| 3878 new BoyerMooreLookahead(eats_at_least, compiler, zone()); | 3892 new(zone()) BoyerMooreLookahead(eats_at_least, |
| 3893 compiler, |
| 3894 zone()); |
| 3879 GuardedAlternative alt0 = alternatives_->at(0); | 3895 GuardedAlternative alt0 = alternatives_->at(0); |
| 3880 alt0.node()->FillInBMInfo(0, 0, kFillInBMBudget, bm, not_at_start); | 3896 alt0.node()->FillInBMInfo(0, 0, kFillInBMBudget, bm, not_at_start); |
| 3881 skip_was_emitted = bm->EmitSkipInstructions(macro_assembler); | 3897 skip_was_emitted = bm->EmitSkipInstructions(macro_assembler); |
| 3882 } | 3898 } |
| 3883 } else { | 3899 } else { |
| 3884 skip_was_emitted = lookahead->EmitSkipInstructions(macro_assembler); | 3900 skip_was_emitted = lookahead->EmitSkipInstructions(macro_assembler); |
| 3885 } | 3901 } |
| 3886 } | 3902 } |
| 3887 } | 3903 } |
| 3888 } | 3904 } |
| 3889 | 3905 |
| 3890 if (eats_at_least == kEatsAtLeastNotYetInitialized) { | 3906 if (eats_at_least == kEatsAtLeastNotYetInitialized) { |
| 3891 // Save some time by looking at most one machine word ahead. | 3907 // Save some time by looking at most one machine word ahead. |
| 3892 eats_at_least = EatsAtLeast(compiler->ascii() ? 4 : 2, 0, not_at_start); | 3908 eats_at_least = EatsAtLeast(compiler->ascii() ? 4 : 2, 0, not_at_start); |
| 3893 } | 3909 } |
| 3894 int preload_characters = CalculatePreloadCharacters(compiler, eats_at_least); | 3910 int preload_characters = CalculatePreloadCharacters(compiler, eats_at_least); |
| 3895 | 3911 |
| 3896 bool preload_is_current = !skip_was_emitted && | 3912 bool preload_is_current = !skip_was_emitted && |
| 3897 (current_trace->characters_preloaded() == preload_characters); | 3913 (current_trace->characters_preloaded() == preload_characters); |
| 3898 bool preload_has_checked_bounds = preload_is_current; | 3914 bool preload_has_checked_bounds = preload_is_current; |
| 3899 | 3915 |
| 3900 AlternativeGenerationList alt_gens(choice_count); | 3916 AlternativeGenerationList alt_gens(choice_count, zone()); |
| 3901 | 3917 |
| 3902 // For now we just call all choices one after the other. The idea ultimately | 3918 // For now we just call all choices one after the other. The idea ultimately |
| 3903 // is to use the Dispatch table to try only the relevant ones. | 3919 // is to use the Dispatch table to try only the relevant ones. |
| 3904 for (int i = first_normal_choice; i < choice_count; i++) { | 3920 for (int i = first_normal_choice; i < choice_count; i++) { |
| 3905 GuardedAlternative alternative = alternatives_->at(i); | 3921 GuardedAlternative alternative = alternatives_->at(i); |
| 3906 AlternativeGeneration* alt_gen = alt_gens.at(i); | 3922 AlternativeGeneration* alt_gen = alt_gens.at(i); |
| 3907 alt_gen->quick_check_details.set_characters(preload_characters); | 3923 alt_gen->quick_check_details.set_characters(preload_characters); |
| 3908 ZoneList<Guard*>* guards = alternative.guards(); | 3924 ZoneList<Guard*>* guards = alternative.guards(); |
| 3909 int guard_count = (guards == NULL) ? 0 : guards->length(); | 3925 int guard_count = (guards == NULL) ? 0 : guards->length(); |
| 3910 Trace new_trace(*current_trace); | 3926 Trace new_trace(*current_trace); |
| (...skipping 459 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4370 } | 4386 } |
| 4371 } | 4387 } |
| 4372 for (int i = 0; i < that->alternatives()->length(); i++) { | 4388 for (int i = 0; i < that->alternatives()->length(); i++) { |
| 4373 GuardedAlternative alt = that->alternatives()->at(i); | 4389 GuardedAlternative alt = that->alternatives()->at(i); |
| 4374 alt.node()->Accept(this); | 4390 alt.node()->Accept(this); |
| 4375 } | 4391 } |
| 4376 } | 4392 } |
| 4377 | 4393 |
| 4378 | 4394 |
| 4379 void DotPrinter::VisitText(TextNode* that) { | 4395 void DotPrinter::VisitText(TextNode* that) { |
| 4396 Zone* zone = that->zone(); |
| 4380 stream()->Add(" n%p [label=\"", that); | 4397 stream()->Add(" n%p [label=\"", that); |
| 4381 for (int i = 0; i < that->elements()->length(); i++) { | 4398 for (int i = 0; i < that->elements()->length(); i++) { |
| 4382 if (i > 0) stream()->Add(" "); | 4399 if (i > 0) stream()->Add(" "); |
| 4383 TextElement elm = that->elements()->at(i); | 4400 TextElement elm = that->elements()->at(i); |
| 4384 switch (elm.type) { | 4401 switch (elm.type) { |
| 4385 case TextElement::ATOM: { | 4402 case TextElement::ATOM: { |
| 4386 stream()->Add("'%w'", elm.data.u_atom->data()); | 4403 stream()->Add("'%w'", elm.data.u_atom->data()); |
| 4387 break; | 4404 break; |
| 4388 } | 4405 } |
| 4389 case TextElement::CHAR_CLASS: { | 4406 case TextElement::CHAR_CLASS: { |
| 4390 RegExpCharacterClass* node = elm.data.u_char_class; | 4407 RegExpCharacterClass* node = elm.data.u_char_class; |
| 4391 stream()->Add("["); | 4408 stream()->Add("["); |
| 4392 if (node->is_negated()) | 4409 if (node->is_negated()) |
| 4393 stream()->Add("^"); | 4410 stream()->Add("^"); |
| 4394 for (int j = 0; j < node->ranges()->length(); j++) { | 4411 for (int j = 0; j < node->ranges(zone)->length(); j++) { |
| 4395 CharacterRange range = node->ranges()->at(j); | 4412 CharacterRange range = node->ranges(zone)->at(j); |
| 4396 stream()->Add("%k-%k", range.from(), range.to()); | 4413 stream()->Add("%k-%k", range.from(), range.to()); |
| 4397 } | 4414 } |
| 4398 stream()->Add("]"); | 4415 stream()->Add("]"); |
| 4399 break; | 4416 break; |
| 4400 } | 4417 } |
| 4401 default: | 4418 default: |
| 4402 UNREACHABLE(); | 4419 UNREACHABLE(); |
| 4403 } | 4420 } |
| 4404 } | 4421 } |
| 4405 stream()->Add("\", shape=box, peripheries=2];\n"); | 4422 stream()->Add("\", shape=box, peripheries=2];\n"); |
| (...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4543 | 4560 |
| 4544 | 4561 |
| 4545 #endif // DEBUG | 4562 #endif // DEBUG |
| 4546 | 4563 |
| 4547 | 4564 |
| 4548 // ------------------------------------------------------------------- | 4565 // ------------------------------------------------------------------- |
| 4549 // Tree to graph conversion | 4566 // Tree to graph conversion |
| 4550 | 4567 |
| 4551 RegExpNode* RegExpAtom::ToNode(RegExpCompiler* compiler, | 4568 RegExpNode* RegExpAtom::ToNode(RegExpCompiler* compiler, |
| 4552 RegExpNode* on_success) { | 4569 RegExpNode* on_success) { |
| 4553 ZoneList<TextElement>* elms = new ZoneList<TextElement>(1); | 4570 ZoneList<TextElement>* elms = |
| 4554 elms->Add(TextElement::Atom(this)); | 4571 new(compiler->zone()) ZoneList<TextElement>(1, compiler->zone()); |
| 4555 return new TextNode(elms, on_success); | 4572 elms->Add(TextElement::Atom(this), compiler->zone()); |
| 4573 return new(compiler->zone()) TextNode(elms, on_success); |
| 4556 } | 4574 } |
| 4557 | 4575 |
| 4558 | 4576 |
| 4559 RegExpNode* RegExpText::ToNode(RegExpCompiler* compiler, | 4577 RegExpNode* RegExpText::ToNode(RegExpCompiler* compiler, |
| 4560 RegExpNode* on_success) { | 4578 RegExpNode* on_success) { |
| 4561 return new TextNode(elements(), on_success); | 4579 return new(compiler->zone()) TextNode(elements(), on_success); |
| 4562 } | 4580 } |
| 4563 | 4581 |
| 4564 | 4582 |
| 4565 static bool CompareInverseRanges(ZoneList<CharacterRange>* ranges, | 4583 static bool CompareInverseRanges(ZoneList<CharacterRange>* ranges, |
| 4566 const int* special_class, | 4584 const int* special_class, |
| 4567 int length) { | 4585 int length) { |
| 4568 length--; // Remove final 0x10000. | 4586 length--; // Remove final 0x10000. |
| 4569 ASSERT(special_class[length] == 0x10000); | 4587 ASSERT(special_class[length] == 0x10000); |
| 4570 ASSERT(ranges->length() != 0); | 4588 ASSERT(ranges->length() != 0); |
| 4571 ASSERT(length != 0); | 4589 ASSERT(length != 0); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4605 CharacterRange range = ranges->at(i >> 1); | 4623 CharacterRange range = ranges->at(i >> 1); |
| 4606 if (range.from() != special_class[i] || | 4624 if (range.from() != special_class[i] || |
| 4607 range.to() != special_class[i + 1] - 1) { | 4625 range.to() != special_class[i + 1] - 1) { |
| 4608 return false; | 4626 return false; |
| 4609 } | 4627 } |
| 4610 } | 4628 } |
| 4611 return true; | 4629 return true; |
| 4612 } | 4630 } |
| 4613 | 4631 |
| 4614 | 4632 |
| 4615 bool RegExpCharacterClass::is_standard() { | 4633 bool RegExpCharacterClass::is_standard(Zone* zone) { |
| 4616 // TODO(lrn): Remove need for this function, by not throwing away information | 4634 // TODO(lrn): Remove need for this function, by not throwing away information |
| 4617 // along the way. | 4635 // along the way. |
| 4618 if (is_negated_) { | 4636 if (is_negated_) { |
| 4619 return false; | 4637 return false; |
| 4620 } | 4638 } |
| 4621 if (set_.is_standard()) { | 4639 if (set_.is_standard()) { |
| 4622 return true; | 4640 return true; |
| 4623 } | 4641 } |
| 4624 if (CompareRanges(set_.ranges(), kSpaceRanges, kSpaceRangeCount)) { | 4642 if (CompareRanges(set_.ranges(zone), kSpaceRanges, kSpaceRangeCount)) { |
| 4625 set_.set_standard_set_type('s'); | 4643 set_.set_standard_set_type('s'); |
| 4626 return true; | 4644 return true; |
| 4627 } | 4645 } |
| 4628 if (CompareInverseRanges(set_.ranges(), kSpaceRanges, kSpaceRangeCount)) { | 4646 if (CompareInverseRanges(set_.ranges(zone), kSpaceRanges, kSpaceRangeCount)) { |
| 4629 set_.set_standard_set_type('S'); | 4647 set_.set_standard_set_type('S'); |
| 4630 return true; | 4648 return true; |
| 4631 } | 4649 } |
| 4632 if (CompareInverseRanges(set_.ranges(), | 4650 if (CompareInverseRanges(set_.ranges(zone), |
| 4633 kLineTerminatorRanges, | 4651 kLineTerminatorRanges, |
| 4634 kLineTerminatorRangeCount)) { | 4652 kLineTerminatorRangeCount)) { |
| 4635 set_.set_standard_set_type('.'); | 4653 set_.set_standard_set_type('.'); |
| 4636 return true; | 4654 return true; |
| 4637 } | 4655 } |
| 4638 if (CompareRanges(set_.ranges(), | 4656 if (CompareRanges(set_.ranges(zone), |
| 4639 kLineTerminatorRanges, | 4657 kLineTerminatorRanges, |
| 4640 kLineTerminatorRangeCount)) { | 4658 kLineTerminatorRangeCount)) { |
| 4641 set_.set_standard_set_type('n'); | 4659 set_.set_standard_set_type('n'); |
| 4642 return true; | 4660 return true; |
| 4643 } | 4661 } |
| 4644 if (CompareRanges(set_.ranges(), kWordRanges, kWordRangeCount)) { | 4662 if (CompareRanges(set_.ranges(zone), kWordRanges, kWordRangeCount)) { |
| 4645 set_.set_standard_set_type('w'); | 4663 set_.set_standard_set_type('w'); |
| 4646 return true; | 4664 return true; |
| 4647 } | 4665 } |
| 4648 if (CompareInverseRanges(set_.ranges(), kWordRanges, kWordRangeCount)) { | 4666 if (CompareInverseRanges(set_.ranges(zone), kWordRanges, kWordRangeCount)) { |
| 4649 set_.set_standard_set_type('W'); | 4667 set_.set_standard_set_type('W'); |
| 4650 return true; | 4668 return true; |
| 4651 } | 4669 } |
| 4652 return false; | 4670 return false; |
| 4653 } | 4671 } |
| 4654 | 4672 |
| 4655 | 4673 |
| 4656 RegExpNode* RegExpCharacterClass::ToNode(RegExpCompiler* compiler, | 4674 RegExpNode* RegExpCharacterClass::ToNode(RegExpCompiler* compiler, |
| 4657 RegExpNode* on_success) { | 4675 RegExpNode* on_success) { |
| 4658 return new TextNode(this, on_success); | 4676 return new(compiler->zone()) TextNode(this, on_success); |
| 4659 } | 4677 } |
| 4660 | 4678 |
| 4661 | 4679 |
| 4662 RegExpNode* RegExpDisjunction::ToNode(RegExpCompiler* compiler, | 4680 RegExpNode* RegExpDisjunction::ToNode(RegExpCompiler* compiler, |
| 4663 RegExpNode* on_success) { | 4681 RegExpNode* on_success) { |
| 4664 ZoneList<RegExpTree*>* alternatives = this->alternatives(); | 4682 ZoneList<RegExpTree*>* alternatives = this->alternatives(); |
| 4665 int length = alternatives->length(); | 4683 int length = alternatives->length(); |
| 4666 ChoiceNode* result = new ChoiceNode(length, compiler->zone()); | 4684 ChoiceNode* result = |
| 4685 new(compiler->zone()) ChoiceNode(length, compiler->zone()); |
| 4667 for (int i = 0; i < length; i++) { | 4686 for (int i = 0; i < length; i++) { |
| 4668 GuardedAlternative alternative(alternatives->at(i)->ToNode(compiler, | 4687 GuardedAlternative alternative(alternatives->at(i)->ToNode(compiler, |
| 4669 on_success)); | 4688 on_success)); |
| 4670 result->AddAlternative(alternative); | 4689 result->AddAlternative(alternative); |
| 4671 } | 4690 } |
| 4672 return result; | 4691 return result; |
| 4673 } | 4692 } |
| 4674 | 4693 |
| 4675 | 4694 |
| 4676 RegExpNode* RegExpQuantifier::ToNode(RegExpCompiler* compiler, | 4695 RegExpNode* RegExpQuantifier::ToNode(RegExpCompiler* compiler, |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4749 // simpler since we don't need to make the special zero length match check | 4768 // simpler since we don't need to make the special zero length match check |
| 4750 // from step 2.1. If the min and max are small we can unroll a little in | 4769 // from step 2.1. If the min and max are small we can unroll a little in |
| 4751 // this case. | 4770 // this case. |
| 4752 static const int kMaxUnrolledMinMatches = 3; // Unroll (foo)+ and (foo){3,} | 4771 static const int kMaxUnrolledMinMatches = 3; // Unroll (foo)+ and (foo){3,} |
| 4753 static const int kMaxUnrolledMaxMatches = 3; // Unroll (foo)? and (foo){x,3} | 4772 static const int kMaxUnrolledMaxMatches = 3; // Unroll (foo)? and (foo){x,3} |
| 4754 if (max == 0) return on_success; // This can happen due to recursion. | 4773 if (max == 0) return on_success; // This can happen due to recursion. |
| 4755 bool body_can_be_empty = (body->min_match() == 0); | 4774 bool body_can_be_empty = (body->min_match() == 0); |
| 4756 int body_start_reg = RegExpCompiler::kNoRegister; | 4775 int body_start_reg = RegExpCompiler::kNoRegister; |
| 4757 Interval capture_registers = body->CaptureRegisters(); | 4776 Interval capture_registers = body->CaptureRegisters(); |
| 4758 bool needs_capture_clearing = !capture_registers.is_empty(); | 4777 bool needs_capture_clearing = !capture_registers.is_empty(); |
| 4778 Zone* zone = compiler->zone(); |
| 4779 |
| 4759 if (body_can_be_empty) { | 4780 if (body_can_be_empty) { |
| 4760 body_start_reg = compiler->AllocateRegister(); | 4781 body_start_reg = compiler->AllocateRegister(); |
| 4761 } else if (FLAG_regexp_optimization && !needs_capture_clearing) { | 4782 } else if (FLAG_regexp_optimization && !needs_capture_clearing) { |
| 4762 // Only unroll if there are no captures and the body can't be | 4783 // Only unroll if there are no captures and the body can't be |
| 4763 // empty. | 4784 // empty. |
| 4764 { | 4785 { |
| 4765 RegExpExpansionLimiter limiter( | 4786 RegExpExpansionLimiter limiter( |
| 4766 compiler, min + ((max != min) ? 1 : 0)); | 4787 compiler, min + ((max != min) ? 1 : 0)); |
| 4767 if (min > 0 && min <= kMaxUnrolledMinMatches && limiter.ok_to_expand()) { | 4788 if (min > 0 && min <= kMaxUnrolledMinMatches && limiter.ok_to_expand()) { |
| 4768 int new_max = (max == kInfinity) ? max : max - min; | 4789 int new_max = (max == kInfinity) ? max : max - min; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 4779 return answer; | 4800 return answer; |
| 4780 } | 4801 } |
| 4781 } | 4802 } |
| 4782 if (max <= kMaxUnrolledMaxMatches && min == 0) { | 4803 if (max <= kMaxUnrolledMaxMatches && min == 0) { |
| 4783 ASSERT(max > 0); // Due to the 'if' above. | 4804 ASSERT(max > 0); // Due to the 'if' above. |
| 4784 RegExpExpansionLimiter limiter(compiler, max); | 4805 RegExpExpansionLimiter limiter(compiler, max); |
| 4785 if (limiter.ok_to_expand()) { | 4806 if (limiter.ok_to_expand()) { |
| 4786 // Unroll the optional matches up to max. | 4807 // Unroll the optional matches up to max. |
| 4787 RegExpNode* answer = on_success; | 4808 RegExpNode* answer = on_success; |
| 4788 for (int i = 0; i < max; i++) { | 4809 for (int i = 0; i < max; i++) { |
| 4789 ChoiceNode* alternation = new ChoiceNode(2, compiler->zone()); | 4810 ChoiceNode* alternation = new(zone) ChoiceNode(2, zone); |
| 4790 if (is_greedy) { | 4811 if (is_greedy) { |
| 4791 alternation->AddAlternative( | 4812 alternation->AddAlternative( |
| 4792 GuardedAlternative(body->ToNode(compiler, answer))); | 4813 GuardedAlternative(body->ToNode(compiler, answer))); |
| 4793 alternation->AddAlternative(GuardedAlternative(on_success)); | 4814 alternation->AddAlternative(GuardedAlternative(on_success)); |
| 4794 } else { | 4815 } else { |
| 4795 alternation->AddAlternative(GuardedAlternative(on_success)); | 4816 alternation->AddAlternative(GuardedAlternative(on_success)); |
| 4796 alternation->AddAlternative( | 4817 alternation->AddAlternative( |
| 4797 GuardedAlternative(body->ToNode(compiler, answer))); | 4818 GuardedAlternative(body->ToNode(compiler, answer))); |
| 4798 } | 4819 } |
| 4799 answer = alternation; | 4820 answer = alternation; |
| 4800 if (not_at_start) alternation->set_not_at_start(); | 4821 if (not_at_start) alternation->set_not_at_start(); |
| 4801 } | 4822 } |
| 4802 return answer; | 4823 return answer; |
| 4803 } | 4824 } |
| 4804 } | 4825 } |
| 4805 } | 4826 } |
| 4806 bool has_min = min > 0; | 4827 bool has_min = min > 0; |
| 4807 bool has_max = max < RegExpTree::kInfinity; | 4828 bool has_max = max < RegExpTree::kInfinity; |
| 4808 bool needs_counter = has_min || has_max; | 4829 bool needs_counter = has_min || has_max; |
| 4809 int reg_ctr = needs_counter | 4830 int reg_ctr = needs_counter |
| 4810 ? compiler->AllocateRegister() | 4831 ? compiler->AllocateRegister() |
| 4811 : RegExpCompiler::kNoRegister; | 4832 : RegExpCompiler::kNoRegister; |
| 4812 LoopChoiceNode* center = new LoopChoiceNode(body->min_match() == 0, | 4833 LoopChoiceNode* center = new(zone) LoopChoiceNode(body->min_match() == 0, |
| 4813 compiler->zone()); | 4834 zone); |
| 4814 if (not_at_start) center->set_not_at_start(); | 4835 if (not_at_start) center->set_not_at_start(); |
| 4815 RegExpNode* loop_return = needs_counter | 4836 RegExpNode* loop_return = needs_counter |
| 4816 ? static_cast<RegExpNode*>(ActionNode::IncrementRegister(reg_ctr, center)) | 4837 ? static_cast<RegExpNode*>(ActionNode::IncrementRegister(reg_ctr, center)) |
| 4817 : static_cast<RegExpNode*>(center); | 4838 : static_cast<RegExpNode*>(center); |
| 4818 if (body_can_be_empty) { | 4839 if (body_can_be_empty) { |
| 4819 // If the body can be empty we need to check if it was and then | 4840 // If the body can be empty we need to check if it was and then |
| 4820 // backtrack. | 4841 // backtrack. |
| 4821 loop_return = ActionNode::EmptyMatchCheck(body_start_reg, | 4842 loop_return = ActionNode::EmptyMatchCheck(body_start_reg, |
| 4822 reg_ctr, | 4843 reg_ctr, |
| 4823 min, | 4844 min, |
| 4824 loop_return); | 4845 loop_return); |
| 4825 } | 4846 } |
| 4826 RegExpNode* body_node = body->ToNode(compiler, loop_return); | 4847 RegExpNode* body_node = body->ToNode(compiler, loop_return); |
| 4827 if (body_can_be_empty) { | 4848 if (body_can_be_empty) { |
| 4828 // If the body can be empty we need to store the start position | 4849 // If the body can be empty we need to store the start position |
| 4829 // so we can bail out if it was empty. | 4850 // so we can bail out if it was empty. |
| 4830 body_node = ActionNode::StorePosition(body_start_reg, false, body_node); | 4851 body_node = ActionNode::StorePosition(body_start_reg, false, body_node); |
| 4831 } | 4852 } |
| 4832 if (needs_capture_clearing) { | 4853 if (needs_capture_clearing) { |
| 4833 // Before entering the body of this loop we need to clear captures. | 4854 // Before entering the body of this loop we need to clear captures. |
| 4834 body_node = ActionNode::ClearCaptures(capture_registers, body_node); | 4855 body_node = ActionNode::ClearCaptures(capture_registers, body_node); |
| 4835 } | 4856 } |
| 4836 GuardedAlternative body_alt(body_node); | 4857 GuardedAlternative body_alt(body_node); |
| 4837 if (has_max) { | 4858 if (has_max) { |
| 4838 Guard* body_guard = new Guard(reg_ctr, Guard::LT, max); | 4859 Guard* body_guard = |
| 4839 body_alt.AddGuard(body_guard); | 4860 new(zone) Guard(reg_ctr, Guard::LT, max); |
| 4861 body_alt.AddGuard(body_guard, zone); |
| 4840 } | 4862 } |
| 4841 GuardedAlternative rest_alt(on_success); | 4863 GuardedAlternative rest_alt(on_success); |
| 4842 if (has_min) { | 4864 if (has_min) { |
| 4843 Guard* rest_guard = new Guard(reg_ctr, Guard::GEQ, min); | 4865 Guard* rest_guard = new(compiler->zone()) Guard(reg_ctr, Guard::GEQ, min); |
| 4844 rest_alt.AddGuard(rest_guard); | 4866 rest_alt.AddGuard(rest_guard, zone); |
| 4845 } | 4867 } |
| 4846 if (is_greedy) { | 4868 if (is_greedy) { |
| 4847 center->AddLoopAlternative(body_alt); | 4869 center->AddLoopAlternative(body_alt); |
| 4848 center->AddContinueAlternative(rest_alt); | 4870 center->AddContinueAlternative(rest_alt); |
| 4849 } else { | 4871 } else { |
| 4850 center->AddContinueAlternative(rest_alt); | 4872 center->AddContinueAlternative(rest_alt); |
| 4851 center->AddLoopAlternative(body_alt); | 4873 center->AddLoopAlternative(body_alt); |
| 4852 } | 4874 } |
| 4853 if (needs_counter) { | 4875 if (needs_counter) { |
| 4854 return ActionNode::SetRegister(reg_ctr, 0, center); | 4876 return ActionNode::SetRegister(reg_ctr, 0, center); |
| 4855 } else { | 4877 } else { |
| 4856 return center; | 4878 return center; |
| 4857 } | 4879 } |
| 4858 } | 4880 } |
| 4859 | 4881 |
| 4860 | 4882 |
| 4861 RegExpNode* RegExpAssertion::ToNode(RegExpCompiler* compiler, | 4883 RegExpNode* RegExpAssertion::ToNode(RegExpCompiler* compiler, |
| 4862 RegExpNode* on_success) { | 4884 RegExpNode* on_success) { |
| 4863 NodeInfo info; | 4885 NodeInfo info; |
| 4886 Zone* zone = compiler->zone(); |
| 4887 |
| 4864 switch (type()) { | 4888 switch (type()) { |
| 4865 case START_OF_LINE: | 4889 case START_OF_LINE: |
| 4866 return AssertionNode::AfterNewline(on_success); | 4890 return AssertionNode::AfterNewline(on_success); |
| 4867 case START_OF_INPUT: | 4891 case START_OF_INPUT: |
| 4868 return AssertionNode::AtStart(on_success); | 4892 return AssertionNode::AtStart(on_success); |
| 4869 case BOUNDARY: | 4893 case BOUNDARY: |
| 4870 return AssertionNode::AtBoundary(on_success); | 4894 return AssertionNode::AtBoundary(on_success); |
| 4871 case NON_BOUNDARY: | 4895 case NON_BOUNDARY: |
| 4872 return AssertionNode::AtNonBoundary(on_success); | 4896 return AssertionNode::AtNonBoundary(on_success); |
| 4873 case END_OF_INPUT: | 4897 case END_OF_INPUT: |
| 4874 return AssertionNode::AtEnd(on_success); | 4898 return AssertionNode::AtEnd(on_success); |
| 4875 case END_OF_LINE: { | 4899 case END_OF_LINE: { |
| 4876 // Compile $ in multiline regexps as an alternation with a positive | 4900 // Compile $ in multiline regexps as an alternation with a positive |
| 4877 // lookahead in one side and an end-of-input on the other side. | 4901 // lookahead in one side and an end-of-input on the other side. |
| 4878 // We need two registers for the lookahead. | 4902 // We need two registers for the lookahead. |
| 4879 int stack_pointer_register = compiler->AllocateRegister(); | 4903 int stack_pointer_register = compiler->AllocateRegister(); |
| 4880 int position_register = compiler->AllocateRegister(); | 4904 int position_register = compiler->AllocateRegister(); |
| 4881 // The ChoiceNode to distinguish between a newline and end-of-input. | 4905 // The ChoiceNode to distinguish between a newline and end-of-input. |
| 4882 ChoiceNode* result = new ChoiceNode(2, compiler->zone()); | 4906 ChoiceNode* result = new(zone) ChoiceNode(2, zone); |
| 4883 // Create a newline atom. | 4907 // Create a newline atom. |
| 4884 ZoneList<CharacterRange>* newline_ranges = | 4908 ZoneList<CharacterRange>* newline_ranges = |
| 4885 new ZoneList<CharacterRange>(3); | 4909 new(zone) ZoneList<CharacterRange>(3, zone); |
| 4886 CharacterRange::AddClassEscape('n', newline_ranges); | 4910 CharacterRange::AddClassEscape('n', newline_ranges, zone); |
| 4887 RegExpCharacterClass* newline_atom = new RegExpCharacterClass('n'); | 4911 RegExpCharacterClass* newline_atom = new(zone) RegExpCharacterClass('n'); |
| 4888 TextNode* newline_matcher = new TextNode( | 4912 TextNode* newline_matcher = new(zone) TextNode( |
| 4889 newline_atom, | 4913 newline_atom, |
| 4890 ActionNode::PositiveSubmatchSuccess(stack_pointer_register, | 4914 ActionNode::PositiveSubmatchSuccess(stack_pointer_register, |
| 4891 position_register, | 4915 position_register, |
| 4892 0, // No captures inside. | 4916 0, // No captures inside. |
| 4893 -1, // Ignored if no captures. | 4917 -1, // Ignored if no captures. |
| 4894 on_success)); | 4918 on_success)); |
| 4895 // Create an end-of-input matcher. | 4919 // Create an end-of-input matcher. |
| 4896 RegExpNode* end_of_line = ActionNode::BeginSubmatch( | 4920 RegExpNode* end_of_line = ActionNode::BeginSubmatch( |
| 4897 stack_pointer_register, | 4921 stack_pointer_register, |
| 4898 position_register, | 4922 position_register, |
| 4899 newline_matcher); | 4923 newline_matcher); |
| 4900 // Add the two alternatives to the ChoiceNode. | 4924 // Add the two alternatives to the ChoiceNode. |
| 4901 GuardedAlternative eol_alternative(end_of_line); | 4925 GuardedAlternative eol_alternative(end_of_line); |
| 4902 result->AddAlternative(eol_alternative); | 4926 result->AddAlternative(eol_alternative); |
| 4903 GuardedAlternative end_alternative(AssertionNode::AtEnd(on_success)); | 4927 GuardedAlternative end_alternative(AssertionNode::AtEnd(on_success)); |
| 4904 result->AddAlternative(end_alternative); | 4928 result->AddAlternative(end_alternative); |
| 4905 return result; | 4929 return result; |
| 4906 } | 4930 } |
| 4907 default: | 4931 default: |
| 4908 UNREACHABLE(); | 4932 UNREACHABLE(); |
| 4909 } | 4933 } |
| 4910 return on_success; | 4934 return on_success; |
| 4911 } | 4935 } |
| 4912 | 4936 |
| 4913 | 4937 |
| 4914 RegExpNode* RegExpBackReference::ToNode(RegExpCompiler* compiler, | 4938 RegExpNode* RegExpBackReference::ToNode(RegExpCompiler* compiler, |
| 4915 RegExpNode* on_success) { | 4939 RegExpNode* on_success) { |
| 4916 return new BackReferenceNode(RegExpCapture::StartRegister(index()), | 4940 return new(compiler->zone()) |
| 4917 RegExpCapture::EndRegister(index()), | 4941 BackReferenceNode(RegExpCapture::StartRegister(index()), |
| 4918 on_success); | 4942 RegExpCapture::EndRegister(index()), |
| 4943 on_success); |
| 4919 } | 4944 } |
| 4920 | 4945 |
| 4921 | 4946 |
| 4922 RegExpNode* RegExpEmpty::ToNode(RegExpCompiler* compiler, | 4947 RegExpNode* RegExpEmpty::ToNode(RegExpCompiler* compiler, |
| 4923 RegExpNode* on_success) { | 4948 RegExpNode* on_success) { |
| 4924 return on_success; | 4949 return on_success; |
| 4925 } | 4950 } |
| 4926 | 4951 |
| 4927 | 4952 |
| 4928 RegExpNode* RegExpLookahead::ToNode(RegExpCompiler* compiler, | 4953 RegExpNode* RegExpLookahead::ToNode(RegExpCompiler* compiler, |
| (...skipping 24 matching lines...) Expand all Loading... |
| 4953 // We use a ChoiceNode for a negative lookahead because it has most of | 4978 // We use a ChoiceNode for a negative lookahead because it has most of |
| 4954 // the characteristics we need. It has the body of the lookahead as its | 4979 // the characteristics we need. It has the body of the lookahead as its |
| 4955 // first alternative and the expression after the lookahead of the second | 4980 // first alternative and the expression after the lookahead of the second |
| 4956 // alternative. If the first alternative succeeds then the | 4981 // alternative. If the first alternative succeeds then the |
| 4957 // NegativeSubmatchSuccess will unwind the stack including everything the | 4982 // NegativeSubmatchSuccess will unwind the stack including everything the |
| 4958 // choice node set up and backtrack. If the first alternative fails then | 4983 // choice node set up and backtrack. If the first alternative fails then |
| 4959 // the second alternative is tried, which is exactly the desired result | 4984 // the second alternative is tried, which is exactly the desired result |
| 4960 // for a negative lookahead. The NegativeLookaheadChoiceNode is a special | 4985 // for a negative lookahead. The NegativeLookaheadChoiceNode is a special |
| 4961 // ChoiceNode that knows to ignore the first exit when calculating quick | 4986 // ChoiceNode that knows to ignore the first exit when calculating quick |
| 4962 // checks. | 4987 // checks. |
| 4988 Zone* zone = compiler->zone(); |
| 4989 |
| 4963 GuardedAlternative body_alt( | 4990 GuardedAlternative body_alt( |
| 4964 body()->ToNode( | 4991 body()->ToNode( |
| 4965 compiler, | 4992 compiler, |
| 4966 success = new NegativeSubmatchSuccess(stack_pointer_register, | 4993 success = new(zone) NegativeSubmatchSuccess(stack_pointer_register, |
| 4967 position_register, | 4994 position_register, |
| 4968 register_count, | 4995 register_count, |
| 4969 register_start, | 4996 register_start, |
| 4970 compiler->zone()))); | 4997 zone))); |
| 4971 ChoiceNode* choice_node = | 4998 ChoiceNode* choice_node = |
| 4972 new NegativeLookaheadChoiceNode(body_alt, | 4999 new(zone) NegativeLookaheadChoiceNode(body_alt, |
| 4973 GuardedAlternative(on_success), | 5000 GuardedAlternative(on_success), |
| 4974 compiler->zone()); | 5001 zone); |
| 4975 return ActionNode::BeginSubmatch(stack_pointer_register, | 5002 return ActionNode::BeginSubmatch(stack_pointer_register, |
| 4976 position_register, | 5003 position_register, |
| 4977 choice_node); | 5004 choice_node); |
| 4978 } | 5005 } |
| 4979 } | 5006 } |
| 4980 | 5007 |
| 4981 | 5008 |
| 4982 RegExpNode* RegExpCapture::ToNode(RegExpCompiler* compiler, | 5009 RegExpNode* RegExpCapture::ToNode(RegExpCompiler* compiler, |
| 4983 RegExpNode* on_success) { | 5010 RegExpNode* on_success) { |
| 4984 return ToNode(body(), index(), compiler, on_success); | 5011 return ToNode(body(), index(), compiler, on_success); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 5003 RegExpNode* current = on_success; | 5030 RegExpNode* current = on_success; |
| 5004 for (int i = children->length() - 1; i >= 0; i--) { | 5031 for (int i = children->length() - 1; i >= 0; i--) { |
| 5005 current = children->at(i)->ToNode(compiler, current); | 5032 current = children->at(i)->ToNode(compiler, current); |
| 5006 } | 5033 } |
| 5007 return current; | 5034 return current; |
| 5008 } | 5035 } |
| 5009 | 5036 |
| 5010 | 5037 |
| 5011 static void AddClass(const int* elmv, | 5038 static void AddClass(const int* elmv, |
| 5012 int elmc, | 5039 int elmc, |
| 5013 ZoneList<CharacterRange>* ranges) { | 5040 ZoneList<CharacterRange>* ranges, |
| 5041 Zone* zone) { |
| 5014 elmc--; | 5042 elmc--; |
| 5015 ASSERT(elmv[elmc] == 0x10000); | 5043 ASSERT(elmv[elmc] == 0x10000); |
| 5016 for (int i = 0; i < elmc; i += 2) { | 5044 for (int i = 0; i < elmc; i += 2) { |
| 5017 ASSERT(elmv[i] < elmv[i + 1]); | 5045 ASSERT(elmv[i] < elmv[i + 1]); |
| 5018 ranges->Add(CharacterRange(elmv[i], elmv[i + 1] - 1)); | 5046 ranges->Add(CharacterRange(elmv[i], elmv[i + 1] - 1), zone); |
| 5019 } | 5047 } |
| 5020 } | 5048 } |
| 5021 | 5049 |
| 5022 | 5050 |
| 5023 static void AddClassNegated(const int *elmv, | 5051 static void AddClassNegated(const int *elmv, |
| 5024 int elmc, | 5052 int elmc, |
| 5025 ZoneList<CharacterRange>* ranges) { | 5053 ZoneList<CharacterRange>* ranges, |
| 5054 Zone* zone) { |
| 5026 elmc--; | 5055 elmc--; |
| 5027 ASSERT(elmv[elmc] == 0x10000); | 5056 ASSERT(elmv[elmc] == 0x10000); |
| 5028 ASSERT(elmv[0] != 0x0000); | 5057 ASSERT(elmv[0] != 0x0000); |
| 5029 ASSERT(elmv[elmc-1] != String::kMaxUtf16CodeUnit); | 5058 ASSERT(elmv[elmc-1] != String::kMaxUtf16CodeUnit); |
| 5030 uc16 last = 0x0000; | 5059 uc16 last = 0x0000; |
| 5031 for (int i = 0; i < elmc; i += 2) { | 5060 for (int i = 0; i < elmc; i += 2) { |
| 5032 ASSERT(last <= elmv[i] - 1); | 5061 ASSERT(last <= elmv[i] - 1); |
| 5033 ASSERT(elmv[i] < elmv[i + 1]); | 5062 ASSERT(elmv[i] < elmv[i + 1]); |
| 5034 ranges->Add(CharacterRange(last, elmv[i] - 1)); | 5063 ranges->Add(CharacterRange(last, elmv[i] - 1), zone); |
| 5035 last = elmv[i + 1]; | 5064 last = elmv[i + 1]; |
| 5036 } | 5065 } |
| 5037 ranges->Add(CharacterRange(last, String::kMaxUtf16CodeUnit)); | 5066 ranges->Add(CharacterRange(last, String::kMaxUtf16CodeUnit), zone); |
| 5038 } | 5067 } |
| 5039 | 5068 |
| 5040 | 5069 |
| 5041 void CharacterRange::AddClassEscape(uc16 type, | 5070 void CharacterRange::AddClassEscape(uc16 type, |
| 5042 ZoneList<CharacterRange>* ranges) { | 5071 ZoneList<CharacterRange>* ranges, |
| 5072 Zone* zone) { |
| 5043 switch (type) { | 5073 switch (type) { |
| 5044 case 's': | 5074 case 's': |
| 5045 AddClass(kSpaceRanges, kSpaceRangeCount, ranges); | 5075 AddClass(kSpaceRanges, kSpaceRangeCount, ranges, zone); |
| 5046 break; | 5076 break; |
| 5047 case 'S': | 5077 case 'S': |
| 5048 AddClassNegated(kSpaceRanges, kSpaceRangeCount, ranges); | 5078 AddClassNegated(kSpaceRanges, kSpaceRangeCount, ranges, zone); |
| 5049 break; | 5079 break; |
| 5050 case 'w': | 5080 case 'w': |
| 5051 AddClass(kWordRanges, kWordRangeCount, ranges); | 5081 AddClass(kWordRanges, kWordRangeCount, ranges, zone); |
| 5052 break; | 5082 break; |
| 5053 case 'W': | 5083 case 'W': |
| 5054 AddClassNegated(kWordRanges, kWordRangeCount, ranges); | 5084 AddClassNegated(kWordRanges, kWordRangeCount, ranges, zone); |
| 5055 break; | 5085 break; |
| 5056 case 'd': | 5086 case 'd': |
| 5057 AddClass(kDigitRanges, kDigitRangeCount, ranges); | 5087 AddClass(kDigitRanges, kDigitRangeCount, ranges, zone); |
| 5058 break; | 5088 break; |
| 5059 case 'D': | 5089 case 'D': |
| 5060 AddClassNegated(kDigitRanges, kDigitRangeCount, ranges); | 5090 AddClassNegated(kDigitRanges, kDigitRangeCount, ranges, zone); |
| 5061 break; | 5091 break; |
| 5062 case '.': | 5092 case '.': |
| 5063 AddClassNegated(kLineTerminatorRanges, | 5093 AddClassNegated(kLineTerminatorRanges, |
| 5064 kLineTerminatorRangeCount, | 5094 kLineTerminatorRangeCount, |
| 5065 ranges); | 5095 ranges, |
| 5096 zone); |
| 5066 break; | 5097 break; |
| 5067 // This is not a character range as defined by the spec but a | 5098 // This is not a character range as defined by the spec but a |
| 5068 // convenient shorthand for a character class that matches any | 5099 // convenient shorthand for a character class that matches any |
| 5069 // character. | 5100 // character. |
| 5070 case '*': | 5101 case '*': |
| 5071 ranges->Add(CharacterRange::Everything()); | 5102 ranges->Add(CharacterRange::Everything(), zone); |
| 5072 break; | 5103 break; |
| 5073 // This is the set of characters matched by the $ and ^ symbols | 5104 // This is the set of characters matched by the $ and ^ symbols |
| 5074 // in multiline mode. | 5105 // in multiline mode. |
| 5075 case 'n': | 5106 case 'n': |
| 5076 AddClass(kLineTerminatorRanges, | 5107 AddClass(kLineTerminatorRanges, |
| 5077 kLineTerminatorRangeCount, | 5108 kLineTerminatorRangeCount, |
| 5078 ranges); | 5109 ranges, |
| 5110 zone); |
| 5079 break; | 5111 break; |
| 5080 default: | 5112 default: |
| 5081 UNREACHABLE(); | 5113 UNREACHABLE(); |
| 5082 } | 5114 } |
| 5083 } | 5115 } |
| 5084 | 5116 |
| 5085 | 5117 |
| 5086 Vector<const int> CharacterRange::GetWordBounds() { | 5118 Vector<const int> CharacterRange::GetWordBounds() { |
| 5087 return Vector<const int>(kWordRanges, kWordRangeCount - 1); | 5119 return Vector<const int>(kWordRanges, kWordRangeCount - 1); |
| 5088 } | 5120 } |
| 5089 | 5121 |
| 5090 | 5122 |
| 5091 class CharacterRangeSplitter { | 5123 class CharacterRangeSplitter { |
| 5092 public: | 5124 public: |
| 5093 CharacterRangeSplitter(ZoneList<CharacterRange>** included, | 5125 CharacterRangeSplitter(ZoneList<CharacterRange>** included, |
| 5094 ZoneList<CharacterRange>** excluded) | 5126 ZoneList<CharacterRange>** excluded, |
| 5127 Zone* zone) |
| 5095 : included_(included), | 5128 : included_(included), |
| 5096 excluded_(excluded) { } | 5129 excluded_(excluded), |
| 5130 zone_(zone) { } |
| 5097 void Call(uc16 from, DispatchTable::Entry entry); | 5131 void Call(uc16 from, DispatchTable::Entry entry); |
| 5098 | 5132 |
| 5099 static const int kInBase = 0; | 5133 static const int kInBase = 0; |
| 5100 static const int kInOverlay = 1; | 5134 static const int kInOverlay = 1; |
| 5101 | 5135 |
| 5102 private: | 5136 private: |
| 5103 ZoneList<CharacterRange>** included_; | 5137 ZoneList<CharacterRange>** included_; |
| 5104 ZoneList<CharacterRange>** excluded_; | 5138 ZoneList<CharacterRange>** excluded_; |
| 5139 Zone* zone_; |
| 5105 }; | 5140 }; |
| 5106 | 5141 |
| 5107 | 5142 |
| 5108 void CharacterRangeSplitter::Call(uc16 from, DispatchTable::Entry entry) { | 5143 void CharacterRangeSplitter::Call(uc16 from, DispatchTable::Entry entry) { |
| 5109 if (!entry.out_set()->Get(kInBase)) return; | 5144 if (!entry.out_set()->Get(kInBase)) return; |
| 5110 ZoneList<CharacterRange>** target = entry.out_set()->Get(kInOverlay) | 5145 ZoneList<CharacterRange>** target = entry.out_set()->Get(kInOverlay) |
| 5111 ? included_ | 5146 ? included_ |
| 5112 : excluded_; | 5147 : excluded_; |
| 5113 if (*target == NULL) *target = new ZoneList<CharacterRange>(2); | 5148 if (*target == NULL) *target = new(zone_) ZoneList<CharacterRange>(2, zone_); |
| 5114 (*target)->Add(CharacterRange(entry.from(), entry.to())); | 5149 (*target)->Add(CharacterRange(entry.from(), entry.to()), zone_); |
| 5115 } | 5150 } |
| 5116 | 5151 |
| 5117 | 5152 |
| 5118 void CharacterRange::Split(ZoneList<CharacterRange>* base, | 5153 void CharacterRange::Split(ZoneList<CharacterRange>* base, |
| 5119 Vector<const int> overlay, | 5154 Vector<const int> overlay, |
| 5120 ZoneList<CharacterRange>** included, | 5155 ZoneList<CharacterRange>** included, |
| 5121 ZoneList<CharacterRange>** excluded) { | 5156 ZoneList<CharacterRange>** excluded, |
| 5157 Zone* zone) { |
| 5122 ASSERT_EQ(NULL, *included); | 5158 ASSERT_EQ(NULL, *included); |
| 5123 ASSERT_EQ(NULL, *excluded); | 5159 ASSERT_EQ(NULL, *excluded); |
| 5124 DispatchTable table; | 5160 DispatchTable table(zone); |
| 5125 for (int i = 0; i < base->length(); i++) | 5161 for (int i = 0; i < base->length(); i++) |
| 5126 table.AddRange(base->at(i), CharacterRangeSplitter::kInBase); | 5162 table.AddRange(base->at(i), CharacterRangeSplitter::kInBase, zone); |
| 5127 for (int i = 0; i < overlay.length(); i += 2) { | 5163 for (int i = 0; i < overlay.length(); i += 2) { |
| 5128 table.AddRange(CharacterRange(overlay[i], overlay[i + 1] - 1), | 5164 table.AddRange(CharacterRange(overlay[i], overlay[i + 1] - 1), |
| 5129 CharacterRangeSplitter::kInOverlay); | 5165 CharacterRangeSplitter::kInOverlay, zone); |
| 5130 } | 5166 } |
| 5131 CharacterRangeSplitter callback(included, excluded); | 5167 CharacterRangeSplitter callback(included, excluded, zone); |
| 5132 table.ForEach(&callback); | 5168 table.ForEach(&callback); |
| 5133 } | 5169 } |
| 5134 | 5170 |
| 5135 | 5171 |
| 5136 void CharacterRange::AddCaseEquivalents(ZoneList<CharacterRange>* ranges, | 5172 void CharacterRange::AddCaseEquivalents(ZoneList<CharacterRange>* ranges, |
| 5137 bool is_ascii) { | 5173 bool is_ascii, |
| 5174 Zone* zone) { |
| 5138 Isolate* isolate = Isolate::Current(); | 5175 Isolate* isolate = Isolate::Current(); |
| 5139 uc16 bottom = from(); | 5176 uc16 bottom = from(); |
| 5140 uc16 top = to(); | 5177 uc16 top = to(); |
| 5141 if (is_ascii) { | 5178 if (is_ascii) { |
| 5142 if (bottom > String::kMaxAsciiCharCode) return; | 5179 if (bottom > String::kMaxAsciiCharCode) return; |
| 5143 if (top > String::kMaxAsciiCharCode) top = String::kMaxAsciiCharCode; | 5180 if (top > String::kMaxAsciiCharCode) top = String::kMaxAsciiCharCode; |
| 5144 } | 5181 } |
| 5145 unibrow::uchar chars[unibrow::Ecma262UnCanonicalize::kMaxWidth]; | 5182 unibrow::uchar chars[unibrow::Ecma262UnCanonicalize::kMaxWidth]; |
| 5146 if (top == bottom) { | 5183 if (top == bottom) { |
| 5147 // If this is a singleton we just expand the one character. | 5184 // If this is a singleton we just expand the one character. |
| 5148 int length = isolate->jsregexp_uncanonicalize()->get(bottom, '\0', chars); | 5185 int length = isolate->jsregexp_uncanonicalize()->get(bottom, '\0', chars); |
| 5149 for (int i = 0; i < length; i++) { | 5186 for (int i = 0; i < length; i++) { |
| 5150 uc32 chr = chars[i]; | 5187 uc32 chr = chars[i]; |
| 5151 if (chr != bottom) { | 5188 if (chr != bottom) { |
| 5152 ranges->Add(CharacterRange::Singleton(chars[i])); | 5189 ranges->Add(CharacterRange::Singleton(chars[i]), zone); |
| 5153 } | 5190 } |
| 5154 } | 5191 } |
| 5155 } else { | 5192 } else { |
| 5156 // If this is a range we expand the characters block by block, | 5193 // If this is a range we expand the characters block by block, |
| 5157 // expanding contiguous subranges (blocks) one at a time. | 5194 // expanding contiguous subranges (blocks) one at a time. |
| 5158 // The approach is as follows. For a given start character we | 5195 // The approach is as follows. For a given start character we |
| 5159 // look up the remainder of the block that contains it (represented | 5196 // look up the remainder of the block that contains it (represented |
| 5160 // by the end point), for instance we find 'z' if the character | 5197 // by the end point), for instance we find 'z' if the character |
| 5161 // is 'c'. A block is characterized by the property | 5198 // is 'c'. A block is characterized by the property |
| 5162 // that all characters uncanonicalize in the same way, except that | 5199 // that all characters uncanonicalize in the same way, except that |
| (...skipping 19 matching lines...) Expand all Loading... |
| 5182 ASSERT_EQ(1, length); | 5219 ASSERT_EQ(1, length); |
| 5183 block_end = range[0]; | 5220 block_end = range[0]; |
| 5184 } | 5221 } |
| 5185 int end = (block_end > top) ? top : block_end; | 5222 int end = (block_end > top) ? top : block_end; |
| 5186 length = isolate->jsregexp_uncanonicalize()->get(block_end, '\0', range); | 5223 length = isolate->jsregexp_uncanonicalize()->get(block_end, '\0', range); |
| 5187 for (int i = 0; i < length; i++) { | 5224 for (int i = 0; i < length; i++) { |
| 5188 uc32 c = range[i]; | 5225 uc32 c = range[i]; |
| 5189 uc16 range_from = c - (block_end - pos); | 5226 uc16 range_from = c - (block_end - pos); |
| 5190 uc16 range_to = c - (block_end - end); | 5227 uc16 range_to = c - (block_end - end); |
| 5191 if (!(bottom <= range_from && range_to <= top)) { | 5228 if (!(bottom <= range_from && range_to <= top)) { |
| 5192 ranges->Add(CharacterRange(range_from, range_to)); | 5229 ranges->Add(CharacterRange(range_from, range_to), zone); |
| 5193 } | 5230 } |
| 5194 } | 5231 } |
| 5195 pos = end + 1; | 5232 pos = end + 1; |
| 5196 } | 5233 } |
| 5197 } | 5234 } |
| 5198 } | 5235 } |
| 5199 | 5236 |
| 5200 | 5237 |
| 5201 bool CharacterRange::IsCanonical(ZoneList<CharacterRange>* ranges) { | 5238 bool CharacterRange::IsCanonical(ZoneList<CharacterRange>* ranges) { |
| 5202 ASSERT_NOT_NULL(ranges); | 5239 ASSERT_NOT_NULL(ranges); |
| 5203 int n = ranges->length(); | 5240 int n = ranges->length(); |
| 5204 if (n <= 1) return true; | 5241 if (n <= 1) return true; |
| 5205 int max = ranges->at(0).to(); | 5242 int max = ranges->at(0).to(); |
| 5206 for (int i = 1; i < n; i++) { | 5243 for (int i = 1; i < n; i++) { |
| 5207 CharacterRange next_range = ranges->at(i); | 5244 CharacterRange next_range = ranges->at(i); |
| 5208 if (next_range.from() <= max + 1) return false; | 5245 if (next_range.from() <= max + 1) return false; |
| 5209 max = next_range.to(); | 5246 max = next_range.to(); |
| 5210 } | 5247 } |
| 5211 return true; | 5248 return true; |
| 5212 } | 5249 } |
| 5213 | 5250 |
| 5214 | 5251 |
| 5215 ZoneList<CharacterRange>* CharacterSet::ranges() { | 5252 ZoneList<CharacterRange>* CharacterSet::ranges(Zone* zone) { |
| 5216 if (ranges_ == NULL) { | 5253 if (ranges_ == NULL) { |
| 5217 ranges_ = new ZoneList<CharacterRange>(2); | 5254 ranges_ = new(zone) ZoneList<CharacterRange>(2, zone); |
| 5218 CharacterRange::AddClassEscape(standard_set_type_, ranges_); | 5255 CharacterRange::AddClassEscape(standard_set_type_, ranges_, zone); |
| 5219 } | 5256 } |
| 5220 return ranges_; | 5257 return ranges_; |
| 5221 } | 5258 } |
| 5222 | 5259 |
| 5223 | 5260 |
| 5224 // Move a number of elements in a zonelist to another position | 5261 // Move a number of elements in a zonelist to another position |
| 5225 // in the same list. Handles overlapping source and target areas. | 5262 // in the same list. Handles overlapping source and target areas. |
| 5226 static void MoveRanges(ZoneList<CharacterRange>* list, | 5263 static void MoveRanges(ZoneList<CharacterRange>* list, |
| 5227 int from, | 5264 int from, |
| 5228 int to, | 5265 int to, |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5337 character_ranges->at(read)); | 5374 character_ranges->at(read)); |
| 5338 read++; | 5375 read++; |
| 5339 } while (read < n); | 5376 } while (read < n); |
| 5340 character_ranges->Rewind(num_canonical); | 5377 character_ranges->Rewind(num_canonical); |
| 5341 | 5378 |
| 5342 ASSERT(CharacterRange::IsCanonical(character_ranges)); | 5379 ASSERT(CharacterRange::IsCanonical(character_ranges)); |
| 5343 } | 5380 } |
| 5344 | 5381 |
| 5345 | 5382 |
| 5346 void CharacterRange::Negate(ZoneList<CharacterRange>* ranges, | 5383 void CharacterRange::Negate(ZoneList<CharacterRange>* ranges, |
| 5347 ZoneList<CharacterRange>* negated_ranges) { | 5384 ZoneList<CharacterRange>* negated_ranges, |
| 5385 Zone* zone) { |
| 5348 ASSERT(CharacterRange::IsCanonical(ranges)); | 5386 ASSERT(CharacterRange::IsCanonical(ranges)); |
| 5349 ASSERT_EQ(0, negated_ranges->length()); | 5387 ASSERT_EQ(0, negated_ranges->length()); |
| 5350 int range_count = ranges->length(); | 5388 int range_count = ranges->length(); |
| 5351 uc16 from = 0; | 5389 uc16 from = 0; |
| 5352 int i = 0; | 5390 int i = 0; |
| 5353 if (range_count > 0 && ranges->at(0).from() == 0) { | 5391 if (range_count > 0 && ranges->at(0).from() == 0) { |
| 5354 from = ranges->at(0).to(); | 5392 from = ranges->at(0).to(); |
| 5355 i = 1; | 5393 i = 1; |
| 5356 } | 5394 } |
| 5357 while (i < range_count) { | 5395 while (i < range_count) { |
| 5358 CharacterRange range = ranges->at(i); | 5396 CharacterRange range = ranges->at(i); |
| 5359 negated_ranges->Add(CharacterRange(from + 1, range.from() - 1)); | 5397 negated_ranges->Add(CharacterRange(from + 1, range.from() - 1), zone); |
| 5360 from = range.to(); | 5398 from = range.to(); |
| 5361 i++; | 5399 i++; |
| 5362 } | 5400 } |
| 5363 if (from < String::kMaxUtf16CodeUnit) { | 5401 if (from < String::kMaxUtf16CodeUnit) { |
| 5364 negated_ranges->Add(CharacterRange(from + 1, String::kMaxUtf16CodeUnit)); | 5402 negated_ranges->Add(CharacterRange(from + 1, String::kMaxUtf16CodeUnit), |
| 5403 zone); |
| 5365 } | 5404 } |
| 5366 } | 5405 } |
| 5367 | 5406 |
| 5368 | 5407 |
| 5369 // ------------------------------------------------------------------- | 5408 // ------------------------------------------------------------------- |
| 5370 // Splay tree | 5409 // Splay tree |
| 5371 | 5410 |
| 5372 | 5411 |
| 5373 OutSet* OutSet::Extend(unsigned value) { | 5412 OutSet* OutSet::Extend(unsigned value, Zone* zone) { |
| 5374 if (Get(value)) | 5413 if (Get(value)) |
| 5375 return this; | 5414 return this; |
| 5376 if (successors() != NULL) { | 5415 if (successors(zone) != NULL) { |
| 5377 for (int i = 0; i < successors()->length(); i++) { | 5416 for (int i = 0; i < successors(zone)->length(); i++) { |
| 5378 OutSet* successor = successors()->at(i); | 5417 OutSet* successor = successors(zone)->at(i); |
| 5379 if (successor->Get(value)) | 5418 if (successor->Get(value)) |
| 5380 return successor; | 5419 return successor; |
| 5381 } | 5420 } |
| 5382 } else { | 5421 } else { |
| 5383 successors_ = new ZoneList<OutSet*>(2); | 5422 successors_ = new(zone) ZoneList<OutSet*>(2, zone); |
| 5384 } | 5423 } |
| 5385 OutSet* result = new OutSet(first_, remaining_); | 5424 OutSet* result = new(zone) OutSet(first_, remaining_); |
| 5386 result->Set(value); | 5425 result->Set(value, zone); |
| 5387 successors()->Add(result); | 5426 successors(zone)->Add(result, zone); |
| 5388 return result; | 5427 return result; |
| 5389 } | 5428 } |
| 5390 | 5429 |
| 5391 | 5430 |
| 5392 void OutSet::Set(unsigned value) { | 5431 void OutSet::Set(unsigned value, Zone *zone) { |
| 5393 if (value < kFirstLimit) { | 5432 if (value < kFirstLimit) { |
| 5394 first_ |= (1 << value); | 5433 first_ |= (1 << value); |
| 5395 } else { | 5434 } else { |
| 5396 if (remaining_ == NULL) | 5435 if (remaining_ == NULL) |
| 5397 remaining_ = new ZoneList<unsigned>(1); | 5436 remaining_ = new(zone) ZoneList<unsigned>(1, zone); |
| 5398 if (remaining_->is_empty() || !remaining_->Contains(value)) | 5437 if (remaining_->is_empty() || !remaining_->Contains(value)) |
| 5399 remaining_->Add(value); | 5438 remaining_->Add(value, zone); |
| 5400 } | 5439 } |
| 5401 } | 5440 } |
| 5402 | 5441 |
| 5403 | 5442 |
| 5404 bool OutSet::Get(unsigned value) { | 5443 bool OutSet::Get(unsigned value) { |
| 5405 if (value < kFirstLimit) { | 5444 if (value < kFirstLimit) { |
| 5406 return (first_ & (1 << value)) != 0; | 5445 return (first_ & (1 << value)) != 0; |
| 5407 } else if (remaining_ == NULL) { | 5446 } else if (remaining_ == NULL) { |
| 5408 return false; | 5447 return false; |
| 5409 } else { | 5448 } else { |
| 5410 return remaining_->Contains(value); | 5449 return remaining_->Contains(value); |
| 5411 } | 5450 } |
| 5412 } | 5451 } |
| 5413 | 5452 |
| 5414 | 5453 |
| 5415 const uc16 DispatchTable::Config::kNoKey = unibrow::Utf8::kBadChar; | 5454 const uc16 DispatchTable::Config::kNoKey = unibrow::Utf8::kBadChar; |
| 5416 | 5455 |
| 5417 | 5456 |
| 5418 void DispatchTable::AddRange(CharacterRange full_range, int value) { | 5457 void DispatchTable::AddRange(CharacterRange full_range, int value, |
| 5458 Zone* zone) { |
| 5419 CharacterRange current = full_range; | 5459 CharacterRange current = full_range; |
| 5420 if (tree()->is_empty()) { | 5460 if (tree()->is_empty()) { |
| 5421 // If this is the first range we just insert into the table. | 5461 // If this is the first range we just insert into the table. |
| 5422 ZoneSplayTree<Config>::Locator loc; | 5462 ZoneSplayTree<Config>::Locator loc; |
| 5423 ASSERT_RESULT(tree()->Insert(current.from(), &loc)); | 5463 ASSERT_RESULT(tree()->Insert(current.from(), &loc)); |
| 5424 loc.set_value(Entry(current.from(), current.to(), empty()->Extend(value))); | 5464 loc.set_value(Entry(current.from(), current.to(), |
| 5465 empty()->Extend(value, zone))); |
| 5425 return; | 5466 return; |
| 5426 } | 5467 } |
| 5427 // First see if there is a range to the left of this one that | 5468 // First see if there is a range to the left of this one that |
| 5428 // overlaps. | 5469 // overlaps. |
| 5429 ZoneSplayTree<Config>::Locator loc; | 5470 ZoneSplayTree<Config>::Locator loc; |
| 5430 if (tree()->FindGreatestLessThan(current.from(), &loc)) { | 5471 if (tree()->FindGreatestLessThan(current.from(), &loc)) { |
| 5431 Entry* entry = &loc.value(); | 5472 Entry* entry = &loc.value(); |
| 5432 // If we've found a range that overlaps with this one, and it | 5473 // If we've found a range that overlaps with this one, and it |
| 5433 // starts strictly to the left of this one, we have to fix it | 5474 // starts strictly to the left of this one, we have to fix it |
| 5434 // because the following code only handles ranges that start on | 5475 // because the following code only handles ranges that start on |
| (...skipping 22 matching lines...) Expand all Loading... |
| 5457 (loc.value().to() >= current.from())) { | 5498 (loc.value().to() >= current.from())) { |
| 5458 Entry* entry = &loc.value(); | 5499 Entry* entry = &loc.value(); |
| 5459 // We have overlap. If there is space between the start point of | 5500 // We have overlap. If there is space between the start point of |
| 5460 // the range we're adding and where the overlapping range starts | 5501 // the range we're adding and where the overlapping range starts |
| 5461 // then we have to add a range covering just that space. | 5502 // then we have to add a range covering just that space. |
| 5462 if (current.from() < entry->from()) { | 5503 if (current.from() < entry->from()) { |
| 5463 ZoneSplayTree<Config>::Locator ins; | 5504 ZoneSplayTree<Config>::Locator ins; |
| 5464 ASSERT_RESULT(tree()->Insert(current.from(), &ins)); | 5505 ASSERT_RESULT(tree()->Insert(current.from(), &ins)); |
| 5465 ins.set_value(Entry(current.from(), | 5506 ins.set_value(Entry(current.from(), |
| 5466 entry->from() - 1, | 5507 entry->from() - 1, |
| 5467 empty()->Extend(value))); | 5508 empty()->Extend(value, zone))); |
| 5468 current.set_from(entry->from()); | 5509 current.set_from(entry->from()); |
| 5469 } | 5510 } |
| 5470 ASSERT_EQ(current.from(), entry->from()); | 5511 ASSERT_EQ(current.from(), entry->from()); |
| 5471 // If the overlapping range extends beyond the one we want to add | 5512 // If the overlapping range extends beyond the one we want to add |
| 5472 // we have to snap the right part off and add it separately. | 5513 // we have to snap the right part off and add it separately. |
| 5473 if (entry->to() > current.to()) { | 5514 if (entry->to() > current.to()) { |
| 5474 ZoneSplayTree<Config>::Locator ins; | 5515 ZoneSplayTree<Config>::Locator ins; |
| 5475 ASSERT_RESULT(tree()->Insert(current.to() + 1, &ins)); | 5516 ASSERT_RESULT(tree()->Insert(current.to() + 1, &ins)); |
| 5476 ins.set_value(Entry(current.to() + 1, | 5517 ins.set_value(Entry(current.to() + 1, |
| 5477 entry->to(), | 5518 entry->to(), |
| 5478 entry->out_set())); | 5519 entry->out_set())); |
| 5479 entry->set_to(current.to()); | 5520 entry->set_to(current.to()); |
| 5480 } | 5521 } |
| 5481 ASSERT(entry->to() <= current.to()); | 5522 ASSERT(entry->to() <= current.to()); |
| 5482 // The overlapping range is now completely contained by the range | 5523 // The overlapping range is now completely contained by the range |
| 5483 // we're adding so we can just update it and move the start point | 5524 // we're adding so we can just update it and move the start point |
| 5484 // of the range we're adding just past it. | 5525 // of the range we're adding just past it. |
| 5485 entry->AddValue(value); | 5526 entry->AddValue(value, zone); |
| 5486 // Bail out if the last interval ended at 0xFFFF since otherwise | 5527 // Bail out if the last interval ended at 0xFFFF since otherwise |
| 5487 // adding 1 will wrap around to 0. | 5528 // adding 1 will wrap around to 0. |
| 5488 if (entry->to() == String::kMaxUtf16CodeUnit) | 5529 if (entry->to() == String::kMaxUtf16CodeUnit) |
| 5489 break; | 5530 break; |
| 5490 ASSERT(entry->to() + 1 > current.from()); | 5531 ASSERT(entry->to() + 1 > current.from()); |
| 5491 current.set_from(entry->to() + 1); | 5532 current.set_from(entry->to() + 1); |
| 5492 } else { | 5533 } else { |
| 5493 // There is no overlap so we can just add the range | 5534 // There is no overlap so we can just add the range |
| 5494 ZoneSplayTree<Config>::Locator ins; | 5535 ZoneSplayTree<Config>::Locator ins; |
| 5495 ASSERT_RESULT(tree()->Insert(current.from(), &ins)); | 5536 ASSERT_RESULT(tree()->Insert(current.from(), &ins)); |
| 5496 ins.set_value(Entry(current.from(), | 5537 ins.set_value(Entry(current.from(), |
| 5497 current.to(), | 5538 current.to(), |
| 5498 empty()->Extend(value))); | 5539 empty()->Extend(value, zone))); |
| 5499 break; | 5540 break; |
| 5500 } | 5541 } |
| 5501 } | 5542 } |
| 5502 } | 5543 } |
| 5503 | 5544 |
| 5504 | 5545 |
| 5505 OutSet* DispatchTable::Get(uc16 value) { | 5546 OutSet* DispatchTable::Get(uc16 value) { |
| 5506 ZoneSplayTree<Config>::Locator loc; | 5547 ZoneSplayTree<Config>::Locator loc; |
| 5507 if (!tree()->FindGreatestLessThan(value, &loc)) | 5548 if (!tree()->FindGreatestLessThan(value, &loc)) |
| 5508 return empty(); | 5549 return empty(); |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5688 for (int j = 0; j < length; j++) { | 5729 for (int j = 0; j < length; j++) { |
| 5689 bm->Set(offset, chars[j]); | 5730 bm->Set(offset, chars[j]); |
| 5690 } | 5731 } |
| 5691 } else { | 5732 } else { |
| 5692 if (character <= max_char) bm->Set(offset, character); | 5733 if (character <= max_char) bm->Set(offset, character); |
| 5693 } | 5734 } |
| 5694 } | 5735 } |
| 5695 } else { | 5736 } else { |
| 5696 ASSERT(text.type == TextElement::CHAR_CLASS); | 5737 ASSERT(text.type == TextElement::CHAR_CLASS); |
| 5697 RegExpCharacterClass* char_class = text.data.u_char_class; | 5738 RegExpCharacterClass* char_class = text.data.u_char_class; |
| 5698 ZoneList<CharacterRange>* ranges = char_class->ranges(); | 5739 ZoneList<CharacterRange>* ranges = char_class->ranges(zone()); |
| 5699 if (char_class->is_negated()) { | 5740 if (char_class->is_negated()) { |
| 5700 bm->SetAll(offset); | 5741 bm->SetAll(offset); |
| 5701 } else { | 5742 } else { |
| 5702 for (int k = 0; k < ranges->length(); k++) { | 5743 for (int k = 0; k < ranges->length(); k++) { |
| 5703 CharacterRange& range = ranges->at(k); | 5744 CharacterRange& range = ranges->at(k); |
| 5704 if (range.from() > max_char) continue; | 5745 if (range.from() > max_char) continue; |
| 5705 int to = Min(max_char, static_cast<int>(range.to())); | 5746 int to = Min(max_char, static_cast<int>(range.to())); |
| 5706 bm->SetInterval(offset, Interval(range.from(), to)); | 5747 bm->SetInterval(offset, Interval(range.from(), to)); |
| 5707 } | 5748 } |
| 5708 } | 5749 } |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5808 void DispatchTableConstructor::VisitText(TextNode* that) { | 5849 void DispatchTableConstructor::VisitText(TextNode* that) { |
| 5809 TextElement elm = that->elements()->at(0); | 5850 TextElement elm = that->elements()->at(0); |
| 5810 switch (elm.type) { | 5851 switch (elm.type) { |
| 5811 case TextElement::ATOM: { | 5852 case TextElement::ATOM: { |
| 5812 uc16 c = elm.data.u_atom->data()[0]; | 5853 uc16 c = elm.data.u_atom->data()[0]; |
| 5813 AddRange(CharacterRange(c, c)); | 5854 AddRange(CharacterRange(c, c)); |
| 5814 break; | 5855 break; |
| 5815 } | 5856 } |
| 5816 case TextElement::CHAR_CLASS: { | 5857 case TextElement::CHAR_CLASS: { |
| 5817 RegExpCharacterClass* tree = elm.data.u_char_class; | 5858 RegExpCharacterClass* tree = elm.data.u_char_class; |
| 5818 ZoneList<CharacterRange>* ranges = tree->ranges(); | 5859 ZoneList<CharacterRange>* ranges = tree->ranges(that->zone()); |
| 5819 if (tree->is_negated()) { | 5860 if (tree->is_negated()) { |
| 5820 AddInverse(ranges); | 5861 AddInverse(ranges); |
| 5821 } else { | 5862 } else { |
| 5822 for (int i = 0; i < ranges->length(); i++) | 5863 for (int i = 0; i < ranges->length(); i++) |
| 5823 AddRange(ranges->at(i)); | 5864 AddRange(ranges->at(i)); |
| 5824 } | 5865 } |
| 5825 break; | 5866 break; |
| 5826 } | 5867 } |
| 5827 default: { | 5868 default: { |
| 5828 UNIMPLEMENTED(); | 5869 UNIMPLEMENTED(); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5872 bool is_end_anchored = data->tree->IsAnchoredAtEnd(); | 5913 bool is_end_anchored = data->tree->IsAnchoredAtEnd(); |
| 5873 bool is_start_anchored = data->tree->IsAnchoredAtStart(); | 5914 bool is_start_anchored = data->tree->IsAnchoredAtStart(); |
| 5874 int max_length = data->tree->max_match(); | 5915 int max_length = data->tree->max_match(); |
| 5875 if (!is_start_anchored) { | 5916 if (!is_start_anchored) { |
| 5876 // Add a .*? at the beginning, outside the body capture, unless | 5917 // Add a .*? at the beginning, outside the body capture, unless |
| 5877 // this expression is anchored at the beginning. | 5918 // this expression is anchored at the beginning. |
| 5878 RegExpNode* loop_node = | 5919 RegExpNode* loop_node = |
| 5879 RegExpQuantifier::ToNode(0, | 5920 RegExpQuantifier::ToNode(0, |
| 5880 RegExpTree::kInfinity, | 5921 RegExpTree::kInfinity, |
| 5881 false, | 5922 false, |
| 5882 new RegExpCharacterClass('*'), | 5923 new(zone) RegExpCharacterClass('*'), |
| 5883 &compiler, | 5924 &compiler, |
| 5884 captured_body, | 5925 captured_body, |
| 5885 data->contains_anchor); | 5926 data->contains_anchor); |
| 5886 | 5927 |
| 5887 if (data->contains_anchor) { | 5928 if (data->contains_anchor) { |
| 5888 // Unroll loop once, to take care of the case that might start | 5929 // Unroll loop once, to take care of the case that might start |
| 5889 // at the start of input. | 5930 // at the start of input. |
| 5890 ChoiceNode* first_step_node = new ChoiceNode(2, zone); | 5931 ChoiceNode* first_step_node = new(zone) ChoiceNode(2, zone); |
| 5891 first_step_node->AddAlternative(GuardedAlternative(captured_body)); | 5932 first_step_node->AddAlternative(GuardedAlternative(captured_body)); |
| 5892 first_step_node->AddAlternative(GuardedAlternative( | 5933 first_step_node->AddAlternative(GuardedAlternative( |
| 5893 new TextNode(new RegExpCharacterClass('*'), loop_node))); | 5934 new(zone) TextNode(new(zone) RegExpCharacterClass('*'), loop_node))); |
| 5894 node = first_step_node; | 5935 node = first_step_node; |
| 5895 } else { | 5936 } else { |
| 5896 node = loop_node; | 5937 node = loop_node; |
| 5897 } | 5938 } |
| 5898 } | 5939 } |
| 5899 if (is_ascii) { | 5940 if (is_ascii) { |
| 5900 node = node->FilterASCII(RegExpCompiler::kMaxRecursion); | 5941 node = node->FilterASCII(RegExpCompiler::kMaxRecursion); |
| 5901 // Do it again to propagate the new nodes to places where they were not | 5942 // Do it again to propagate the new nodes to places where they were not |
| 5902 // put because they had not been calculated yet. | 5943 // put because they had not been calculated yet. |
| 5903 if (node != NULL) node = node->FilterASCII(RegExpCompiler::kMaxRecursion); | 5944 if (node != NULL) node = node->FilterASCII(RegExpCompiler::kMaxRecursion); |
| 5904 } | 5945 } |
| 5905 | 5946 |
| 5906 if (node == NULL) node = new EndNode(EndNode::BACKTRACK, zone); | 5947 if (node == NULL) node = new(zone) EndNode(EndNode::BACKTRACK, zone); |
| 5907 data->node = node; | 5948 data->node = node; |
| 5908 Analysis analysis(ignore_case, is_ascii); | 5949 Analysis analysis(ignore_case, is_ascii); |
| 5909 analysis.EnsureAnalyzed(node); | 5950 analysis.EnsureAnalyzed(node); |
| 5910 if (analysis.has_failed()) { | 5951 if (analysis.has_failed()) { |
| 5911 const char* error_message = analysis.error_message(); | 5952 const char* error_message = analysis.error_message(); |
| 5912 return CompilationResult(error_message); | 5953 return CompilationResult(error_message); |
| 5913 } | 5954 } |
| 5914 | 5955 |
| 5915 // Create the correct assembler for the architecture. | 5956 // Create the correct assembler for the architecture. |
| 5916 #ifndef V8_INTERPRETED_REGEXP | 5957 #ifndef V8_INTERPRETED_REGEXP |
| 5917 // Native regexp implementation. | 5958 // Native regexp implementation. |
| 5918 | 5959 |
| 5919 NativeRegExpMacroAssembler::Mode mode = | 5960 NativeRegExpMacroAssembler::Mode mode = |
| 5920 is_ascii ? NativeRegExpMacroAssembler::ASCII | 5961 is_ascii ? NativeRegExpMacroAssembler::ASCII |
| 5921 : NativeRegExpMacroAssembler::UC16; | 5962 : NativeRegExpMacroAssembler::UC16; |
| 5922 | 5963 |
| 5923 #if V8_TARGET_ARCH_IA32 | 5964 #if V8_TARGET_ARCH_IA32 |
| 5924 RegExpMacroAssemblerIA32 macro_assembler(mode, (data->capture_count + 1) * 2); | 5965 RegExpMacroAssemblerIA32 macro_assembler(mode, (data->capture_count + 1) * 2, |
| 5966 zone); |
| 5925 #elif V8_TARGET_ARCH_X64 | 5967 #elif V8_TARGET_ARCH_X64 |
| 5926 RegExpMacroAssemblerX64 macro_assembler(mode, (data->capture_count + 1) * 2); | 5968 RegExpMacroAssemblerX64 macro_assembler(mode, (data->capture_count + 1) * 2, |
| 5969 zone); |
| 5927 #elif V8_TARGET_ARCH_ARM | 5970 #elif V8_TARGET_ARCH_ARM |
| 5928 RegExpMacroAssemblerARM macro_assembler(mode, (data->capture_count + 1) * 2); | 5971 RegExpMacroAssemblerARM macro_assembler(mode, (data->capture_count + 1) * 2, |
| 5972 zone); |
| 5929 #elif V8_TARGET_ARCH_MIPS | 5973 #elif V8_TARGET_ARCH_MIPS |
| 5930 RegExpMacroAssemblerMIPS macro_assembler(mode, (data->capture_count + 1) * 2); | 5974 RegExpMacroAssemblerMIPS macro_assembler(mode, (data->capture_count + 1) * 2); |
| 5931 #endif | 5975 #endif |
| 5932 | 5976 |
| 5933 #else // V8_INTERPRETED_REGEXP | 5977 #else // V8_INTERPRETED_REGEXP |
| 5934 // Interpreted regexp implementation. | 5978 // Interpreted regexp implementation. |
| 5935 EmbeddedVector<byte, 1024> codes; | 5979 EmbeddedVector<byte, 1024> codes; |
| 5936 RegExpMacroAssemblerIrregexp macro_assembler(codes); | 5980 RegExpMacroAssemblerIrregexp macro_assembler(codes); |
| 5937 #endif // V8_INTERPRETED_REGEXP | 5981 #endif // V8_INTERPRETED_REGEXP |
| 5938 | 5982 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 5953 } | 5997 } |
| 5954 | 5998 |
| 5955 return compiler.Assemble(¯o_assembler, | 5999 return compiler.Assemble(¯o_assembler, |
| 5956 node, | 6000 node, |
| 5957 data->capture_count, | 6001 data->capture_count, |
| 5958 pattern); | 6002 pattern); |
| 5959 } | 6003 } |
| 5960 | 6004 |
| 5961 | 6005 |
| 5962 }} // namespace v8::internal | 6006 }} // namespace v8::internal |
| OLD | NEW |