| 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(); |
| 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 439 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4350 stream()->Add(" a%p -> n%p [style=dashed, color=grey, " | 4366 stream()->Add(" a%p -> n%p [style=dashed, color=grey, " |
| 4351 "arrowhead=none];\n", that, that); | 4367 "arrowhead=none];\n", that, that); |
| 4352 } | 4368 } |
| 4353 | 4369 |
| 4354 | 4370 |
| 4355 static const bool kPrintDispatchTable = false; | 4371 static const bool kPrintDispatchTable = false; |
| 4356 void DotPrinter::VisitChoice(ChoiceNode* that) { | 4372 void DotPrinter::VisitChoice(ChoiceNode* that) { |
| 4357 if (kPrintDispatchTable) { | 4373 if (kPrintDispatchTable) { |
| 4358 stream()->Add(" n%p [shape=Mrecord, label=\"", that); | 4374 stream()->Add(" n%p [shape=Mrecord, label=\"", that); |
| 4359 TableEntryHeaderPrinter header_printer(stream()); | 4375 TableEntryHeaderPrinter header_printer(stream()); |
| 4360 that->GetTable(ignore_case_)->ForEach(&header_printer); | 4376 that->GetTable(ignore_case_)->ForEach(&header_printer, that->zone()); |
| 4361 stream()->Add("\"]\n", that); | 4377 stream()->Add("\"]\n", that); |
| 4362 PrintAttributes(that); | 4378 PrintAttributes(that); |
| 4363 TableEntryBodyPrinter body_printer(stream(), that); | 4379 TableEntryBodyPrinter body_printer(stream(), that); |
| 4364 that->GetTable(ignore_case_)->ForEach(&body_printer); | 4380 that->GetTable(ignore_case_)->ForEach(&body_printer, that->zone()); |
| 4365 } else { | 4381 } else { |
| 4366 stream()->Add(" n%p [shape=Mrecord, label=\"?\"];\n", that); | 4382 stream()->Add(" n%p [shape=Mrecord, label=\"?\"];\n", that); |
| 4367 for (int i = 0; i < that->alternatives()->length(); i++) { | 4383 for (int i = 0; i < that->alternatives()->length(); i++) { |
| 4368 GuardedAlternative alt = that->alternatives()->at(i); | 4384 GuardedAlternative alt = that->alternatives()->at(i); |
| 4369 stream()->Add(" n%p -> n%p;\n", that, alt.node()); | 4385 stream()->Add(" n%p -> n%p;\n", that, alt.node()); |
| 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 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4522 } | 4539 } |
| 4523 } | 4540 } |
| 4524 stream()->Add("}\n"); | 4541 stream()->Add("}\n"); |
| 4525 } | 4542 } |
| 4526 | 4543 |
| 4527 | 4544 |
| 4528 void DispatchTable::Dump() { | 4545 void DispatchTable::Dump() { |
| 4529 HeapStringAllocator alloc; | 4546 HeapStringAllocator alloc; |
| 4530 StringStream stream(&alloc); | 4547 StringStream stream(&alloc); |
| 4531 DispatchTableDumper dumper(&stream); | 4548 DispatchTableDumper dumper(&stream); |
| 4532 tree()->ForEach(&dumper); | 4549 Zone* zone = Isolate::Current()->zone(); |
| 4550 tree()->ForEach(&dumper, ZoneAllocationPolicy(zone)); |
| 4533 OS::PrintError("%s", *stream.ToCString()); | 4551 OS::PrintError("%s", *stream.ToCString()); |
| 4534 } | 4552 } |
| 4535 | 4553 |
| 4536 | 4554 |
| 4537 void RegExpEngine::DotPrint(const char* label, | 4555 void RegExpEngine::DotPrint(const char* label, |
| 4538 RegExpNode* node, | 4556 RegExpNode* node, |
| 4539 bool ignore_case) { | 4557 bool ignore_case) { |
| 4540 DotPrinter printer(ignore_case); | 4558 DotPrinter printer(ignore_case); |
| 4541 printer.PrintNode(label, node); | 4559 printer.PrintNode(label, node); |
| 4542 } | 4560 } |
| 4543 | 4561 |
| 4544 | 4562 |
| 4545 #endif // DEBUG | 4563 #endif // DEBUG |
| 4546 | 4564 |
| 4547 | 4565 |
| 4548 // ------------------------------------------------------------------- | 4566 // ------------------------------------------------------------------- |
| 4549 // Tree to graph conversion | 4567 // Tree to graph conversion |
| 4550 | 4568 |
| 4551 RegExpNode* RegExpAtom::ToNode(RegExpCompiler* compiler, | 4569 RegExpNode* RegExpAtom::ToNode(RegExpCompiler* compiler, |
| 4552 RegExpNode* on_success) { | 4570 RegExpNode* on_success) { |
| 4553 ZoneList<TextElement>* elms = new ZoneList<TextElement>(1); | 4571 ZoneList<TextElement>* elms = |
| 4554 elms->Add(TextElement::Atom(this)); | 4572 new(compiler->zone()) ZoneList<TextElement>(1, compiler->zone()); |
| 4555 return new TextNode(elms, on_success); | 4573 elms->Add(TextElement::Atom(this), compiler->zone()); |
| 4574 return new(compiler->zone()) TextNode(elms, on_success); |
| 4556 } | 4575 } |
| 4557 | 4576 |
| 4558 | 4577 |
| 4559 RegExpNode* RegExpText::ToNode(RegExpCompiler* compiler, | 4578 RegExpNode* RegExpText::ToNode(RegExpCompiler* compiler, |
| 4560 RegExpNode* on_success) { | 4579 RegExpNode* on_success) { |
| 4561 return new TextNode(elements(), on_success); | 4580 return new(compiler->zone()) TextNode(elements(), on_success); |
| 4562 } | 4581 } |
| 4563 | 4582 |
| 4564 | 4583 |
| 4565 static bool CompareInverseRanges(ZoneList<CharacterRange>* ranges, | 4584 static bool CompareInverseRanges(ZoneList<CharacterRange>* ranges, |
| 4566 const int* special_class, | 4585 const int* special_class, |
| 4567 int length) { | 4586 int length) { |
| 4568 length--; // Remove final 0x10000. | 4587 length--; // Remove final 0x10000. |
| 4569 ASSERT(special_class[length] == 0x10000); | 4588 ASSERT(special_class[length] == 0x10000); |
| 4570 ASSERT(ranges->length() != 0); | 4589 ASSERT(ranges->length() != 0); |
| 4571 ASSERT(length != 0); | 4590 ASSERT(length != 0); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4605 CharacterRange range = ranges->at(i >> 1); | 4624 CharacterRange range = ranges->at(i >> 1); |
| 4606 if (range.from() != special_class[i] || | 4625 if (range.from() != special_class[i] || |
| 4607 range.to() != special_class[i + 1] - 1) { | 4626 range.to() != special_class[i + 1] - 1) { |
| 4608 return false; | 4627 return false; |
| 4609 } | 4628 } |
| 4610 } | 4629 } |
| 4611 return true; | 4630 return true; |
| 4612 } | 4631 } |
| 4613 | 4632 |
| 4614 | 4633 |
| 4615 bool RegExpCharacterClass::is_standard() { | 4634 bool RegExpCharacterClass::is_standard(Zone* zone) { |
| 4616 // TODO(lrn): Remove need for this function, by not throwing away information | 4635 // TODO(lrn): Remove need for this function, by not throwing away information |
| 4617 // along the way. | 4636 // along the way. |
| 4618 if (is_negated_) { | 4637 if (is_negated_) { |
| 4619 return false; | 4638 return false; |
| 4620 } | 4639 } |
| 4621 if (set_.is_standard()) { | 4640 if (set_.is_standard()) { |
| 4622 return true; | 4641 return true; |
| 4623 } | 4642 } |
| 4624 if (CompareRanges(set_.ranges(), kSpaceRanges, kSpaceRangeCount)) { | 4643 if (CompareRanges(set_.ranges(zone), kSpaceRanges, kSpaceRangeCount)) { |
| 4625 set_.set_standard_set_type('s'); | 4644 set_.set_standard_set_type('s'); |
| 4626 return true; | 4645 return true; |
| 4627 } | 4646 } |
| 4628 if (CompareInverseRanges(set_.ranges(), kSpaceRanges, kSpaceRangeCount)) { | 4647 if (CompareInverseRanges(set_.ranges(zone), kSpaceRanges, kSpaceRangeCount)) { |
| 4629 set_.set_standard_set_type('S'); | 4648 set_.set_standard_set_type('S'); |
| 4630 return true; | 4649 return true; |
| 4631 } | 4650 } |
| 4632 if (CompareInverseRanges(set_.ranges(), | 4651 if (CompareInverseRanges(set_.ranges(zone), |
| 4633 kLineTerminatorRanges, | 4652 kLineTerminatorRanges, |
| 4634 kLineTerminatorRangeCount)) { | 4653 kLineTerminatorRangeCount)) { |
| 4635 set_.set_standard_set_type('.'); | 4654 set_.set_standard_set_type('.'); |
| 4636 return true; | 4655 return true; |
| 4637 } | 4656 } |
| 4638 if (CompareRanges(set_.ranges(), | 4657 if (CompareRanges(set_.ranges(zone), |
| 4639 kLineTerminatorRanges, | 4658 kLineTerminatorRanges, |
| 4640 kLineTerminatorRangeCount)) { | 4659 kLineTerminatorRangeCount)) { |
| 4641 set_.set_standard_set_type('n'); | 4660 set_.set_standard_set_type('n'); |
| 4642 return true; | 4661 return true; |
| 4643 } | 4662 } |
| 4644 if (CompareRanges(set_.ranges(), kWordRanges, kWordRangeCount)) { | 4663 if (CompareRanges(set_.ranges(zone), kWordRanges, kWordRangeCount)) { |
| 4645 set_.set_standard_set_type('w'); | 4664 set_.set_standard_set_type('w'); |
| 4646 return true; | 4665 return true; |
| 4647 } | 4666 } |
| 4648 if (CompareInverseRanges(set_.ranges(), kWordRanges, kWordRangeCount)) { | 4667 if (CompareInverseRanges(set_.ranges(zone), kWordRanges, kWordRangeCount)) { |
| 4649 set_.set_standard_set_type('W'); | 4668 set_.set_standard_set_type('W'); |
| 4650 return true; | 4669 return true; |
| 4651 } | 4670 } |
| 4652 return false; | 4671 return false; |
| 4653 } | 4672 } |
| 4654 | 4673 |
| 4655 | 4674 |
| 4656 RegExpNode* RegExpCharacterClass::ToNode(RegExpCompiler* compiler, | 4675 RegExpNode* RegExpCharacterClass::ToNode(RegExpCompiler* compiler, |
| 4657 RegExpNode* on_success) { | 4676 RegExpNode* on_success) { |
| 4658 return new TextNode(this, on_success); | 4677 return new(compiler->zone()) TextNode(this, on_success); |
| 4659 } | 4678 } |
| 4660 | 4679 |
| 4661 | 4680 |
| 4662 RegExpNode* RegExpDisjunction::ToNode(RegExpCompiler* compiler, | 4681 RegExpNode* RegExpDisjunction::ToNode(RegExpCompiler* compiler, |
| 4663 RegExpNode* on_success) { | 4682 RegExpNode* on_success) { |
| 4664 ZoneList<RegExpTree*>* alternatives = this->alternatives(); | 4683 ZoneList<RegExpTree*>* alternatives = this->alternatives(); |
| 4665 int length = alternatives->length(); | 4684 int length = alternatives->length(); |
| 4666 ChoiceNode* result = new ChoiceNode(length, compiler->zone()); | 4685 ChoiceNode* result = |
| 4686 new(compiler->zone()) ChoiceNode(length, compiler->zone()); |
| 4667 for (int i = 0; i < length; i++) { | 4687 for (int i = 0; i < length; i++) { |
| 4668 GuardedAlternative alternative(alternatives->at(i)->ToNode(compiler, | 4688 GuardedAlternative alternative(alternatives->at(i)->ToNode(compiler, |
| 4669 on_success)); | 4689 on_success)); |
| 4670 result->AddAlternative(alternative); | 4690 result->AddAlternative(alternative); |
| 4671 } | 4691 } |
| 4672 return result; | 4692 return result; |
| 4673 } | 4693 } |
| 4674 | 4694 |
| 4675 | 4695 |
| 4676 RegExpNode* RegExpQuantifier::ToNode(RegExpCompiler* compiler, | 4696 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 | 4769 // 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 | 4770 // from step 2.1. If the min and max are small we can unroll a little in |
| 4751 // this case. | 4771 // this case. |
| 4752 static const int kMaxUnrolledMinMatches = 3; // Unroll (foo)+ and (foo){3,} | 4772 static const int kMaxUnrolledMinMatches = 3; // Unroll (foo)+ and (foo){3,} |
| 4753 static const int kMaxUnrolledMaxMatches = 3; // Unroll (foo)? and (foo){x,3} | 4773 static const int kMaxUnrolledMaxMatches = 3; // Unroll (foo)? and (foo){x,3} |
| 4754 if (max == 0) return on_success; // This can happen due to recursion. | 4774 if (max == 0) return on_success; // This can happen due to recursion. |
| 4755 bool body_can_be_empty = (body->min_match() == 0); | 4775 bool body_can_be_empty = (body->min_match() == 0); |
| 4756 int body_start_reg = RegExpCompiler::kNoRegister; | 4776 int body_start_reg = RegExpCompiler::kNoRegister; |
| 4757 Interval capture_registers = body->CaptureRegisters(); | 4777 Interval capture_registers = body->CaptureRegisters(); |
| 4758 bool needs_capture_clearing = !capture_registers.is_empty(); | 4778 bool needs_capture_clearing = !capture_registers.is_empty(); |
| 4779 Zone* zone = compiler->zone(); |
| 4780 |
| 4759 if (body_can_be_empty) { | 4781 if (body_can_be_empty) { |
| 4760 body_start_reg = compiler->AllocateRegister(); | 4782 body_start_reg = compiler->AllocateRegister(); |
| 4761 } else if (FLAG_regexp_optimization && !needs_capture_clearing) { | 4783 } else if (FLAG_regexp_optimization && !needs_capture_clearing) { |
| 4762 // Only unroll if there are no captures and the body can't be | 4784 // Only unroll if there are no captures and the body can't be |
| 4763 // empty. | 4785 // empty. |
| 4764 { | 4786 { |
| 4765 RegExpExpansionLimiter limiter( | 4787 RegExpExpansionLimiter limiter( |
| 4766 compiler, min + ((max != min) ? 1 : 0)); | 4788 compiler, min + ((max != min) ? 1 : 0)); |
| 4767 if (min > 0 && min <= kMaxUnrolledMinMatches && limiter.ok_to_expand()) { | 4789 if (min > 0 && min <= kMaxUnrolledMinMatches && limiter.ok_to_expand()) { |
| 4768 int new_max = (max == kInfinity) ? max : max - min; | 4790 int new_max = (max == kInfinity) ? max : max - min; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 4779 return answer; | 4801 return answer; |
| 4780 } | 4802 } |
| 4781 } | 4803 } |
| 4782 if (max <= kMaxUnrolledMaxMatches && min == 0) { | 4804 if (max <= kMaxUnrolledMaxMatches && min == 0) { |
| 4783 ASSERT(max > 0); // Due to the 'if' above. | 4805 ASSERT(max > 0); // Due to the 'if' above. |
| 4784 RegExpExpansionLimiter limiter(compiler, max); | 4806 RegExpExpansionLimiter limiter(compiler, max); |
| 4785 if (limiter.ok_to_expand()) { | 4807 if (limiter.ok_to_expand()) { |
| 4786 // Unroll the optional matches up to max. | 4808 // Unroll the optional matches up to max. |
| 4787 RegExpNode* answer = on_success; | 4809 RegExpNode* answer = on_success; |
| 4788 for (int i = 0; i < max; i++) { | 4810 for (int i = 0; i < max; i++) { |
| 4789 ChoiceNode* alternation = new ChoiceNode(2, compiler->zone()); | 4811 ChoiceNode* alternation = new(zone) ChoiceNode(2, zone); |
| 4790 if (is_greedy) { | 4812 if (is_greedy) { |
| 4791 alternation->AddAlternative( | 4813 alternation->AddAlternative( |
| 4792 GuardedAlternative(body->ToNode(compiler, answer))); | 4814 GuardedAlternative(body->ToNode(compiler, answer))); |
| 4793 alternation->AddAlternative(GuardedAlternative(on_success)); | 4815 alternation->AddAlternative(GuardedAlternative(on_success)); |
| 4794 } else { | 4816 } else { |
| 4795 alternation->AddAlternative(GuardedAlternative(on_success)); | 4817 alternation->AddAlternative(GuardedAlternative(on_success)); |
| 4796 alternation->AddAlternative( | 4818 alternation->AddAlternative( |
| 4797 GuardedAlternative(body->ToNode(compiler, answer))); | 4819 GuardedAlternative(body->ToNode(compiler, answer))); |
| 4798 } | 4820 } |
| 4799 answer = alternation; | 4821 answer = alternation; |
| 4800 if (not_at_start) alternation->set_not_at_start(); | 4822 if (not_at_start) alternation->set_not_at_start(); |
| 4801 } | 4823 } |
| 4802 return answer; | 4824 return answer; |
| 4803 } | 4825 } |
| 4804 } | 4826 } |
| 4805 } | 4827 } |
| 4806 bool has_min = min > 0; | 4828 bool has_min = min > 0; |
| 4807 bool has_max = max < RegExpTree::kInfinity; | 4829 bool has_max = max < RegExpTree::kInfinity; |
| 4808 bool needs_counter = has_min || has_max; | 4830 bool needs_counter = has_min || has_max; |
| 4809 int reg_ctr = needs_counter | 4831 int reg_ctr = needs_counter |
| 4810 ? compiler->AllocateRegister() | 4832 ? compiler->AllocateRegister() |
| 4811 : RegExpCompiler::kNoRegister; | 4833 : RegExpCompiler::kNoRegister; |
| 4812 LoopChoiceNode* center = new LoopChoiceNode(body->min_match() == 0, | 4834 LoopChoiceNode* center = new(zone) LoopChoiceNode(body->min_match() == 0, |
| 4813 compiler->zone()); | 4835 zone); |
| 4814 if (not_at_start) center->set_not_at_start(); | 4836 if (not_at_start) center->set_not_at_start(); |
| 4815 RegExpNode* loop_return = needs_counter | 4837 RegExpNode* loop_return = needs_counter |
| 4816 ? static_cast<RegExpNode*>(ActionNode::IncrementRegister(reg_ctr, center)) | 4838 ? static_cast<RegExpNode*>(ActionNode::IncrementRegister(reg_ctr, center)) |
| 4817 : static_cast<RegExpNode*>(center); | 4839 : static_cast<RegExpNode*>(center); |
| 4818 if (body_can_be_empty) { | 4840 if (body_can_be_empty) { |
| 4819 // If the body can be empty we need to check if it was and then | 4841 // If the body can be empty we need to check if it was and then |
| 4820 // backtrack. | 4842 // backtrack. |
| 4821 loop_return = ActionNode::EmptyMatchCheck(body_start_reg, | 4843 loop_return = ActionNode::EmptyMatchCheck(body_start_reg, |
| 4822 reg_ctr, | 4844 reg_ctr, |
| 4823 min, | 4845 min, |
| 4824 loop_return); | 4846 loop_return); |
| 4825 } | 4847 } |
| 4826 RegExpNode* body_node = body->ToNode(compiler, loop_return); | 4848 RegExpNode* body_node = body->ToNode(compiler, loop_return); |
| 4827 if (body_can_be_empty) { | 4849 if (body_can_be_empty) { |
| 4828 // If the body can be empty we need to store the start position | 4850 // If the body can be empty we need to store the start position |
| 4829 // so we can bail out if it was empty. | 4851 // so we can bail out if it was empty. |
| 4830 body_node = ActionNode::StorePosition(body_start_reg, false, body_node); | 4852 body_node = ActionNode::StorePosition(body_start_reg, false, body_node); |
| 4831 } | 4853 } |
| 4832 if (needs_capture_clearing) { | 4854 if (needs_capture_clearing) { |
| 4833 // Before entering the body of this loop we need to clear captures. | 4855 // Before entering the body of this loop we need to clear captures. |
| 4834 body_node = ActionNode::ClearCaptures(capture_registers, body_node); | 4856 body_node = ActionNode::ClearCaptures(capture_registers, body_node); |
| 4835 } | 4857 } |
| 4836 GuardedAlternative body_alt(body_node); | 4858 GuardedAlternative body_alt(body_node); |
| 4837 if (has_max) { | 4859 if (has_max) { |
| 4838 Guard* body_guard = new Guard(reg_ctr, Guard::LT, max); | 4860 Guard* body_guard = |
| 4839 body_alt.AddGuard(body_guard); | 4861 new(zone) Guard(reg_ctr, Guard::LT, max); |
| 4862 body_alt.AddGuard(body_guard, zone); |
| 4840 } | 4863 } |
| 4841 GuardedAlternative rest_alt(on_success); | 4864 GuardedAlternative rest_alt(on_success); |
| 4842 if (has_min) { | 4865 if (has_min) { |
| 4843 Guard* rest_guard = new Guard(reg_ctr, Guard::GEQ, min); | 4866 Guard* rest_guard = new(compiler->zone()) Guard(reg_ctr, Guard::GEQ, min); |
| 4844 rest_alt.AddGuard(rest_guard); | 4867 rest_alt.AddGuard(rest_guard, zone); |
| 4845 } | 4868 } |
| 4846 if (is_greedy) { | 4869 if (is_greedy) { |
| 4847 center->AddLoopAlternative(body_alt); | 4870 center->AddLoopAlternative(body_alt); |
| 4848 center->AddContinueAlternative(rest_alt); | 4871 center->AddContinueAlternative(rest_alt); |
| 4849 } else { | 4872 } else { |
| 4850 center->AddContinueAlternative(rest_alt); | 4873 center->AddContinueAlternative(rest_alt); |
| 4851 center->AddLoopAlternative(body_alt); | 4874 center->AddLoopAlternative(body_alt); |
| 4852 } | 4875 } |
| 4853 if (needs_counter) { | 4876 if (needs_counter) { |
| 4854 return ActionNode::SetRegister(reg_ctr, 0, center); | 4877 return ActionNode::SetRegister(reg_ctr, 0, center); |
| 4855 } else { | 4878 } else { |
| 4856 return center; | 4879 return center; |
| 4857 } | 4880 } |
| 4858 } | 4881 } |
| 4859 | 4882 |
| 4860 | 4883 |
| 4861 RegExpNode* RegExpAssertion::ToNode(RegExpCompiler* compiler, | 4884 RegExpNode* RegExpAssertion::ToNode(RegExpCompiler* compiler, |
| 4862 RegExpNode* on_success) { | 4885 RegExpNode* on_success) { |
| 4863 NodeInfo info; | 4886 NodeInfo info; |
| 4887 Zone* zone = compiler->zone(); |
| 4888 |
| 4864 switch (type()) { | 4889 switch (type()) { |
| 4865 case START_OF_LINE: | 4890 case START_OF_LINE: |
| 4866 return AssertionNode::AfterNewline(on_success); | 4891 return AssertionNode::AfterNewline(on_success); |
| 4867 case START_OF_INPUT: | 4892 case START_OF_INPUT: |
| 4868 return AssertionNode::AtStart(on_success); | 4893 return AssertionNode::AtStart(on_success); |
| 4869 case BOUNDARY: | 4894 case BOUNDARY: |
| 4870 return AssertionNode::AtBoundary(on_success); | 4895 return AssertionNode::AtBoundary(on_success); |
| 4871 case NON_BOUNDARY: | 4896 case NON_BOUNDARY: |
| 4872 return AssertionNode::AtNonBoundary(on_success); | 4897 return AssertionNode::AtNonBoundary(on_success); |
| 4873 case END_OF_INPUT: | 4898 case END_OF_INPUT: |
| 4874 return AssertionNode::AtEnd(on_success); | 4899 return AssertionNode::AtEnd(on_success); |
| 4875 case END_OF_LINE: { | 4900 case END_OF_LINE: { |
| 4876 // Compile $ in multiline regexps as an alternation with a positive | 4901 // Compile $ in multiline regexps as an alternation with a positive |
| 4877 // lookahead in one side and an end-of-input on the other side. | 4902 // lookahead in one side and an end-of-input on the other side. |
| 4878 // We need two registers for the lookahead. | 4903 // We need two registers for the lookahead. |
| 4879 int stack_pointer_register = compiler->AllocateRegister(); | 4904 int stack_pointer_register = compiler->AllocateRegister(); |
| 4880 int position_register = compiler->AllocateRegister(); | 4905 int position_register = compiler->AllocateRegister(); |
| 4881 // The ChoiceNode to distinguish between a newline and end-of-input. | 4906 // The ChoiceNode to distinguish between a newline and end-of-input. |
| 4882 ChoiceNode* result = new ChoiceNode(2, compiler->zone()); | 4907 ChoiceNode* result = new(zone) ChoiceNode(2, zone); |
| 4883 // Create a newline atom. | 4908 // Create a newline atom. |
| 4884 ZoneList<CharacterRange>* newline_ranges = | 4909 ZoneList<CharacterRange>* newline_ranges = |
| 4885 new ZoneList<CharacterRange>(3); | 4910 new(zone) ZoneList<CharacterRange>(3, zone); |
| 4886 CharacterRange::AddClassEscape('n', newline_ranges); | 4911 CharacterRange::AddClassEscape('n', newline_ranges, zone); |
| 4887 RegExpCharacterClass* newline_atom = new RegExpCharacterClass('n'); | 4912 RegExpCharacterClass* newline_atom = new(zone) RegExpCharacterClass('n'); |
| 4888 TextNode* newline_matcher = new TextNode( | 4913 TextNode* newline_matcher = new(zone) TextNode( |
| 4889 newline_atom, | 4914 newline_atom, |
| 4890 ActionNode::PositiveSubmatchSuccess(stack_pointer_register, | 4915 ActionNode::PositiveSubmatchSuccess(stack_pointer_register, |
| 4891 position_register, | 4916 position_register, |
| 4892 0, // No captures inside. | 4917 0, // No captures inside. |
| 4893 -1, // Ignored if no captures. | 4918 -1, // Ignored if no captures. |
| 4894 on_success)); | 4919 on_success)); |
| 4895 // Create an end-of-input matcher. | 4920 // Create an end-of-input matcher. |
| 4896 RegExpNode* end_of_line = ActionNode::BeginSubmatch( | 4921 RegExpNode* end_of_line = ActionNode::BeginSubmatch( |
| 4897 stack_pointer_register, | 4922 stack_pointer_register, |
| 4898 position_register, | 4923 position_register, |
| 4899 newline_matcher); | 4924 newline_matcher); |
| 4900 // Add the two alternatives to the ChoiceNode. | 4925 // Add the two alternatives to the ChoiceNode. |
| 4901 GuardedAlternative eol_alternative(end_of_line); | 4926 GuardedAlternative eol_alternative(end_of_line); |
| 4902 result->AddAlternative(eol_alternative); | 4927 result->AddAlternative(eol_alternative); |
| 4903 GuardedAlternative end_alternative(AssertionNode::AtEnd(on_success)); | 4928 GuardedAlternative end_alternative(AssertionNode::AtEnd(on_success)); |
| 4904 result->AddAlternative(end_alternative); | 4929 result->AddAlternative(end_alternative); |
| 4905 return result; | 4930 return result; |
| 4906 } | 4931 } |
| 4907 default: | 4932 default: |
| 4908 UNREACHABLE(); | 4933 UNREACHABLE(); |
| 4909 } | 4934 } |
| 4910 return on_success; | 4935 return on_success; |
| 4911 } | 4936 } |
| 4912 | 4937 |
| 4913 | 4938 |
| 4914 RegExpNode* RegExpBackReference::ToNode(RegExpCompiler* compiler, | 4939 RegExpNode* RegExpBackReference::ToNode(RegExpCompiler* compiler, |
| 4915 RegExpNode* on_success) { | 4940 RegExpNode* on_success) { |
| 4916 return new BackReferenceNode(RegExpCapture::StartRegister(index()), | 4941 return new(compiler->zone()) |
| 4917 RegExpCapture::EndRegister(index()), | 4942 BackReferenceNode(RegExpCapture::StartRegister(index()), |
| 4918 on_success); | 4943 RegExpCapture::EndRegister(index()), |
| 4944 on_success); |
| 4919 } | 4945 } |
| 4920 | 4946 |
| 4921 | 4947 |
| 4922 RegExpNode* RegExpEmpty::ToNode(RegExpCompiler* compiler, | 4948 RegExpNode* RegExpEmpty::ToNode(RegExpCompiler* compiler, |
| 4923 RegExpNode* on_success) { | 4949 RegExpNode* on_success) { |
| 4924 return on_success; | 4950 return on_success; |
| 4925 } | 4951 } |
| 4926 | 4952 |
| 4927 | 4953 |
| 4928 RegExpNode* RegExpLookahead::ToNode(RegExpCompiler* compiler, | 4954 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 | 4979 // 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 | 4980 // 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 | 4981 // first alternative and the expression after the lookahead of the second |
| 4956 // alternative. If the first alternative succeeds then the | 4982 // alternative. If the first alternative succeeds then the |
| 4957 // NegativeSubmatchSuccess will unwind the stack including everything the | 4983 // NegativeSubmatchSuccess will unwind the stack including everything the |
| 4958 // choice node set up and backtrack. If the first alternative fails then | 4984 // choice node set up and backtrack. If the first alternative fails then |
| 4959 // the second alternative is tried, which is exactly the desired result | 4985 // the second alternative is tried, which is exactly the desired result |
| 4960 // for a negative lookahead. The NegativeLookaheadChoiceNode is a special | 4986 // for a negative lookahead. The NegativeLookaheadChoiceNode is a special |
| 4961 // ChoiceNode that knows to ignore the first exit when calculating quick | 4987 // ChoiceNode that knows to ignore the first exit when calculating quick |
| 4962 // checks. | 4988 // checks. |
| 4989 Zone* zone = compiler->zone(); |
| 4990 |
| 4963 GuardedAlternative body_alt( | 4991 GuardedAlternative body_alt( |
| 4964 body()->ToNode( | 4992 body()->ToNode( |
| 4965 compiler, | 4993 compiler, |
| 4966 success = new NegativeSubmatchSuccess(stack_pointer_register, | 4994 success = new(zone) NegativeSubmatchSuccess(stack_pointer_register, |
| 4967 position_register, | 4995 position_register, |
| 4968 register_count, | 4996 register_count, |
| 4969 register_start, | 4997 register_start, |
| 4970 compiler->zone()))); | 4998 zone))); |
| 4971 ChoiceNode* choice_node = | 4999 ChoiceNode* choice_node = |
| 4972 new NegativeLookaheadChoiceNode(body_alt, | 5000 new(zone) NegativeLookaheadChoiceNode(body_alt, |
| 4973 GuardedAlternative(on_success), | 5001 GuardedAlternative(on_success), |
| 4974 compiler->zone()); | 5002 zone); |
| 4975 return ActionNode::BeginSubmatch(stack_pointer_register, | 5003 return ActionNode::BeginSubmatch(stack_pointer_register, |
| 4976 position_register, | 5004 position_register, |
| 4977 choice_node); | 5005 choice_node); |
| 4978 } | 5006 } |
| 4979 } | 5007 } |
| 4980 | 5008 |
| 4981 | 5009 |
| 4982 RegExpNode* RegExpCapture::ToNode(RegExpCompiler* compiler, | 5010 RegExpNode* RegExpCapture::ToNode(RegExpCompiler* compiler, |
| 4983 RegExpNode* on_success) { | 5011 RegExpNode* on_success) { |
| 4984 return ToNode(body(), index(), compiler, on_success); | 5012 return ToNode(body(), index(), compiler, on_success); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 5003 RegExpNode* current = on_success; | 5031 RegExpNode* current = on_success; |
| 5004 for (int i = children->length() - 1; i >= 0; i--) { | 5032 for (int i = children->length() - 1; i >= 0; i--) { |
| 5005 current = children->at(i)->ToNode(compiler, current); | 5033 current = children->at(i)->ToNode(compiler, current); |
| 5006 } | 5034 } |
| 5007 return current; | 5035 return current; |
| 5008 } | 5036 } |
| 5009 | 5037 |
| 5010 | 5038 |
| 5011 static void AddClass(const int* elmv, | 5039 static void AddClass(const int* elmv, |
| 5012 int elmc, | 5040 int elmc, |
| 5013 ZoneList<CharacterRange>* ranges) { | 5041 ZoneList<CharacterRange>* ranges, |
| 5042 Zone* zone) { |
| 5014 elmc--; | 5043 elmc--; |
| 5015 ASSERT(elmv[elmc] == 0x10000); | 5044 ASSERT(elmv[elmc] == 0x10000); |
| 5016 for (int i = 0; i < elmc; i += 2) { | 5045 for (int i = 0; i < elmc; i += 2) { |
| 5017 ASSERT(elmv[i] < elmv[i + 1]); | 5046 ASSERT(elmv[i] < elmv[i + 1]); |
| 5018 ranges->Add(CharacterRange(elmv[i], elmv[i + 1] - 1)); | 5047 ranges->Add(CharacterRange(elmv[i], elmv[i + 1] - 1), zone); |
| 5019 } | 5048 } |
| 5020 } | 5049 } |
| 5021 | 5050 |
| 5022 | 5051 |
| 5023 static void AddClassNegated(const int *elmv, | 5052 static void AddClassNegated(const int *elmv, |
| 5024 int elmc, | 5053 int elmc, |
| 5025 ZoneList<CharacterRange>* ranges) { | 5054 ZoneList<CharacterRange>* ranges, |
| 5055 Zone* zone) { |
| 5026 elmc--; | 5056 elmc--; |
| 5027 ASSERT(elmv[elmc] == 0x10000); | 5057 ASSERT(elmv[elmc] == 0x10000); |
| 5028 ASSERT(elmv[0] != 0x0000); | 5058 ASSERT(elmv[0] != 0x0000); |
| 5029 ASSERT(elmv[elmc-1] != String::kMaxUtf16CodeUnit); | 5059 ASSERT(elmv[elmc-1] != String::kMaxUtf16CodeUnit); |
| 5030 uc16 last = 0x0000; | 5060 uc16 last = 0x0000; |
| 5031 for (int i = 0; i < elmc; i += 2) { | 5061 for (int i = 0; i < elmc; i += 2) { |
| 5032 ASSERT(last <= elmv[i] - 1); | 5062 ASSERT(last <= elmv[i] - 1); |
| 5033 ASSERT(elmv[i] < elmv[i + 1]); | 5063 ASSERT(elmv[i] < elmv[i + 1]); |
| 5034 ranges->Add(CharacterRange(last, elmv[i] - 1)); | 5064 ranges->Add(CharacterRange(last, elmv[i] - 1), zone); |
| 5035 last = elmv[i + 1]; | 5065 last = elmv[i + 1]; |
| 5036 } | 5066 } |
| 5037 ranges->Add(CharacterRange(last, String::kMaxUtf16CodeUnit)); | 5067 ranges->Add(CharacterRange(last, String::kMaxUtf16CodeUnit), zone); |
| 5038 } | 5068 } |
| 5039 | 5069 |
| 5040 | 5070 |
| 5041 void CharacterRange::AddClassEscape(uc16 type, | 5071 void CharacterRange::AddClassEscape(uc16 type, |
| 5042 ZoneList<CharacterRange>* ranges) { | 5072 ZoneList<CharacterRange>* ranges, |
| 5073 Zone* zone) { |
| 5043 switch (type) { | 5074 switch (type) { |
| 5044 case 's': | 5075 case 's': |
| 5045 AddClass(kSpaceRanges, kSpaceRangeCount, ranges); | 5076 AddClass(kSpaceRanges, kSpaceRangeCount, ranges, zone); |
| 5046 break; | 5077 break; |
| 5047 case 'S': | 5078 case 'S': |
| 5048 AddClassNegated(kSpaceRanges, kSpaceRangeCount, ranges); | 5079 AddClassNegated(kSpaceRanges, kSpaceRangeCount, ranges, zone); |
| 5049 break; | 5080 break; |
| 5050 case 'w': | 5081 case 'w': |
| 5051 AddClass(kWordRanges, kWordRangeCount, ranges); | 5082 AddClass(kWordRanges, kWordRangeCount, ranges, zone); |
| 5052 break; | 5083 break; |
| 5053 case 'W': | 5084 case 'W': |
| 5054 AddClassNegated(kWordRanges, kWordRangeCount, ranges); | 5085 AddClassNegated(kWordRanges, kWordRangeCount, ranges, zone); |
| 5055 break; | 5086 break; |
| 5056 case 'd': | 5087 case 'd': |
| 5057 AddClass(kDigitRanges, kDigitRangeCount, ranges); | 5088 AddClass(kDigitRanges, kDigitRangeCount, ranges, zone); |
| 5058 break; | 5089 break; |
| 5059 case 'D': | 5090 case 'D': |
| 5060 AddClassNegated(kDigitRanges, kDigitRangeCount, ranges); | 5091 AddClassNegated(kDigitRanges, kDigitRangeCount, ranges, zone); |
| 5061 break; | 5092 break; |
| 5062 case '.': | 5093 case '.': |
| 5063 AddClassNegated(kLineTerminatorRanges, | 5094 AddClassNegated(kLineTerminatorRanges, |
| 5064 kLineTerminatorRangeCount, | 5095 kLineTerminatorRangeCount, |
| 5065 ranges); | 5096 ranges, |
| 5097 zone); |
| 5066 break; | 5098 break; |
| 5067 // This is not a character range as defined by the spec but a | 5099 // This is not a character range as defined by the spec but a |
| 5068 // convenient shorthand for a character class that matches any | 5100 // convenient shorthand for a character class that matches any |
| 5069 // character. | 5101 // character. |
| 5070 case '*': | 5102 case '*': |
| 5071 ranges->Add(CharacterRange::Everything()); | 5103 ranges->Add(CharacterRange::Everything(), zone); |
| 5072 break; | 5104 break; |
| 5073 // This is the set of characters matched by the $ and ^ symbols | 5105 // This is the set of characters matched by the $ and ^ symbols |
| 5074 // in multiline mode. | 5106 // in multiline mode. |
| 5075 case 'n': | 5107 case 'n': |
| 5076 AddClass(kLineTerminatorRanges, | 5108 AddClass(kLineTerminatorRanges, |
| 5077 kLineTerminatorRangeCount, | 5109 kLineTerminatorRangeCount, |
| 5078 ranges); | 5110 ranges, |
| 5111 zone); |
| 5079 break; | 5112 break; |
| 5080 default: | 5113 default: |
| 5081 UNREACHABLE(); | 5114 UNREACHABLE(); |
| 5082 } | 5115 } |
| 5083 } | 5116 } |
| 5084 | 5117 |
| 5085 | 5118 |
| 5086 Vector<const int> CharacterRange::GetWordBounds() { | 5119 Vector<const int> CharacterRange::GetWordBounds() { |
| 5087 return Vector<const int>(kWordRanges, kWordRangeCount - 1); | 5120 return Vector<const int>(kWordRanges, kWordRangeCount - 1); |
| 5088 } | 5121 } |
| 5089 | 5122 |
| 5090 | 5123 |
| 5091 class CharacterRangeSplitter { | 5124 class CharacterRangeSplitter { |
| 5092 public: | 5125 public: |
| 5093 CharacterRangeSplitter(ZoneList<CharacterRange>** included, | 5126 CharacterRangeSplitter(ZoneList<CharacterRange>** included, |
| 5094 ZoneList<CharacterRange>** excluded) | 5127 ZoneList<CharacterRange>** excluded, |
| 5128 Zone* zone) |
| 5095 : included_(included), | 5129 : included_(included), |
| 5096 excluded_(excluded) { } | 5130 excluded_(excluded), |
| 5131 zone_(zone) { } |
| 5097 void Call(uc16 from, DispatchTable::Entry entry); | 5132 void Call(uc16 from, DispatchTable::Entry entry); |
| 5098 | 5133 |
| 5099 static const int kInBase = 0; | 5134 static const int kInBase = 0; |
| 5100 static const int kInOverlay = 1; | 5135 static const int kInOverlay = 1; |
| 5101 | 5136 |
| 5102 private: | 5137 private: |
| 5103 ZoneList<CharacterRange>** included_; | 5138 ZoneList<CharacterRange>** included_; |
| 5104 ZoneList<CharacterRange>** excluded_; | 5139 ZoneList<CharacterRange>** excluded_; |
| 5140 Zone* zone_; |
| 5105 }; | 5141 }; |
| 5106 | 5142 |
| 5107 | 5143 |
| 5108 void CharacterRangeSplitter::Call(uc16 from, DispatchTable::Entry entry) { | 5144 void CharacterRangeSplitter::Call(uc16 from, DispatchTable::Entry entry) { |
| 5109 if (!entry.out_set()->Get(kInBase)) return; | 5145 if (!entry.out_set()->Get(kInBase)) return; |
| 5110 ZoneList<CharacterRange>** target = entry.out_set()->Get(kInOverlay) | 5146 ZoneList<CharacterRange>** target = entry.out_set()->Get(kInOverlay) |
| 5111 ? included_ | 5147 ? included_ |
| 5112 : excluded_; | 5148 : excluded_; |
| 5113 if (*target == NULL) *target = new ZoneList<CharacterRange>(2); | 5149 if (*target == NULL) *target = new(zone_) ZoneList<CharacterRange>(2, zone_); |
| 5114 (*target)->Add(CharacterRange(entry.from(), entry.to())); | 5150 (*target)->Add(CharacterRange(entry.from(), entry.to()), zone_); |
| 5115 } | 5151 } |
| 5116 | 5152 |
| 5117 | 5153 |
| 5118 void CharacterRange::Split(ZoneList<CharacterRange>* base, | 5154 void CharacterRange::Split(ZoneList<CharacterRange>* base, |
| 5119 Vector<const int> overlay, | 5155 Vector<const int> overlay, |
| 5120 ZoneList<CharacterRange>** included, | 5156 ZoneList<CharacterRange>** included, |
| 5121 ZoneList<CharacterRange>** excluded) { | 5157 ZoneList<CharacterRange>** excluded, |
| 5158 Zone* zone) { |
| 5122 ASSERT_EQ(NULL, *included); | 5159 ASSERT_EQ(NULL, *included); |
| 5123 ASSERT_EQ(NULL, *excluded); | 5160 ASSERT_EQ(NULL, *excluded); |
| 5124 DispatchTable table; | 5161 DispatchTable table; |
| 5125 for (int i = 0; i < base->length(); i++) | 5162 for (int i = 0; i < base->length(); i++) |
| 5126 table.AddRange(base->at(i), CharacterRangeSplitter::kInBase); | 5163 table.AddRange(base->at(i), CharacterRangeSplitter::kInBase, zone); |
| 5127 for (int i = 0; i < overlay.length(); i += 2) { | 5164 for (int i = 0; i < overlay.length(); i += 2) { |
| 5128 table.AddRange(CharacterRange(overlay[i], overlay[i + 1] - 1), | 5165 table.AddRange(CharacterRange(overlay[i], overlay[i + 1] - 1), |
| 5129 CharacterRangeSplitter::kInOverlay); | 5166 CharacterRangeSplitter::kInOverlay, zone); |
| 5130 } | 5167 } |
| 5131 CharacterRangeSplitter callback(included, excluded); | 5168 CharacterRangeSplitter callback(included, excluded, zone); |
| 5132 table.ForEach(&callback); | 5169 table.ForEach(&callback, zone); |
| 5133 } | 5170 } |
| 5134 | 5171 |
| 5135 | 5172 |
| 5136 void CharacterRange::AddCaseEquivalents(ZoneList<CharacterRange>* ranges, | 5173 void CharacterRange::AddCaseEquivalents(ZoneList<CharacterRange>* ranges, |
| 5137 bool is_ascii) { | 5174 bool is_ascii, |
| 5175 Zone* zone) { |
| 5138 Isolate* isolate = Isolate::Current(); | 5176 Isolate* isolate = Isolate::Current(); |
| 5139 uc16 bottom = from(); | 5177 uc16 bottom = from(); |
| 5140 uc16 top = to(); | 5178 uc16 top = to(); |
| 5141 if (is_ascii) { | 5179 if (is_ascii) { |
| 5142 if (bottom > String::kMaxAsciiCharCode) return; | 5180 if (bottom > String::kMaxAsciiCharCode) return; |
| 5143 if (top > String::kMaxAsciiCharCode) top = String::kMaxAsciiCharCode; | 5181 if (top > String::kMaxAsciiCharCode) top = String::kMaxAsciiCharCode; |
| 5144 } | 5182 } |
| 5145 unibrow::uchar chars[unibrow::Ecma262UnCanonicalize::kMaxWidth]; | 5183 unibrow::uchar chars[unibrow::Ecma262UnCanonicalize::kMaxWidth]; |
| 5146 if (top == bottom) { | 5184 if (top == bottom) { |
| 5147 // If this is a singleton we just expand the one character. | 5185 // If this is a singleton we just expand the one character. |
| 5148 int length = isolate->jsregexp_uncanonicalize()->get(bottom, '\0', chars); | 5186 int length = isolate->jsregexp_uncanonicalize()->get(bottom, '\0', chars); |
| 5149 for (int i = 0; i < length; i++) { | 5187 for (int i = 0; i < length; i++) { |
| 5150 uc32 chr = chars[i]; | 5188 uc32 chr = chars[i]; |
| 5151 if (chr != bottom) { | 5189 if (chr != bottom) { |
| 5152 ranges->Add(CharacterRange::Singleton(chars[i])); | 5190 ranges->Add(CharacterRange::Singleton(chars[i]), zone); |
| 5153 } | 5191 } |
| 5154 } | 5192 } |
| 5155 } else { | 5193 } else { |
| 5156 // If this is a range we expand the characters block by block, | 5194 // If this is a range we expand the characters block by block, |
| 5157 // expanding contiguous subranges (blocks) one at a time. | 5195 // expanding contiguous subranges (blocks) one at a time. |
| 5158 // The approach is as follows. For a given start character we | 5196 // The approach is as follows. For a given start character we |
| 5159 // look up the remainder of the block that contains it (represented | 5197 // look up the remainder of the block that contains it (represented |
| 5160 // by the end point), for instance we find 'z' if the character | 5198 // by the end point), for instance we find 'z' if the character |
| 5161 // is 'c'. A block is characterized by the property | 5199 // is 'c'. A block is characterized by the property |
| 5162 // that all characters uncanonicalize in the same way, except that | 5200 // that all characters uncanonicalize in the same way, except that |
| (...skipping 19 matching lines...) Expand all Loading... |
| 5182 ASSERT_EQ(1, length); | 5220 ASSERT_EQ(1, length); |
| 5183 block_end = range[0]; | 5221 block_end = range[0]; |
| 5184 } | 5222 } |
| 5185 int end = (block_end > top) ? top : block_end; | 5223 int end = (block_end > top) ? top : block_end; |
| 5186 length = isolate->jsregexp_uncanonicalize()->get(block_end, '\0', range); | 5224 length = isolate->jsregexp_uncanonicalize()->get(block_end, '\0', range); |
| 5187 for (int i = 0; i < length; i++) { | 5225 for (int i = 0; i < length; i++) { |
| 5188 uc32 c = range[i]; | 5226 uc32 c = range[i]; |
| 5189 uc16 range_from = c - (block_end - pos); | 5227 uc16 range_from = c - (block_end - pos); |
| 5190 uc16 range_to = c - (block_end - end); | 5228 uc16 range_to = c - (block_end - end); |
| 5191 if (!(bottom <= range_from && range_to <= top)) { | 5229 if (!(bottom <= range_from && range_to <= top)) { |
| 5192 ranges->Add(CharacterRange(range_from, range_to)); | 5230 ranges->Add(CharacterRange(range_from, range_to), zone); |
| 5193 } | 5231 } |
| 5194 } | 5232 } |
| 5195 pos = end + 1; | 5233 pos = end + 1; |
| 5196 } | 5234 } |
| 5197 } | 5235 } |
| 5198 } | 5236 } |
| 5199 | 5237 |
| 5200 | 5238 |
| 5201 bool CharacterRange::IsCanonical(ZoneList<CharacterRange>* ranges) { | 5239 bool CharacterRange::IsCanonical(ZoneList<CharacterRange>* ranges) { |
| 5202 ASSERT_NOT_NULL(ranges); | 5240 ASSERT_NOT_NULL(ranges); |
| 5203 int n = ranges->length(); | 5241 int n = ranges->length(); |
| 5204 if (n <= 1) return true; | 5242 if (n <= 1) return true; |
| 5205 int max = ranges->at(0).to(); | 5243 int max = ranges->at(0).to(); |
| 5206 for (int i = 1; i < n; i++) { | 5244 for (int i = 1; i < n; i++) { |
| 5207 CharacterRange next_range = ranges->at(i); | 5245 CharacterRange next_range = ranges->at(i); |
| 5208 if (next_range.from() <= max + 1) return false; | 5246 if (next_range.from() <= max + 1) return false; |
| 5209 max = next_range.to(); | 5247 max = next_range.to(); |
| 5210 } | 5248 } |
| 5211 return true; | 5249 return true; |
| 5212 } | 5250 } |
| 5213 | 5251 |
| 5214 | 5252 |
| 5215 ZoneList<CharacterRange>* CharacterSet::ranges() { | 5253 ZoneList<CharacterRange>* CharacterSet::ranges(Zone* zone) { |
| 5216 if (ranges_ == NULL) { | 5254 if (ranges_ == NULL) { |
| 5217 ranges_ = new ZoneList<CharacterRange>(2); | 5255 ranges_ = new(zone) ZoneList<CharacterRange>(2, zone); |
| 5218 CharacterRange::AddClassEscape(standard_set_type_, ranges_); | 5256 CharacterRange::AddClassEscape(standard_set_type_, ranges_, zone); |
| 5219 } | 5257 } |
| 5220 return ranges_; | 5258 return ranges_; |
| 5221 } | 5259 } |
| 5222 | 5260 |
| 5223 | 5261 |
| 5224 // Move a number of elements in a zonelist to another position | 5262 // Move a number of elements in a zonelist to another position |
| 5225 // in the same list. Handles overlapping source and target areas. | 5263 // in the same list. Handles overlapping source and target areas. |
| 5226 static void MoveRanges(ZoneList<CharacterRange>* list, | 5264 static void MoveRanges(ZoneList<CharacterRange>* list, |
| 5227 int from, | 5265 int from, |
| 5228 int to, | 5266 int to, |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5337 character_ranges->at(read)); | 5375 character_ranges->at(read)); |
| 5338 read++; | 5376 read++; |
| 5339 } while (read < n); | 5377 } while (read < n); |
| 5340 character_ranges->Rewind(num_canonical); | 5378 character_ranges->Rewind(num_canonical); |
| 5341 | 5379 |
| 5342 ASSERT(CharacterRange::IsCanonical(character_ranges)); | 5380 ASSERT(CharacterRange::IsCanonical(character_ranges)); |
| 5343 } | 5381 } |
| 5344 | 5382 |
| 5345 | 5383 |
| 5346 void CharacterRange::Negate(ZoneList<CharacterRange>* ranges, | 5384 void CharacterRange::Negate(ZoneList<CharacterRange>* ranges, |
| 5347 ZoneList<CharacterRange>* negated_ranges) { | 5385 ZoneList<CharacterRange>* negated_ranges, |
| 5386 Zone* zone) { |
| 5348 ASSERT(CharacterRange::IsCanonical(ranges)); | 5387 ASSERT(CharacterRange::IsCanonical(ranges)); |
| 5349 ASSERT_EQ(0, negated_ranges->length()); | 5388 ASSERT_EQ(0, negated_ranges->length()); |
| 5350 int range_count = ranges->length(); | 5389 int range_count = ranges->length(); |
| 5351 uc16 from = 0; | 5390 uc16 from = 0; |
| 5352 int i = 0; | 5391 int i = 0; |
| 5353 if (range_count > 0 && ranges->at(0).from() == 0) { | 5392 if (range_count > 0 && ranges->at(0).from() == 0) { |
| 5354 from = ranges->at(0).to(); | 5393 from = ranges->at(0).to(); |
| 5355 i = 1; | 5394 i = 1; |
| 5356 } | 5395 } |
| 5357 while (i < range_count) { | 5396 while (i < range_count) { |
| 5358 CharacterRange range = ranges->at(i); | 5397 CharacterRange range = ranges->at(i); |
| 5359 negated_ranges->Add(CharacterRange(from + 1, range.from() - 1)); | 5398 negated_ranges->Add(CharacterRange(from + 1, range.from() - 1), zone); |
| 5360 from = range.to(); | 5399 from = range.to(); |
| 5361 i++; | 5400 i++; |
| 5362 } | 5401 } |
| 5363 if (from < String::kMaxUtf16CodeUnit) { | 5402 if (from < String::kMaxUtf16CodeUnit) { |
| 5364 negated_ranges->Add(CharacterRange(from + 1, String::kMaxUtf16CodeUnit)); | 5403 negated_ranges->Add(CharacterRange(from + 1, String::kMaxUtf16CodeUnit), |
| 5404 zone); |
| 5365 } | 5405 } |
| 5366 } | 5406 } |
| 5367 | 5407 |
| 5368 | 5408 |
| 5369 // ------------------------------------------------------------------- | 5409 // ------------------------------------------------------------------- |
| 5370 // Splay tree | 5410 // Splay tree |
| 5371 | 5411 |
| 5372 | 5412 |
| 5373 OutSet* OutSet::Extend(unsigned value) { | 5413 OutSet* OutSet::Extend(unsigned value, Zone* zone) { |
| 5374 if (Get(value)) | 5414 if (Get(value)) |
| 5375 return this; | 5415 return this; |
| 5376 if (successors() != NULL) { | 5416 if (successors(zone) != NULL) { |
| 5377 for (int i = 0; i < successors()->length(); i++) { | 5417 for (int i = 0; i < successors(zone)->length(); i++) { |
| 5378 OutSet* successor = successors()->at(i); | 5418 OutSet* successor = successors(zone)->at(i); |
| 5379 if (successor->Get(value)) | 5419 if (successor->Get(value)) |
| 5380 return successor; | 5420 return successor; |
| 5381 } | 5421 } |
| 5382 } else { | 5422 } else { |
| 5383 successors_ = new ZoneList<OutSet*>(2); | 5423 successors_ = new(zone) ZoneList<OutSet*>(2, zone); |
| 5384 } | 5424 } |
| 5385 OutSet* result = new OutSet(first_, remaining_); | 5425 OutSet* result = new(zone) OutSet(first_, remaining_); |
| 5386 result->Set(value); | 5426 result->Set(value, zone); |
| 5387 successors()->Add(result); | 5427 successors(zone)->Add(result, zone); |
| 5388 return result; | 5428 return result; |
| 5389 } | 5429 } |
| 5390 | 5430 |
| 5391 | 5431 |
| 5392 void OutSet::Set(unsigned value) { | 5432 void OutSet::Set(unsigned value, Zone *zone) { |
| 5393 if (value < kFirstLimit) { | 5433 if (value < kFirstLimit) { |
| 5394 first_ |= (1 << value); | 5434 first_ |= (1 << value); |
| 5395 } else { | 5435 } else { |
| 5396 if (remaining_ == NULL) | 5436 if (remaining_ == NULL) |
| 5397 remaining_ = new ZoneList<unsigned>(1); | 5437 remaining_ = new(zone) ZoneList<unsigned>(1, zone); |
| 5398 if (remaining_->is_empty() || !remaining_->Contains(value)) | 5438 if (remaining_->is_empty() || !remaining_->Contains(value)) |
| 5399 remaining_->Add(value); | 5439 remaining_->Add(value, zone); |
| 5400 } | 5440 } |
| 5401 } | 5441 } |
| 5402 | 5442 |
| 5403 | 5443 |
| 5404 bool OutSet::Get(unsigned value) { | 5444 bool OutSet::Get(unsigned value) { |
| 5405 if (value < kFirstLimit) { | 5445 if (value < kFirstLimit) { |
| 5406 return (first_ & (1 << value)) != 0; | 5446 return (first_ & (1 << value)) != 0; |
| 5407 } else if (remaining_ == NULL) { | 5447 } else if (remaining_ == NULL) { |
| 5408 return false; | 5448 return false; |
| 5409 } else { | 5449 } else { |
| 5410 return remaining_->Contains(value); | 5450 return remaining_->Contains(value); |
| 5411 } | 5451 } |
| 5412 } | 5452 } |
| 5413 | 5453 |
| 5414 | 5454 |
| 5415 const uc16 DispatchTable::Config::kNoKey = unibrow::Utf8::kBadChar; | 5455 const uc16 DispatchTable::Config::kNoKey = unibrow::Utf8::kBadChar; |
| 5416 | 5456 |
| 5417 | 5457 |
| 5418 void DispatchTable::AddRange(CharacterRange full_range, int value) { | 5458 void DispatchTable::AddRange(CharacterRange full_range, int value, |
| 5459 Zone* zone) { |
| 5419 CharacterRange current = full_range; | 5460 CharacterRange current = full_range; |
| 5461 ZoneAllocationPolicy allocator(zone); |
| 5420 if (tree()->is_empty()) { | 5462 if (tree()->is_empty()) { |
| 5421 // If this is the first range we just insert into the table. | 5463 // If this is the first range we just insert into the table. |
| 5422 ZoneSplayTree<Config>::Locator loc; | 5464 ZoneSplayTree<Config>::Locator loc; |
| 5423 ASSERT_RESULT(tree()->Insert(current.from(), &loc)); | 5465 ASSERT_RESULT(tree()->Insert(current.from(), &loc, allocator)); |
| 5424 loc.set_value(Entry(current.from(), current.to(), empty()->Extend(value))); | 5466 loc.set_value(Entry(current.from(), current.to(), |
| 5467 empty()->Extend(value, zone))); |
| 5425 return; | 5468 return; |
| 5426 } | 5469 } |
| 5427 // First see if there is a range to the left of this one that | 5470 // First see if there is a range to the left of this one that |
| 5428 // overlaps. | 5471 // overlaps. |
| 5429 ZoneSplayTree<Config>::Locator loc; | 5472 ZoneSplayTree<Config>::Locator loc; |
| 5430 if (tree()->FindGreatestLessThan(current.from(), &loc)) { | 5473 if (tree()->FindGreatestLessThan(current.from(), &loc)) { |
| 5431 Entry* entry = &loc.value(); | 5474 Entry* entry = &loc.value(); |
| 5432 // If we've found a range that overlaps with this one, and it | 5475 // 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 | 5476 // starts strictly to the left of this one, we have to fix it |
| 5434 // because the following code only handles ranges that start on | 5477 // because the following code only handles ranges that start on |
| 5435 // or after the start point of the range we're adding. | 5478 // or after the start point of the range we're adding. |
| 5436 if (entry->from() < current.from() && entry->to() >= current.from()) { | 5479 if (entry->from() < current.from() && entry->to() >= current.from()) { |
| 5437 // Snap the overlapping range in half around the start point of | 5480 // Snap the overlapping range in half around the start point of |
| 5438 // the range we're adding. | 5481 // the range we're adding. |
| 5439 CharacterRange left(entry->from(), current.from() - 1); | 5482 CharacterRange left(entry->from(), current.from() - 1); |
| 5440 CharacterRange right(current.from(), entry->to()); | 5483 CharacterRange right(current.from(), entry->to()); |
| 5441 // The left part of the overlapping range doesn't overlap. | 5484 // The left part of the overlapping range doesn't overlap. |
| 5442 // Truncate the whole entry to be just the left part. | 5485 // Truncate the whole entry to be just the left part. |
| 5443 entry->set_to(left.to()); | 5486 entry->set_to(left.to()); |
| 5444 // The right part is the one that overlaps. We add this part | 5487 // The right part is the one that overlaps. We add this part |
| 5445 // to the map and let the next step deal with merging it with | 5488 // to the map and let the next step deal with merging it with |
| 5446 // the range we're adding. | 5489 // the range we're adding. |
| 5447 ZoneSplayTree<Config>::Locator loc; | 5490 ZoneSplayTree<Config>::Locator loc; |
| 5448 ASSERT_RESULT(tree()->Insert(right.from(), &loc)); | 5491 ASSERT_RESULT(tree()->Insert(right.from(), &loc, allocator)); |
| 5449 loc.set_value(Entry(right.from(), | 5492 loc.set_value(Entry(right.from(), |
| 5450 right.to(), | 5493 right.to(), |
| 5451 entry->out_set())); | 5494 entry->out_set())); |
| 5452 } | 5495 } |
| 5453 } | 5496 } |
| 5454 while (current.is_valid()) { | 5497 while (current.is_valid()) { |
| 5455 if (tree()->FindLeastGreaterThan(current.from(), &loc) && | 5498 if (tree()->FindLeastGreaterThan(current.from(), &loc) && |
| 5456 (loc.value().from() <= current.to()) && | 5499 (loc.value().from() <= current.to()) && |
| 5457 (loc.value().to() >= current.from())) { | 5500 (loc.value().to() >= current.from())) { |
| 5458 Entry* entry = &loc.value(); | 5501 Entry* entry = &loc.value(); |
| 5459 // We have overlap. If there is space between the start point of | 5502 // We have overlap. If there is space between the start point of |
| 5460 // the range we're adding and where the overlapping range starts | 5503 // the range we're adding and where the overlapping range starts |
| 5461 // then we have to add a range covering just that space. | 5504 // then we have to add a range covering just that space. |
| 5462 if (current.from() < entry->from()) { | 5505 if (current.from() < entry->from()) { |
| 5463 ZoneSplayTree<Config>::Locator ins; | 5506 ZoneSplayTree<Config>::Locator ins; |
| 5464 ASSERT_RESULT(tree()->Insert(current.from(), &ins)); | 5507 ASSERT_RESULT(tree()->Insert(current.from(), &ins, allocator)); |
| 5465 ins.set_value(Entry(current.from(), | 5508 ins.set_value(Entry(current.from(), |
| 5466 entry->from() - 1, | 5509 entry->from() - 1, |
| 5467 empty()->Extend(value))); | 5510 empty()->Extend(value, zone))); |
| 5468 current.set_from(entry->from()); | 5511 current.set_from(entry->from()); |
| 5469 } | 5512 } |
| 5470 ASSERT_EQ(current.from(), entry->from()); | 5513 ASSERT_EQ(current.from(), entry->from()); |
| 5471 // If the overlapping range extends beyond the one we want to add | 5514 // 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. | 5515 // we have to snap the right part off and add it separately. |
| 5473 if (entry->to() > current.to()) { | 5516 if (entry->to() > current.to()) { |
| 5474 ZoneSplayTree<Config>::Locator ins; | 5517 ZoneSplayTree<Config>::Locator ins; |
| 5475 ASSERT_RESULT(tree()->Insert(current.to() + 1, &ins)); | 5518 ASSERT_RESULT(tree()->Insert(current.to() + 1, &ins, allocator)); |
| 5476 ins.set_value(Entry(current.to() + 1, | 5519 ins.set_value(Entry(current.to() + 1, |
| 5477 entry->to(), | 5520 entry->to(), |
| 5478 entry->out_set())); | 5521 entry->out_set())); |
| 5479 entry->set_to(current.to()); | 5522 entry->set_to(current.to()); |
| 5480 } | 5523 } |
| 5481 ASSERT(entry->to() <= current.to()); | 5524 ASSERT(entry->to() <= current.to()); |
| 5482 // The overlapping range is now completely contained by the range | 5525 // 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 | 5526 // we're adding so we can just update it and move the start point |
| 5484 // of the range we're adding just past it. | 5527 // of the range we're adding just past it. |
| 5485 entry->AddValue(value); | 5528 entry->AddValue(value, zone); |
| 5486 // Bail out if the last interval ended at 0xFFFF since otherwise | 5529 // Bail out if the last interval ended at 0xFFFF since otherwise |
| 5487 // adding 1 will wrap around to 0. | 5530 // adding 1 will wrap around to 0. |
| 5488 if (entry->to() == String::kMaxUtf16CodeUnit) | 5531 if (entry->to() == String::kMaxUtf16CodeUnit) |
| 5489 break; | 5532 break; |
| 5490 ASSERT(entry->to() + 1 > current.from()); | 5533 ASSERT(entry->to() + 1 > current.from()); |
| 5491 current.set_from(entry->to() + 1); | 5534 current.set_from(entry->to() + 1); |
| 5492 } else { | 5535 } else { |
| 5493 // There is no overlap so we can just add the range | 5536 // There is no overlap so we can just add the range |
| 5494 ZoneSplayTree<Config>::Locator ins; | 5537 ZoneSplayTree<Config>::Locator ins; |
| 5495 ASSERT_RESULT(tree()->Insert(current.from(), &ins)); | 5538 ASSERT_RESULT(tree()->Insert(current.from(), &ins, allocator)); |
| 5496 ins.set_value(Entry(current.from(), | 5539 ins.set_value(Entry(current.from(), |
| 5497 current.to(), | 5540 current.to(), |
| 5498 empty()->Extend(value))); | 5541 empty()->Extend(value, zone))); |
| 5499 break; | 5542 break; |
| 5500 } | 5543 } |
| 5501 } | 5544 } |
| 5502 } | 5545 } |
| 5503 | 5546 |
| 5504 | 5547 |
| 5505 OutSet* DispatchTable::Get(uc16 value) { | 5548 OutSet* DispatchTable::Get(uc16 value) { |
| 5506 ZoneSplayTree<Config>::Locator loc; | 5549 ZoneSplayTree<Config>::Locator loc; |
| 5507 if (!tree()->FindGreatestLessThan(value, &loc)) | 5550 if (!tree()->FindGreatestLessThan(value, &loc)) |
| 5508 return empty(); | 5551 return empty(); |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5688 for (int j = 0; j < length; j++) { | 5731 for (int j = 0; j < length; j++) { |
| 5689 bm->Set(offset, chars[j]); | 5732 bm->Set(offset, chars[j]); |
| 5690 } | 5733 } |
| 5691 } else { | 5734 } else { |
| 5692 if (character <= max_char) bm->Set(offset, character); | 5735 if (character <= max_char) bm->Set(offset, character); |
| 5693 } | 5736 } |
| 5694 } | 5737 } |
| 5695 } else { | 5738 } else { |
| 5696 ASSERT(text.type == TextElement::CHAR_CLASS); | 5739 ASSERT(text.type == TextElement::CHAR_CLASS); |
| 5697 RegExpCharacterClass* char_class = text.data.u_char_class; | 5740 RegExpCharacterClass* char_class = text.data.u_char_class; |
| 5698 ZoneList<CharacterRange>* ranges = char_class->ranges(); | 5741 ZoneList<CharacterRange>* ranges = char_class->ranges(zone()); |
| 5699 if (char_class->is_negated()) { | 5742 if (char_class->is_negated()) { |
| 5700 bm->SetAll(offset); | 5743 bm->SetAll(offset); |
| 5701 } else { | 5744 } else { |
| 5702 for (int k = 0; k < ranges->length(); k++) { | 5745 for (int k = 0; k < ranges->length(); k++) { |
| 5703 CharacterRange& range = ranges->at(k); | 5746 CharacterRange& range = ranges->at(k); |
| 5704 if (range.from() > max_char) continue; | 5747 if (range.from() > max_char) continue; |
| 5705 int to = Min(max_char, static_cast<int>(range.to())); | 5748 int to = Min(max_char, static_cast<int>(range.to())); |
| 5706 bm->SetInterval(offset, Interval(range.from(), to)); | 5749 bm->SetInterval(offset, Interval(range.from(), to)); |
| 5707 } | 5750 } |
| 5708 } | 5751 } |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5756 CharacterRange range(from, entry.to()); | 5799 CharacterRange range(from, entry.to()); |
| 5757 constructor_->AddRange(range); | 5800 constructor_->AddRange(range); |
| 5758 } | 5801 } |
| 5759 | 5802 |
| 5760 | 5803 |
| 5761 void DispatchTableConstructor::VisitChoice(ChoiceNode* node) { | 5804 void DispatchTableConstructor::VisitChoice(ChoiceNode* node) { |
| 5762 if (node->being_calculated()) | 5805 if (node->being_calculated()) |
| 5763 return; | 5806 return; |
| 5764 DispatchTable* table = node->GetTable(ignore_case_); | 5807 DispatchTable* table = node->GetTable(ignore_case_); |
| 5765 AddDispatchRange adder(this); | 5808 AddDispatchRange adder(this); |
| 5766 table->ForEach(&adder); | 5809 table->ForEach(&adder, node->zone()); |
| 5767 } | 5810 } |
| 5768 | 5811 |
| 5769 | 5812 |
| 5770 void DispatchTableConstructor::VisitBackReference(BackReferenceNode* that) { | 5813 void DispatchTableConstructor::VisitBackReference(BackReferenceNode* that) { |
| 5771 // TODO(160): Find the node that we refer back to and propagate its start | 5814 // TODO(160): Find the node that we refer back to and propagate its start |
| 5772 // set back to here. For now we just accept anything. | 5815 // set back to here. For now we just accept anything. |
| 5773 AddRange(CharacterRange::Everything()); | 5816 AddRange(CharacterRange::Everything()); |
| 5774 } | 5817 } |
| 5775 | 5818 |
| 5776 | 5819 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5808 void DispatchTableConstructor::VisitText(TextNode* that) { | 5851 void DispatchTableConstructor::VisitText(TextNode* that) { |
| 5809 TextElement elm = that->elements()->at(0); | 5852 TextElement elm = that->elements()->at(0); |
| 5810 switch (elm.type) { | 5853 switch (elm.type) { |
| 5811 case TextElement::ATOM: { | 5854 case TextElement::ATOM: { |
| 5812 uc16 c = elm.data.u_atom->data()[0]; | 5855 uc16 c = elm.data.u_atom->data()[0]; |
| 5813 AddRange(CharacterRange(c, c)); | 5856 AddRange(CharacterRange(c, c)); |
| 5814 break; | 5857 break; |
| 5815 } | 5858 } |
| 5816 case TextElement::CHAR_CLASS: { | 5859 case TextElement::CHAR_CLASS: { |
| 5817 RegExpCharacterClass* tree = elm.data.u_char_class; | 5860 RegExpCharacterClass* tree = elm.data.u_char_class; |
| 5818 ZoneList<CharacterRange>* ranges = tree->ranges(); | 5861 ZoneList<CharacterRange>* ranges = tree->ranges(that->zone()); |
| 5819 if (tree->is_negated()) { | 5862 if (tree->is_negated()) { |
| 5820 AddInverse(ranges); | 5863 AddInverse(ranges); |
| 5821 } else { | 5864 } else { |
| 5822 for (int i = 0; i < ranges->length(); i++) | 5865 for (int i = 0; i < ranges->length(); i++) |
| 5823 AddRange(ranges->at(i)); | 5866 AddRange(ranges->at(i)); |
| 5824 } | 5867 } |
| 5825 break; | 5868 break; |
| 5826 } | 5869 } |
| 5827 default: { | 5870 default: { |
| 5828 UNIMPLEMENTED(); | 5871 UNIMPLEMENTED(); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5872 bool is_end_anchored = data->tree->IsAnchoredAtEnd(); | 5915 bool is_end_anchored = data->tree->IsAnchoredAtEnd(); |
| 5873 bool is_start_anchored = data->tree->IsAnchoredAtStart(); | 5916 bool is_start_anchored = data->tree->IsAnchoredAtStart(); |
| 5874 int max_length = data->tree->max_match(); | 5917 int max_length = data->tree->max_match(); |
| 5875 if (!is_start_anchored) { | 5918 if (!is_start_anchored) { |
| 5876 // Add a .*? at the beginning, outside the body capture, unless | 5919 // Add a .*? at the beginning, outside the body capture, unless |
| 5877 // this expression is anchored at the beginning. | 5920 // this expression is anchored at the beginning. |
| 5878 RegExpNode* loop_node = | 5921 RegExpNode* loop_node = |
| 5879 RegExpQuantifier::ToNode(0, | 5922 RegExpQuantifier::ToNode(0, |
| 5880 RegExpTree::kInfinity, | 5923 RegExpTree::kInfinity, |
| 5881 false, | 5924 false, |
| 5882 new RegExpCharacterClass('*'), | 5925 new(zone) RegExpCharacterClass('*'), |
| 5883 &compiler, | 5926 &compiler, |
| 5884 captured_body, | 5927 captured_body, |
| 5885 data->contains_anchor); | 5928 data->contains_anchor); |
| 5886 | 5929 |
| 5887 if (data->contains_anchor) { | 5930 if (data->contains_anchor) { |
| 5888 // Unroll loop once, to take care of the case that might start | 5931 // Unroll loop once, to take care of the case that might start |
| 5889 // at the start of input. | 5932 // at the start of input. |
| 5890 ChoiceNode* first_step_node = new ChoiceNode(2, zone); | 5933 ChoiceNode* first_step_node = new(zone) ChoiceNode(2, zone); |
| 5891 first_step_node->AddAlternative(GuardedAlternative(captured_body)); | 5934 first_step_node->AddAlternative(GuardedAlternative(captured_body)); |
| 5892 first_step_node->AddAlternative(GuardedAlternative( | 5935 first_step_node->AddAlternative(GuardedAlternative( |
| 5893 new TextNode(new RegExpCharacterClass('*'), loop_node))); | 5936 new(zone) TextNode(new(zone) RegExpCharacterClass('*'), loop_node))); |
| 5894 node = first_step_node; | 5937 node = first_step_node; |
| 5895 } else { | 5938 } else { |
| 5896 node = loop_node; | 5939 node = loop_node; |
| 5897 } | 5940 } |
| 5898 } | 5941 } |
| 5899 if (is_ascii) { | 5942 if (is_ascii) { |
| 5900 node = node->FilterASCII(RegExpCompiler::kMaxRecursion); | 5943 node = node->FilterASCII(RegExpCompiler::kMaxRecursion); |
| 5901 // Do it again to propagate the new nodes to places where they were not | 5944 // Do it again to propagate the new nodes to places where they were not |
| 5902 // put because they had not been calculated yet. | 5945 // put because they had not been calculated yet. |
| 5903 if (node != NULL) node = node->FilterASCII(RegExpCompiler::kMaxRecursion); | 5946 if (node != NULL) node = node->FilterASCII(RegExpCompiler::kMaxRecursion); |
| 5904 } | 5947 } |
| 5905 | 5948 |
| 5906 if (node == NULL) node = new EndNode(EndNode::BACKTRACK, zone); | 5949 if (node == NULL) node = new(zone) EndNode(EndNode::BACKTRACK, zone); |
| 5907 data->node = node; | 5950 data->node = node; |
| 5908 Analysis analysis(ignore_case, is_ascii); | 5951 Analysis analysis(ignore_case, is_ascii); |
| 5909 analysis.EnsureAnalyzed(node); | 5952 analysis.EnsureAnalyzed(node); |
| 5910 if (analysis.has_failed()) { | 5953 if (analysis.has_failed()) { |
| 5911 const char* error_message = analysis.error_message(); | 5954 const char* error_message = analysis.error_message(); |
| 5912 return CompilationResult(error_message); | 5955 return CompilationResult(error_message); |
| 5913 } | 5956 } |
| 5914 | 5957 |
| 5915 // Create the correct assembler for the architecture. | 5958 // Create the correct assembler for the architecture. |
| 5916 #ifndef V8_INTERPRETED_REGEXP | 5959 #ifndef V8_INTERPRETED_REGEXP |
| 5917 // Native regexp implementation. | 5960 // Native regexp implementation. |
| 5918 | 5961 |
| 5919 NativeRegExpMacroAssembler::Mode mode = | 5962 NativeRegExpMacroAssembler::Mode mode = |
| 5920 is_ascii ? NativeRegExpMacroAssembler::ASCII | 5963 is_ascii ? NativeRegExpMacroAssembler::ASCII |
| 5921 : NativeRegExpMacroAssembler::UC16; | 5964 : NativeRegExpMacroAssembler::UC16; |
| 5922 | 5965 |
| 5923 #if V8_TARGET_ARCH_IA32 | 5966 #if V8_TARGET_ARCH_IA32 |
| 5924 RegExpMacroAssemblerIA32 macro_assembler(mode, (data->capture_count + 1) * 2); | 5967 RegExpMacroAssemblerIA32 macro_assembler(mode, (data->capture_count + 1) * 2, |
| 5968 zone); |
| 5925 #elif V8_TARGET_ARCH_X64 | 5969 #elif V8_TARGET_ARCH_X64 |
| 5926 RegExpMacroAssemblerX64 macro_assembler(mode, (data->capture_count + 1) * 2); | 5970 RegExpMacroAssemblerX64 macro_assembler(mode, (data->capture_count + 1) * 2, |
| 5971 zone); |
| 5927 #elif V8_TARGET_ARCH_ARM | 5972 #elif V8_TARGET_ARCH_ARM |
| 5928 RegExpMacroAssemblerARM macro_assembler(mode, (data->capture_count + 1) * 2); | 5973 RegExpMacroAssemblerARM macro_assembler(mode, (data->capture_count + 1) * 2, |
| 5974 zone); |
| 5929 #elif V8_TARGET_ARCH_MIPS | 5975 #elif V8_TARGET_ARCH_MIPS |
| 5930 RegExpMacroAssemblerMIPS macro_assembler(mode, (data->capture_count + 1) * 2); | 5976 RegExpMacroAssemblerMIPS macro_assembler(mode, (data->capture_count + 1) * 2); |
| 5931 #endif | 5977 #endif |
| 5932 | 5978 |
| 5933 #else // V8_INTERPRETED_REGEXP | 5979 #else // V8_INTERPRETED_REGEXP |
| 5934 // Interpreted regexp implementation. | 5980 // Interpreted regexp implementation. |
| 5935 EmbeddedVector<byte, 1024> codes; | 5981 EmbeddedVector<byte, 1024> codes; |
| 5936 RegExpMacroAssemblerIrregexp macro_assembler(codes); | 5982 RegExpMacroAssemblerIrregexp macro_assembler(codes); |
| 5937 #endif // V8_INTERPRETED_REGEXP | 5983 #endif // V8_INTERPRETED_REGEXP |
| 5938 | 5984 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 5953 } | 5999 } |
| 5954 | 6000 |
| 5955 return compiler.Assemble(¯o_assembler, | 6001 return compiler.Assemble(¯o_assembler, |
| 5956 node, | 6002 node, |
| 5957 data->capture_count, | 6003 data->capture_count, |
| 5958 pattern); | 6004 pattern); |
| 5959 } | 6005 } |
| 5960 | 6006 |
| 5961 | 6007 |
| 5962 }} // namespace v8::internal | 6008 }} // namespace v8::internal |
| OLD | NEW |