Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 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 22 matching lines...) Expand all Loading... | |
| 33 #include "jsregexp-inl.h" | 33 #include "jsregexp-inl.h" |
| 34 #include "platform.h" | 34 #include "platform.h" |
| 35 #include "runtime.h" | 35 #include "runtime.h" |
| 36 #include "top.h" | 36 #include "top.h" |
| 37 #include "compilation-cache.h" | 37 #include "compilation-cache.h" |
| 38 #include "string-stream.h" | 38 #include "string-stream.h" |
| 39 #include "parser.h" | 39 #include "parser.h" |
| 40 #include "regexp-macro-assembler.h" | 40 #include "regexp-macro-assembler.h" |
| 41 #include "regexp-macro-assembler-tracer.h" | 41 #include "regexp-macro-assembler-tracer.h" |
| 42 #include "regexp-macro-assembler-irregexp.h" | 42 #include "regexp-macro-assembler-irregexp.h" |
| 43 #include "regexp-stack.h" | |
| 43 | 44 |
| 44 #ifdef ARM | 45 #ifdef ARM |
| 45 #include "regexp-macro-assembler-arm.h" | 46 #include "regexp-macro-assembler-arm.h" |
| 46 #else // IA32 | 47 #else // IA32 |
| 47 #include "macro-assembler-ia32.h" | 48 #include "macro-assembler-ia32.h" |
| 48 #include "regexp-macro-assembler-ia32.h" | 49 #include "regexp-macro-assembler-ia32.h" |
| 49 #endif | 50 #endif |
| 50 | 51 |
| 51 #include "interpreter-irregexp.h" | 52 #include "interpreter-irregexp.h" |
| 52 | 53 |
| (...skipping 853 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 906 const byte* address; | 907 const byte* address; |
| 907 if (is_ascii) { | 908 if (is_ascii) { |
| 908 ExternalAsciiString* ext = ExternalAsciiString::cast(*subject); | 909 ExternalAsciiString* ext = ExternalAsciiString::cast(*subject); |
| 909 address = reinterpret_cast<const byte*>(ext->resource()->data()); | 910 address = reinterpret_cast<const byte*>(ext->resource()->data()); |
| 910 } else { | 911 } else { |
| 911 ExternalTwoByteString* ext = ExternalTwoByteString::cast(*subject); | 912 ExternalTwoByteString* ext = ExternalTwoByteString::cast(*subject); |
| 912 address = reinterpret_cast<const byte*>(ext->resource()->data()); | 913 address = reinterpret_cast<const byte*>(ext->resource()->data()); |
| 913 } | 914 } |
| 914 res = RegExpMacroAssemblerIA32::Execute( | 915 res = RegExpMacroAssemblerIA32::Execute( |
| 915 *code, | 916 *code, |
| 916 &address, | 917 const_cast<Address*>(&address), |
| 917 start_offset << char_size_shift, | 918 start_offset << char_size_shift, |
| 918 end_offset << char_size_shift, | 919 end_offset << char_size_shift, |
| 919 offsets_vector, | 920 offsets_vector, |
| 920 previous_index == 0); | 921 previous_index == 0); |
| 921 } else { // Sequential string | 922 } else { // Sequential string |
| 922 Address char_address = | 923 Address char_address = |
| 923 is_ascii ? SeqAsciiString::cast(*subject)->GetCharsAddress() | 924 is_ascii ? SeqAsciiString::cast(*subject)->GetCharsAddress() |
| 924 : SeqTwoByteString::cast(*subject)->GetCharsAddress(); | 925 : SeqTwoByteString::cast(*subject)->GetCharsAddress(); |
| 925 int byte_offset = char_address - reinterpret_cast<Address>(*subject); | 926 int byte_offset = char_address - reinterpret_cast<Address>(*subject); |
| 926 res = RegExpMacroAssemblerIA32::Execute( | 927 res = RegExpMacroAssemblerIA32::Execute( |
| 927 *code, | 928 *code, |
| 928 subject.location(), | 929 reinterpret_cast<Address*>(subject.location()), |
| 929 byte_offset + (start_offset << char_size_shift), | 930 byte_offset + (start_offset << char_size_shift), |
| 930 byte_offset + (end_offset << char_size_shift), | 931 byte_offset + (end_offset << char_size_shift), |
| 931 offsets_vector, | 932 offsets_vector, |
| 932 previous_index == 0); | 933 previous_index == 0); |
| 933 } | 934 } |
| 934 | 935 |
| 935 if (res == RegExpMacroAssemblerIA32::EXCEPTION) { | 936 if (res == RegExpMacroAssemblerIA32::EXCEPTION) { |
| 936 ASSERT(Top::has_pending_exception()); | 937 ASSERT(Top::has_pending_exception()); |
| 937 return Handle<Object>::null(); | 938 return Handle<Object>::null(); |
| 938 } | 939 } |
| (...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1264 Handle<String> pattern) { | 1265 Handle<String> pattern) { |
| 1265 #ifdef DEBUG | 1266 #ifdef DEBUG |
| 1266 if (FLAG_trace_regexp_assembler) | 1267 if (FLAG_trace_regexp_assembler) |
| 1267 macro_assembler_ = new RegExpMacroAssemblerTracer(macro_assembler); | 1268 macro_assembler_ = new RegExpMacroAssemblerTracer(macro_assembler); |
| 1268 else | 1269 else |
| 1269 #endif | 1270 #endif |
| 1270 macro_assembler_ = macro_assembler; | 1271 macro_assembler_ = macro_assembler; |
| 1271 List <RegExpNode*> work_list(0); | 1272 List <RegExpNode*> work_list(0); |
| 1272 work_list_ = &work_list; | 1273 work_list_ = &work_list; |
| 1273 Label fail; | 1274 Label fail; |
| 1274 macro_assembler->PushBacktrack(&fail); | 1275 macro_assembler->PushBacktrack(&fail, |
| 1276 RegExpMacroAssembler::kNoStackLimitCheck); | |
| 1275 GenerationVariant generic_variant; | 1277 GenerationVariant generic_variant; |
| 1276 if (!start->Emit(this, &generic_variant)) { | 1278 if (!start->Emit(this, &generic_variant)) { |
| 1277 fail.Unuse(); | 1279 fail.Unuse(); |
| 1278 return Handle<FixedArray>::null(); | 1280 return Handle<FixedArray>::null(); |
| 1279 } | 1281 } |
| 1280 macro_assembler_->Bind(&fail); | 1282 macro_assembler_->Bind(&fail); |
| 1281 macro_assembler_->Fail(); | 1283 macro_assembler_->Fail(); |
| 1282 while (!work_list.is_empty()) { | 1284 while (!work_list.is_empty()) { |
| 1283 if (!work_list.RemoveLast()->Emit(this, &generic_variant)) { | 1285 if (!work_list.RemoveLast()->Emit(this, &generic_variant)) { |
| 1284 return Handle<FixedArray>::null(); | 1286 return Handle<FixedArray>::null(); |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1340 affected_registers->Set(action->reg()); | 1342 affected_registers->Set(action->reg()); |
| 1341 if (action->reg() > max_register) max_register = action->reg(); | 1343 if (action->reg() > max_register) max_register = action->reg(); |
| 1342 } | 1344 } |
| 1343 return max_register; | 1345 return max_register; |
| 1344 } | 1346 } |
| 1345 | 1347 |
| 1346 | 1348 |
| 1347 void GenerationVariant::PushAffectedRegisters(RegExpMacroAssembler* assembler, | 1349 void GenerationVariant::PushAffectedRegisters(RegExpMacroAssembler* assembler, |
| 1348 int max_register, | 1350 int max_register, |
| 1349 OutSet& affected_registers) { | 1351 OutSet& affected_registers) { |
| 1350 for (int reg = 0; reg <= max_register; reg++) { | 1352 // Stay safe and check every half times the limit. |
| 1351 if (affected_registers.Get(reg)) assembler->PushRegister(reg); | 1353 int push_limit = (assembler->stack_limit() + 1) / 2; |
|
Erik Corry
2009/01/12 11:50:13
Why plus 1?
Lasse Reichstein
2009/01/12 13:03:59
Rounding up in case the value is one (which it hap
| |
| 1354 for (int reg = 0, pushes = 0; reg <= max_register; reg++) { | |
| 1355 if (affected_registers.Get(reg)) { | |
| 1356 pushes++; | |
| 1357 RegExpMacroAssembler::StackCheckFlag check_stack_limit = | |
| 1358 (pushes % push_limit) == 0 ? | |
| 1359 RegExpMacroAssembler::kCheckStackLimit : | |
| 1360 RegExpMacroAssembler::kNoStackLimitCheck; | |
| 1361 assembler->PushRegister(reg, check_stack_limit); | |
| 1362 } | |
| 1352 } | 1363 } |
| 1353 } | 1364 } |
| 1354 | 1365 |
| 1355 | 1366 |
| 1356 void GenerationVariant::RestoreAffectedRegisters( | 1367 void GenerationVariant::RestoreAffectedRegisters( |
| 1357 RegExpMacroAssembler* assembler, | 1368 RegExpMacroAssembler* assembler, |
| 1358 int max_register, | 1369 int max_register, |
| 1359 OutSet& affected_registers) { | 1370 OutSet& affected_registers) { |
| 1360 for (int reg = max_register; reg >= 0; reg--) { | 1371 for (int reg = max_register; reg >= 0; reg--) { |
| 1361 if (affected_registers.Get(reg)) assembler->PopRegister(reg); | 1372 if (affected_registers.Get(reg)) assembler->PopRegister(reg); |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1450 | 1461 |
| 1451 // Generate deferred actions here along with code to undo them again. | 1462 // Generate deferred actions here along with code to undo them again. |
| 1452 OutSet affected_registers; | 1463 OutSet affected_registers; |
| 1453 int max_register = FindAffectedRegisters(&affected_registers); | 1464 int max_register = FindAffectedRegisters(&affected_registers); |
| 1454 PushAffectedRegisters(assembler, max_register, affected_registers); | 1465 PushAffectedRegisters(assembler, max_register, affected_registers); |
| 1455 PerformDeferredActions(assembler, max_register, affected_registers); | 1466 PerformDeferredActions(assembler, max_register, affected_registers); |
| 1456 if (backtrack() != NULL) { | 1467 if (backtrack() != NULL) { |
| 1457 // Here we have a concrete backtrack location. These are set up by choice | 1468 // Here we have a concrete backtrack location. These are set up by choice |
| 1458 // nodes and so they indicate that we have a deferred save of the current | 1469 // nodes and so they indicate that we have a deferred save of the current |
| 1459 // position which we may need to emit here. | 1470 // position which we may need to emit here. |
| 1460 assembler->PushCurrentPosition(); | 1471 assembler->PushCurrentPosition(RegExpMacroAssembler::kNoStackLimitCheck); |
|
Erik Corry
2009/01/12 11:50:13
We never emit this with stack limit check so the e
Lasse Reichstein
2009/01/12 13:03:59
What's wrong with needless generality now?!?
Ok, r
| |
| 1461 } | 1472 } |
| 1462 if (cp_offset_ != 0) { | 1473 if (cp_offset_ != 0) { |
| 1463 assembler->AdvanceCurrentPosition(cp_offset_); | 1474 assembler->AdvanceCurrentPosition(cp_offset_); |
| 1464 } | 1475 } |
| 1465 | 1476 |
| 1466 // Create a new trivial state and generate the node with that. | 1477 // Create a new trivial state and generate the node with that. |
| 1467 Label undo; | 1478 Label undo; |
| 1468 assembler->PushBacktrack(&undo); | 1479 assembler->PushBacktrack(&undo, RegExpMacroAssembler::kCheckStackLimit); |
|
Erik Corry
2009/01/12 11:50:13
We should always emit this with stack limit check
Lasse Reichstein
2009/01/12 13:03:59
Removed too
| |
| 1469 GenerationVariant new_state; | 1480 GenerationVariant new_state; |
| 1470 bool ok = successor->Emit(compiler, &new_state); | 1481 bool ok = successor->Emit(compiler, &new_state); |
| 1471 | 1482 |
| 1472 // On backtrack we need to restore state. | 1483 // On backtrack we need to restore state. |
| 1473 assembler->Bind(&undo); | 1484 assembler->Bind(&undo); |
| 1474 if (!ok) return false; | 1485 if (!ok) return false; |
| 1475 if (backtrack() != NULL) { | 1486 if (backtrack() != NULL) { |
| 1476 assembler->PopCurrentPosition(); | 1487 assembler->PopCurrentPosition(); |
| 1477 } | 1488 } |
| 1478 RestoreAffectedRegisters(assembler, max_register, affected_registers); | 1489 RestoreAffectedRegisters(assembler, max_register, affected_registers); |
| (...skipping 1312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2791 if (choice_count > 1 && text_length != kNodeIsTooComplexForGreedyLoops) { | 2802 if (choice_count > 1 && text_length != kNodeIsTooComplexForGreedyLoops) { |
| 2792 // Here we have special handling for greedy loops containing only text nodes | 2803 // Here we have special handling for greedy loops containing only text nodes |
| 2793 // and other simple nodes. These are handled by pushing the current | 2804 // and other simple nodes. These are handled by pushing the current |
| 2794 // position on the stack and then incrementing the current position each | 2805 // position on the stack and then incrementing the current position each |
| 2795 // time around the switch. On backtrack we decrement the current position | 2806 // time around the switch. On backtrack we decrement the current position |
| 2796 // and check it against the pushed value. This avoids pushing backtrack | 2807 // and check it against the pushed value. This avoids pushing backtrack |
| 2797 // information for each iteration of the loop, which could take up a lot of | 2808 // information for each iteration of the loop, which could take up a lot of |
| 2798 // space. | 2809 // space. |
| 2799 greedy_loop = true; | 2810 greedy_loop = true; |
| 2800 ASSERT(variant->stop_node() == NULL); | 2811 ASSERT(variant->stop_node() == NULL); |
| 2801 macro_assembler->PushCurrentPosition(); | 2812 macro_assembler->PushCurrentPosition( |
| 2813 RegExpMacroAssembler::kCheckStackLimit); | |
|
Erik Corry
2009/01/12 11:50:13
We don't need to check here. Greedy loops cannot
Lasse Reichstein
2009/01/12 13:03:59
PushCurrentPosition never checks now.
We shouldn'
| |
| 2802 current_variant = &counter_backtrack_variant; | 2814 current_variant = &counter_backtrack_variant; |
| 2803 Label greedy_match_failed; | 2815 Label greedy_match_failed; |
| 2804 GenerationVariant greedy_match_variant; | 2816 GenerationVariant greedy_match_variant; |
| 2805 greedy_match_variant.set_backtrack(&greedy_match_failed); | 2817 greedy_match_variant.set_backtrack(&greedy_match_failed); |
| 2806 Label loop_label; | 2818 Label loop_label; |
| 2807 macro_assembler->Bind(&loop_label); | 2819 macro_assembler->Bind(&loop_label); |
| 2808 greedy_match_variant.set_stop_node(this); | 2820 greedy_match_variant.set_stop_node(this); |
| 2809 greedy_match_variant.set_loop_label(&loop_label); | 2821 greedy_match_variant.set_loop_label(&loop_label); |
| 2810 bool ok = alternatives_->at(0).node()->Emit(compiler, | 2822 bool ok = alternatives_->at(0).node()->Emit(compiler, |
| 2811 &greedy_match_variant); | 2823 &greedy_match_variant); |
| (...skipping 1662 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4474 EmbeddedVector<byte, 1024> codes; | 4486 EmbeddedVector<byte, 1024> codes; |
| 4475 RegExpMacroAssemblerIrregexp macro_assembler(codes); | 4487 RegExpMacroAssemblerIrregexp macro_assembler(codes); |
| 4476 return compiler.Assemble(¯o_assembler, | 4488 return compiler.Assemble(¯o_assembler, |
| 4477 node, | 4489 node, |
| 4478 data->capture_count, | 4490 data->capture_count, |
| 4479 pattern); | 4491 pattern); |
| 4480 } | 4492 } |
| 4481 | 4493 |
| 4482 | 4494 |
| 4483 }} // namespace v8::internal | 4495 }} // namespace v8::internal |
| OLD | NEW |