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

Side by Side Diff: src/jsregexp.cc

Issue 17416: * Move irregexp backtrack stack to external memory area, instead of the system stack. (Closed)
Patch Set: Added explicit stack check requests to push operations. Created 11 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
4474 EmbeddedVector<byte, 1024> codes; 4486 EmbeddedVector<byte, 1024> codes;
4475 RegExpMacroAssemblerIrregexp macro_assembler(codes); 4487 RegExpMacroAssemblerIrregexp macro_assembler(codes);
4476 return compiler.Assemble(&macro_assembler, 4488 return compiler.Assemble(&macro_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
OLDNEW
« no previous file with comments | « src/assembler.cc ('k') | src/regexp-macro-assembler.h » ('j') | src/regexp-macro-assembler.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698