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

Side by Side Diff: src/jsregexp.cc

Issue 18096: Experimental: merge from bleeding_edge. Merge up to and including... (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/toiger/
Patch Set: 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 | Annotate | Revision Log
« no previous file with comments | « src/jsregexp.h ('k') | src/log.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
1102 // space. 1103 // space.
1103 // * The current state is virtualized. 1104 // * The current state is virtualized.
1104 // This is used to defer expensive operations until it is clear that they 1105 // This is used to defer expensive operations until it is clear that they
1105 // are needed and to generate code for a node more than once, allowing 1106 // are needed and to generate code for a node more than once, allowing
1106 // specialized an efficient versions of the code to be created. This is 1107 // specialized an efficient versions of the code to be created. This is
1107 // explained in the section below. 1108 // explained in the section below.
1108 // 1109 //
1109 // Execution state virtualization. 1110 // Execution state virtualization.
1110 // 1111 //
1111 // Instead of emitting code, nodes that manipulate the state can record their 1112 // Instead of emitting code, nodes that manipulate the state can record their
1112 // manipulation in an object called the GenerationVariant. The 1113 // manipulation in an object called the Trace. The Trace object can record a
1113 // GenerationVariant object can record a current position offset, an 1114 // current position offset, an optional backtrack code location on the top of
1114 // optional backtrack code location on the top of the virtualized backtrack 1115 // the virtualized backtrack stack and some register changes. When a node is
1115 // stack and some register changes. When a node is to be emitted it can flush 1116 // to be emitted it can flush the Trace or update it. Flushing the Trace
1116 // the GenerationVariant or update it. Flushing the GenerationVariant
1117 // will emit code to bring the actual state into line with the virtual state. 1117 // will emit code to bring the actual state into line with the virtual state.
1118 // Avoiding flushing the state can postpone some work (eg updates of capture 1118 // Avoiding flushing the state can postpone some work (eg updates of capture
1119 // registers). Postponing work can save time when executing the regular 1119 // registers). Postponing work can save time when executing the regular
1120 // expression since it may be found that the work never has to be done as a 1120 // expression since it may be found that the work never has to be done as a
1121 // failure to match can occur. In addition it is much faster to jump to a 1121 // failure to match can occur. In addition it is much faster to jump to a
1122 // known backtrack code location than it is to pop an unknown backtrack 1122 // known backtrack code location than it is to pop an unknown backtrack
1123 // location from the stack and jump there. 1123 // location from the stack and jump there.
1124 // 1124 //
1125 // The virtual state found in the GenerationVariant affects code generation. 1125 // The virtual state found in the Trace affects code generation. For example
1126 // For example the virtual state contains the difference between the actual 1126 // the virtual state contains the difference between the actual current
1127 // current position and the virtual current position, and matching code needs 1127 // position and the virtual current position, and matching code needs to use
1128 // to use this offset to attempt a match in the correct location of the input 1128 // this offset to attempt a match in the correct location of the input
1129 // string. Therefore code generated for a non-trivial GenerationVariant is 1129 // string. Therefore code generated for a non-trivial trace is specialized
1130 // specialized to that GenerationVariant. The code generator therefore 1130 // to that trace. The code generator therefore has the ability to generate
1131 // has the ability to generate code for each node several times. In order to 1131 // code for each node several times. In order to limit the size of the
1132 // limit the size of the generated code there is an arbitrary limit on how 1132 // generated code there is an arbitrary limit on how many specialized sets of
1133 // many specialized sets of code may be generated for a given node. If the 1133 // code may be generated for a given node. If the limit is reached, the
1134 // limit is reached, the GenerationVariant is flushed and a generic version of 1134 // trace is flushed and a generic version of the code for a node is emitted.
1135 // the code for a node is emitted. This is subsequently used for that node. 1135 // This is subsequently used for that node. The code emitted for non-generic
1136 // The code emitted for non-generic GenerationVariants is not recorded in the 1136 // trace is not recorded in the node and so it cannot currently be reused in
1137 // node and so it cannot currently be reused in the event that code generation 1137 // the event that code generation is requested for an identical trace.
1138 // is requested for an identical GenerationVariant.
1139 1138
1140 1139
1141 void RegExpTree::AppendToText(RegExpText* text) { 1140 void RegExpTree::AppendToText(RegExpText* text) {
1142 UNREACHABLE(); 1141 UNREACHABLE();
1143 } 1142 }
1144 1143
1145 1144
1146 void RegExpAtom::AppendToText(RegExpText* text) { 1145 void RegExpAtom::AppendToText(RegExpText* text) {
1147 text->AddElement(TextElement::Atom(this)); 1146 text->AddElement(TextElement::Atom(this));
1148 } 1147 }
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
1215 EndNode* accept() { return accept_; } 1214 EndNode* accept() { return accept_; }
1216 1215
1217 static const int kMaxRecursion = 100; 1216 static const int kMaxRecursion = 100;
1218 inline int recursion_depth() { return recursion_depth_; } 1217 inline int recursion_depth() { return recursion_depth_; }
1219 inline void IncrementRecursionDepth() { recursion_depth_++; } 1218 inline void IncrementRecursionDepth() { recursion_depth_++; }
1220 inline void DecrementRecursionDepth() { recursion_depth_--; } 1219 inline void DecrementRecursionDepth() { recursion_depth_--; }
1221 1220
1222 inline bool ignore_case() { return ignore_case_; } 1221 inline bool ignore_case() { return ignore_case_; }
1223 inline bool ascii() { return ascii_; } 1222 inline bool ascii() { return ascii_; }
1224 1223
1224 static const int kNoRegister = -1;
1225 private: 1225 private:
1226 EndNode* accept_; 1226 EndNode* accept_;
1227 int next_register_; 1227 int next_register_;
1228 List<RegExpNode*>* work_list_; 1228 List<RegExpNode*>* work_list_;
1229 int recursion_depth_; 1229 int recursion_depth_;
1230 RegExpMacroAssembler* macro_assembler_; 1230 RegExpMacroAssembler* macro_assembler_;
1231 bool ignore_case_; 1231 bool ignore_case_;
1232 bool ascii_; 1232 bool ascii_;
1233 }; 1233 };
1234 1234
(...skipping 29 matching lines...) Expand all
1264 #ifdef DEBUG 1264 #ifdef DEBUG
1265 if (FLAG_trace_regexp_assembler) 1265 if (FLAG_trace_regexp_assembler)
1266 macro_assembler_ = new RegExpMacroAssemblerTracer(macro_assembler); 1266 macro_assembler_ = new RegExpMacroAssemblerTracer(macro_assembler);
1267 else 1267 else
1268 #endif 1268 #endif
1269 macro_assembler_ = macro_assembler; 1269 macro_assembler_ = macro_assembler;
1270 List <RegExpNode*> work_list(0); 1270 List <RegExpNode*> work_list(0);
1271 work_list_ = &work_list; 1271 work_list_ = &work_list;
1272 Label fail; 1272 Label fail;
1273 macro_assembler->PushBacktrack(&fail); 1273 macro_assembler->PushBacktrack(&fail);
1274 GenerationVariant generic_variant; 1274 Trace new_trace;
1275 if (!start->Emit(this, &generic_variant)) { 1275 if (!start->Emit(this, &new_trace)) {
1276 fail.Unuse(); 1276 fail.Unuse();
1277 return Handle<FixedArray>::null(); 1277 return Handle<FixedArray>::null();
1278 } 1278 }
1279 macro_assembler_->Bind(&fail); 1279 macro_assembler_->Bind(&fail);
1280 macro_assembler_->Fail(); 1280 macro_assembler_->Fail();
1281 while (!work_list.is_empty()) { 1281 while (!work_list.is_empty()) {
1282 if (!work_list.RemoveLast()->Emit(this, &generic_variant)) { 1282 if (!work_list.RemoveLast()->Emit(this, &new_trace)) {
1283 return Handle<FixedArray>::null(); 1283 return Handle<FixedArray>::null();
1284 } 1284 }
1285 } 1285 }
1286 Handle<FixedArray> array = 1286 Handle<FixedArray> array =
1287 Factory::NewFixedArray(RegExpImpl::kIrregexpDataLength); 1287 Factory::NewFixedArray(RegExpImpl::kIrregexpDataLength);
1288 array->set(RegExpImpl::kIrregexpImplementationIndex, 1288 array->set(RegExpImpl::kIrregexpImplementationIndex,
1289 Smi::FromInt(macro_assembler_->Implementation())); 1289 Smi::FromInt(macro_assembler_->Implementation()));
1290 array->set(RegExpImpl::kIrregexpNumberOfRegistersIndex, 1290 array->set(RegExpImpl::kIrregexpNumberOfRegistersIndex,
1291 Smi::FromInt(next_register_)); 1291 Smi::FromInt(next_register_));
1292 array->set(RegExpImpl::kIrregexpNumberOfCapturesIndex, 1292 array->set(RegExpImpl::kIrregexpNumberOfCapturesIndex,
1293 Smi::FromInt(capture_count)); 1293 Smi::FromInt(capture_count));
1294 Handle<Object> code = macro_assembler_->GetCode(pattern); 1294 Handle<Object> code = macro_assembler_->GetCode(pattern);
1295 array->set(RegExpImpl::kIrregexpCodeIndex, *code); 1295 array->set(RegExpImpl::kIrregexpCodeIndex, *code);
1296 work_list_ = NULL; 1296 work_list_ = NULL;
1297 #ifdef DEBUG 1297 #ifdef DEBUG
1298 if (FLAG_trace_regexp_assembler) { 1298 if (FLAG_trace_regexp_assembler) {
1299 delete macro_assembler_; 1299 delete macro_assembler_;
1300 } 1300 }
1301 #endif 1301 #endif
1302 return array; 1302 return array;
1303 } 1303 }
1304 1304
1305 bool Trace::DeferredAction::Mentions(int that) {
1306 if (type() == ActionNode::CLEAR_CAPTURES) {
1307 Interval range = static_cast<DeferredClearCaptures*>(this)->range();
1308 return range.Contains(that);
1309 } else {
1310 return reg() == that;
1311 }
1312 }
1305 1313
1306 bool GenerationVariant::mentions_reg(int reg) { 1314
1315 bool Trace::mentions_reg(int reg) {
1307 for (DeferredAction* action = actions_; 1316 for (DeferredAction* action = actions_;
1308 action != NULL; 1317 action != NULL;
1309 action = action->next()) { 1318 action = action->next()) {
1310 if (reg == action->reg()) return true; 1319 if (action->Mentions(reg))
1320 return true;
1311 } 1321 }
1312 return false; 1322 return false;
1313 } 1323 }
1314 1324
1315 1325
1316 int GenerationVariant::FindAffectedRegisters(OutSet* affected_registers) { 1326 bool Trace::GetStoredPosition(int reg, int* cp_offset) {
1317 int max_register = -1; 1327 ASSERT_EQ(0, *cp_offset);
1318 for (DeferredAction* action = actions_; 1328 for (DeferredAction* action = actions_;
1319 action != NULL; 1329 action != NULL;
1320 action = action->next()) { 1330 action = action->next()) {
1321 affected_registers->Set(action->reg()); 1331 if (action->Mentions(reg)) {
1322 if (action->reg() > max_register) max_register = action->reg(); 1332 if (action->type() == ActionNode::STORE_POSITION) {
1333 *cp_offset = static_cast<DeferredCapture*>(action)->cp_offset();
1334 return true;
1335 } else {
1336 return false;
1337 }
1338 }
1339 }
1340 return false;
1341 }
1342
1343
1344 int Trace::FindAffectedRegisters(OutSet* affected_registers) {
1345 int max_register = RegExpCompiler::kNoRegister;
1346 for (DeferredAction* action = actions_;
1347 action != NULL;
1348 action = action->next()) {
1349 if (action->type() == ActionNode::CLEAR_CAPTURES) {
1350 Interval range = static_cast<DeferredClearCaptures*>(action)->range();
1351 for (int i = range.from(); i <= range.to(); i++)
1352 affected_registers->Set(i);
1353 if (range.to() > max_register) max_register = range.to();
1354 } else {
1355 affected_registers->Set(action->reg());
1356 if (action->reg() > max_register) max_register = action->reg();
1357 }
1323 } 1358 }
1324 return max_register; 1359 return max_register;
1325 } 1360 }
1326 1361
1327 1362
1328 void GenerationVariant::PushAffectedRegisters(RegExpMacroAssembler* assembler, 1363 void Trace::PushAffectedRegisters(RegExpMacroAssembler* assembler,
1329 int max_register, 1364 int max_register,
1330 OutSet& affected_registers) { 1365 OutSet& affected_registers) {
1331 for (int reg = 0; reg <= max_register; reg++) { 1366 // Stay safe and check every half times the limit.
1332 if (affected_registers.Get(reg)) assembler->PushRegister(reg); 1367 // (Round up in case the limit is 1).
1368 int push_limit = (assembler->stack_limit_slack() + 1) / 2;
1369 for (int reg = 0, pushes = 0; reg <= max_register; reg++) {
1370 if (affected_registers.Get(reg)) {
1371 pushes++;
1372 RegExpMacroAssembler::StackCheckFlag check_stack_limit =
1373 (pushes % push_limit) == 0 ?
1374 RegExpMacroAssembler::kCheckStackLimit :
1375 RegExpMacroAssembler::kNoStackLimitCheck;
1376 assembler->PushRegister(reg, check_stack_limit);
1377 }
1333 } 1378 }
1334 } 1379 }
1335 1380
1336 1381
1337 void GenerationVariant::RestoreAffectedRegisters( 1382 void Trace::RestoreAffectedRegisters(RegExpMacroAssembler* assembler,
1338 RegExpMacroAssembler* assembler, 1383 int max_register,
1339 int max_register, 1384 OutSet& affected_registers) {
1340 OutSet& affected_registers) {
1341 for (int reg = max_register; reg >= 0; reg--) { 1385 for (int reg = max_register; reg >= 0; reg--) {
1342 if (affected_registers.Get(reg)) assembler->PopRegister(reg); 1386 if (affected_registers.Get(reg)) assembler->PopRegister(reg);
1343 } 1387 }
1344 } 1388 }
1345 1389
1346 1390
1347 void GenerationVariant::PerformDeferredActions(RegExpMacroAssembler* assembler, 1391 void Trace::PerformDeferredActions(RegExpMacroAssembler* assembler,
1348 int max_register, 1392 int max_register,
1349 OutSet& affected_registers) { 1393 OutSet& affected_registers) {
1350 for (int reg = 0; reg <= max_register; reg++) { 1394 for (int reg = 0; reg <= max_register; reg++) {
1351 if (!affected_registers.Get(reg)) { 1395 if (!affected_registers.Get(reg)) {
1352 continue; 1396 continue;
1353 } 1397 }
1354 int value = 0; 1398 int value = 0;
1355 bool absolute = false; 1399 bool absolute = false;
1400 bool clear = false;
1356 int store_position = -1; 1401 int store_position = -1;
1357 // This is a little tricky because we are scanning the actions in reverse 1402 // This is a little tricky because we are scanning the actions in reverse
1358 // historical order (newest first). 1403 // historical order (newest first).
1359 for (DeferredAction* action = actions_; 1404 for (DeferredAction* action = actions_;
1360 action != NULL; 1405 action != NULL;
1361 action = action->next()) { 1406 action = action->next()) {
1362 if (action->reg() == reg) { 1407 if (action->Mentions(reg)) {
1363 switch (action->type()) { 1408 switch (action->type()) {
1364 case ActionNode::SET_REGISTER: { 1409 case ActionNode::SET_REGISTER: {
1365 GenerationVariant::DeferredSetRegister* psr = 1410 Trace::DeferredSetRegister* psr =
1366 static_cast<GenerationVariant::DeferredSetRegister*>(action); 1411 static_cast<Trace::DeferredSetRegister*>(action);
1367 value += psr->value(); 1412 value += psr->value();
1368 absolute = true; 1413 absolute = true;
1369 ASSERT_EQ(store_position, -1); 1414 ASSERT_EQ(store_position, -1);
1415 ASSERT(!clear);
1370 break; 1416 break;
1371 } 1417 }
1372 case ActionNode::INCREMENT_REGISTER: 1418 case ActionNode::INCREMENT_REGISTER:
1373 if (!absolute) { 1419 if (!absolute) {
1374 value++; 1420 value++;
1375 } 1421 }
1376 ASSERT_EQ(store_position, -1); 1422 ASSERT_EQ(store_position, -1);
1423 ASSERT(!clear);
1377 break; 1424 break;
1378 case ActionNode::STORE_POSITION: { 1425 case ActionNode::STORE_POSITION: {
1379 GenerationVariant::DeferredCapture* pc = 1426 Trace::DeferredCapture* pc =
1380 static_cast<GenerationVariant::DeferredCapture*>(action); 1427 static_cast<Trace::DeferredCapture*>(action);
1381 if (store_position == -1) { 1428 if (!clear && store_position == -1) {
1382 store_position = pc->cp_offset(); 1429 store_position = pc->cp_offset();
1383 } 1430 }
1384 ASSERT(!absolute); 1431 ASSERT(!absolute);
1385 ASSERT_EQ(value, 0); 1432 ASSERT_EQ(value, 0);
1386 break; 1433 break;
1387 } 1434 }
1435 case ActionNode::CLEAR_CAPTURES: {
1436 // Since we're scanning in reverse order, if we've already
1437 // set the position we have to ignore historically earlier
1438 // clearing operations.
1439 if (store_position == -1)
1440 clear = true;
1441 ASSERT(!absolute);
1442 ASSERT_EQ(value, 0);
1443 break;
1444 }
1388 default: 1445 default:
1389 UNREACHABLE(); 1446 UNREACHABLE();
1390 break; 1447 break;
1391 } 1448 }
1392 } 1449 }
1393 } 1450 }
1394 if (store_position != -1) { 1451 if (store_position != -1) {
1395 assembler->WriteCurrentPositionToRegister(reg, store_position); 1452 assembler->WriteCurrentPositionToRegister(reg, store_position);
1396 } else { 1453 } else if (clear) {
1397 if (absolute) { 1454 assembler->ClearRegister(reg);
1398 assembler->SetRegister(reg, value); 1455 } else if (absolute) {
1399 } else { 1456 assembler->SetRegister(reg, value);
1400 if (value != 0) { 1457 } else if (value != 0) {
1401 assembler->AdvanceRegister(reg, value); 1458 assembler->AdvanceRegister(reg, value);
1402 }
1403 }
1404 } 1459 }
1405 } 1460 }
1406 } 1461 }
1407 1462
1408 1463
1409 // This is called as we come into a loop choice node and some other tricky 1464 // This is called as we come into a loop choice node and some other tricky
1410 // nodes. It normalises the state of the code generator to ensure we can 1465 // nodes. It normalises the state of the code generator to ensure we can
1411 // generate generic code. 1466 // generate generic code.
1412 bool GenerationVariant::Flush(RegExpCompiler* compiler, RegExpNode* successor) { 1467 bool Trace::Flush(RegExpCompiler* compiler, RegExpNode* successor) {
1413 RegExpMacroAssembler* assembler = compiler->macro_assembler(); 1468 RegExpMacroAssembler* assembler = compiler->macro_assembler();
1414 1469
1415 ASSERT(actions_ != NULL || 1470 ASSERT(actions_ != NULL ||
1416 cp_offset_ != 0 || 1471 cp_offset_ != 0 ||
1417 backtrack() != NULL || 1472 backtrack() != NULL ||
1418 characters_preloaded_ != 0 || 1473 characters_preloaded_ != 0 ||
1419 quick_check_performed_.characters() != 0 || 1474 quick_check_performed_.characters() != 0 ||
1420 bound_checked_up_to_ != 0); 1475 bound_checked_up_to_ != 0);
1421 1476
1422 if (actions_ == NULL && backtrack() == NULL) { 1477 if (actions_ == NULL && backtrack() == NULL) {
1423 // Here we just have some deferred cp advances to fix and we are back to 1478 // Here we just have some deferred cp advances to fix and we are back to
1424 // a normal situation. We may also have to forget some information gained 1479 // a normal situation. We may also have to forget some information gained
1425 // through a quick check that was already performed. 1480 // through a quick check that was already performed.
1426 if (cp_offset_ != 0) assembler->AdvanceCurrentPosition(cp_offset_); 1481 if (cp_offset_ != 0) assembler->AdvanceCurrentPosition(cp_offset_);
1427 // Create a new trivial state and generate the node with that. 1482 // Create a new trivial state and generate the node with that.
1428 GenerationVariant new_state; 1483 Trace new_state;
1429 return successor->Emit(compiler, &new_state); 1484 return successor->Emit(compiler, &new_state);
1430 } 1485 }
1431 1486
1432 // Generate deferred actions here along with code to undo them again. 1487 // Generate deferred actions here along with code to undo them again.
1433 OutSet affected_registers; 1488 OutSet affected_registers;
1434 int max_register = FindAffectedRegisters(&affected_registers); 1489 int max_register = FindAffectedRegisters(&affected_registers);
1435 PushAffectedRegisters(assembler, max_register, affected_registers); 1490 PushAffectedRegisters(assembler, max_register, affected_registers);
1436 PerformDeferredActions(assembler, max_register, affected_registers); 1491 PerformDeferredActions(assembler, max_register, affected_registers);
1437 if (backtrack() != NULL) { 1492 if (backtrack() != NULL) {
1438 // Here we have a concrete backtrack location. These are set up by choice 1493 // Here we have a concrete backtrack location. These are set up by choice
1439 // nodes and so they indicate that we have a deferred save of the current 1494 // nodes and so they indicate that we have a deferred save of the current
1440 // position which we may need to emit here. 1495 // position which we may need to emit here.
1441 assembler->PushCurrentPosition(); 1496 assembler->PushCurrentPosition();
1442 } 1497 }
1443 if (cp_offset_ != 0) { 1498 if (cp_offset_ != 0) {
1444 assembler->AdvanceCurrentPosition(cp_offset_); 1499 assembler->AdvanceCurrentPosition(cp_offset_);
1445 } 1500 }
1446 1501
1447 // Create a new trivial state and generate the node with that. 1502 // Create a new trivial state and generate the node with that.
1448 Label undo; 1503 Label undo;
1449 assembler->PushBacktrack(&undo); 1504 assembler->PushBacktrack(&undo);
1450 GenerationVariant new_state; 1505 Trace new_state;
1451 bool ok = successor->Emit(compiler, &new_state); 1506 bool ok = successor->Emit(compiler, &new_state);
1452 1507
1453 // On backtrack we need to restore state. 1508 // On backtrack we need to restore state.
1454 assembler->Bind(&undo); 1509 assembler->Bind(&undo);
1455 if (!ok) return false; 1510 if (!ok) return false;
1456 if (backtrack() != NULL) { 1511 if (backtrack() != NULL) {
1457 assembler->PopCurrentPosition(); 1512 assembler->PopCurrentPosition();
1458 } 1513 }
1459 RestoreAffectedRegisters(assembler, max_register, affected_registers); 1514 RestoreAffectedRegisters(assembler, max_register, affected_registers);
1460 if (backtrack() == NULL) { 1515 if (backtrack() == NULL) {
1461 assembler->Backtrack(); 1516 assembler->Backtrack();
1462 } else { 1517 } else {
1463 assembler->GoTo(backtrack()); 1518 assembler->GoTo(backtrack());
1464 } 1519 }
1465 1520
1466 return true; 1521 return true;
1467 } 1522 }
1468 1523
1469 1524
1470 void EndNode::EmitInfoChecks(RegExpMacroAssembler* assembler, 1525 void EndNode::EmitInfoChecks(RegExpMacroAssembler* assembler, Trace* trace) {
1471 GenerationVariant* variant) {
1472 if (info()->at_end) { 1526 if (info()->at_end) {
1473 Label succeed; 1527 Label succeed;
1474 // LoadCurrentCharacter will go to the label if we are at the end of the 1528 // LoadCurrentCharacter will go to the label if we are at the end of the
1475 // input string. 1529 // input string.
1476 assembler->LoadCurrentCharacter(0, &succeed); 1530 assembler->LoadCurrentCharacter(0, &succeed);
1477 assembler->GoTo(variant->backtrack()); 1531 assembler->GoTo(trace->backtrack());
1478 assembler->Bind(&succeed); 1532 assembler->Bind(&succeed);
1479 } 1533 }
1480 } 1534 }
1481 1535
1482 1536
1483 bool NegativeSubmatchSuccess::Emit(RegExpCompiler* compiler, 1537 bool NegativeSubmatchSuccess::Emit(RegExpCompiler* compiler, Trace* trace) {
1484 GenerationVariant* variant) { 1538 if (!trace->is_trivial()) {
1485 if (!variant->is_trivial()) { 1539 return trace->Flush(compiler, this);
1486 return variant->Flush(compiler, this);
1487 } 1540 }
1488 RegExpMacroAssembler* assembler = compiler->macro_assembler(); 1541 RegExpMacroAssembler* assembler = compiler->macro_assembler();
1489 if (!label()->is_bound()) { 1542 if (!label()->is_bound()) {
1490 assembler->Bind(label()); 1543 assembler->Bind(label());
1491 } 1544 }
1492 EmitInfoChecks(assembler, variant); 1545 EmitInfoChecks(assembler, trace);
1493 assembler->ReadCurrentPositionFromRegister(current_position_register_); 1546 assembler->ReadCurrentPositionFromRegister(current_position_register_);
1494 assembler->ReadStackPointerFromRegister(stack_pointer_register_); 1547 assembler->ReadStackPointerFromRegister(stack_pointer_register_);
1495 // Now that we have unwound the stack we find at the top of the stack the 1548 // Now that we have unwound the stack we find at the top of the stack the
1496 // backtrack that the BeginSubmatch node got. 1549 // backtrack that the BeginSubmatch node got.
1497 assembler->Backtrack(); 1550 assembler->Backtrack();
1498 return true; 1551 return true;
1499 } 1552 }
1500 1553
1501 1554
1502 bool EndNode::Emit(RegExpCompiler* compiler, GenerationVariant* variant) { 1555 bool EndNode::Emit(RegExpCompiler* compiler, Trace* trace) {
1503 if (!variant->is_trivial()) { 1556 if (!trace->is_trivial()) {
1504 return variant->Flush(compiler, this); 1557 return trace->Flush(compiler, this);
1505 } 1558 }
1506 RegExpMacroAssembler* assembler = compiler->macro_assembler(); 1559 RegExpMacroAssembler* assembler = compiler->macro_assembler();
1507 if (!label()->is_bound()) { 1560 if (!label()->is_bound()) {
1508 assembler->Bind(label()); 1561 assembler->Bind(label());
1509 } 1562 }
1510 switch (action_) { 1563 switch (action_) {
1511 case ACCEPT: 1564 case ACCEPT:
1512 EmitInfoChecks(assembler, variant); 1565 EmitInfoChecks(assembler, trace);
1513 assembler->Succeed(); 1566 assembler->Succeed();
1514 return true; 1567 return true;
1515 case BACKTRACK: 1568 case BACKTRACK:
1516 ASSERT(!info()->at_end); 1569 ASSERT(!info()->at_end);
1517 assembler->GoTo(variant->backtrack()); 1570 assembler->GoTo(trace->backtrack());
1518 return true; 1571 return true;
1519 case NEGATIVE_SUBMATCH_SUCCESS: 1572 case NEGATIVE_SUBMATCH_SUCCESS:
1520 // This case is handled in a different virtual method. 1573 // This case is handled in a different virtual method.
1521 UNREACHABLE(); 1574 UNREACHABLE();
1522 } 1575 }
1523 UNIMPLEMENTED(); 1576 UNIMPLEMENTED();
1524 return false; 1577 return false;
1525 } 1578 }
1526 1579
1527 1580
(...skipping 21 matching lines...) Expand all
1549 } 1602 }
1550 1603
1551 1604
1552 ActionNode* ActionNode::StorePosition(int reg, RegExpNode* on_success) { 1605 ActionNode* ActionNode::StorePosition(int reg, RegExpNode* on_success) {
1553 ActionNode* result = new ActionNode(STORE_POSITION, on_success); 1606 ActionNode* result = new ActionNode(STORE_POSITION, on_success);
1554 result->data_.u_position_register.reg = reg; 1607 result->data_.u_position_register.reg = reg;
1555 return result; 1608 return result;
1556 } 1609 }
1557 1610
1558 1611
1612 ActionNode* ActionNode::ClearCaptures(Interval range,
1613 RegExpNode* on_success) {
1614 ActionNode* result = new ActionNode(CLEAR_CAPTURES, on_success);
1615 result->data_.u_clear_captures.range_from = range.from();
1616 result->data_.u_clear_captures.range_to = range.to();
1617 return result;
1618 }
1619
1620
1559 ActionNode* ActionNode::BeginSubmatch(int stack_reg, 1621 ActionNode* ActionNode::BeginSubmatch(int stack_reg,
1560 int position_reg, 1622 int position_reg,
1561 RegExpNode* on_success) { 1623 RegExpNode* on_success) {
1562 ActionNode* result = new ActionNode(BEGIN_SUBMATCH, on_success); 1624 ActionNode* result = new ActionNode(BEGIN_SUBMATCH, on_success);
1563 result->data_.u_submatch.stack_pointer_register = stack_reg; 1625 result->data_.u_submatch.stack_pointer_register = stack_reg;
1564 result->data_.u_submatch.current_position_register = position_reg; 1626 result->data_.u_submatch.current_position_register = position_reg;
1565 return result; 1627 return result;
1566 } 1628 }
1567 1629
1568 1630
1569 ActionNode* ActionNode::PositiveSubmatchSuccess(int stack_reg, 1631 ActionNode* ActionNode::PositiveSubmatchSuccess(int stack_reg,
1570 int position_reg, 1632 int position_reg,
1571 RegExpNode* on_success) { 1633 RegExpNode* on_success) {
1572 ActionNode* result = new ActionNode(POSITIVE_SUBMATCH_SUCCESS, on_success); 1634 ActionNode* result = new ActionNode(POSITIVE_SUBMATCH_SUCCESS, on_success);
1573 result->data_.u_submatch.stack_pointer_register = stack_reg; 1635 result->data_.u_submatch.stack_pointer_register = stack_reg;
1574 result->data_.u_submatch.current_position_register = position_reg; 1636 result->data_.u_submatch.current_position_register = position_reg;
1575 return result; 1637 return result;
1576 } 1638 }
1577 1639
1578 1640
1641 ActionNode* ActionNode::EmptyMatchCheck(int start_register,
1642 int repetition_register,
1643 int repetition_limit,
1644 RegExpNode* on_success) {
1645 ActionNode* result = new ActionNode(EMPTY_MATCH_CHECK, on_success);
1646 result->data_.u_empty_match_check.start_register = start_register;
1647 result->data_.u_empty_match_check.repetition_register = repetition_register;
1648 result->data_.u_empty_match_check.repetition_limit = repetition_limit;
1649 return result;
1650 }
1651
1652
1579 #define DEFINE_ACCEPT(Type) \ 1653 #define DEFINE_ACCEPT(Type) \
1580 void Type##Node::Accept(NodeVisitor* visitor) { \ 1654 void Type##Node::Accept(NodeVisitor* visitor) { \
1581 visitor->Visit##Type(this); \ 1655 visitor->Visit##Type(this); \
1582 } 1656 }
1583 FOR_EACH_NODE_TYPE(DEFINE_ACCEPT) 1657 FOR_EACH_NODE_TYPE(DEFINE_ACCEPT)
1584 #undef DEFINE_ACCEPT 1658 #undef DEFINE_ACCEPT
1585 1659
1586 1660
1587 void LoopChoiceNode::Accept(NodeVisitor* visitor) { 1661 void LoopChoiceNode::Accept(NodeVisitor* visitor) {
1588 visitor->VisitLoopChoice(this); 1662 visitor->VisitLoopChoice(this);
1589 } 1663 }
1590 1664
1591 1665
1592 // ------------------------------------------------------------------- 1666 // -------------------------------------------------------------------
1593 // Emit code. 1667 // Emit code.
1594 1668
1595 1669
1596 void ChoiceNode::GenerateGuard(RegExpMacroAssembler* macro_assembler, 1670 void ChoiceNode::GenerateGuard(RegExpMacroAssembler* macro_assembler,
1597 Guard* guard, 1671 Guard* guard,
1598 GenerationVariant* variant) { 1672 Trace* trace) {
1599 switch (guard->op()) { 1673 switch (guard->op()) {
1600 case Guard::LT: 1674 case Guard::LT:
1601 ASSERT(!variant->mentions_reg(guard->reg())); 1675 ASSERT(!trace->mentions_reg(guard->reg()));
1602 macro_assembler->IfRegisterGE(guard->reg(), 1676 macro_assembler->IfRegisterGE(guard->reg(),
1603 guard->value(), 1677 guard->value(),
1604 variant->backtrack()); 1678 trace->backtrack());
1605 break; 1679 break;
1606 case Guard::GEQ: 1680 case Guard::GEQ:
1607 ASSERT(!variant->mentions_reg(guard->reg())); 1681 ASSERT(!trace->mentions_reg(guard->reg()));
1608 macro_assembler->IfRegisterLT(guard->reg(), 1682 macro_assembler->IfRegisterLT(guard->reg(),
1609 guard->value(), 1683 guard->value(),
1610 variant->backtrack()); 1684 trace->backtrack());
1611 break; 1685 break;
1612 } 1686 }
1613 } 1687 }
1614 1688
1615 1689
1616 static unibrow::Mapping<unibrow::Ecma262UnCanonicalize> uncanonicalize; 1690 static unibrow::Mapping<unibrow::Ecma262UnCanonicalize> uncanonicalize;
1617 static unibrow::Mapping<unibrow::CanonicalizationRange> canonrange; 1691 static unibrow::Mapping<unibrow::CanonicalizationRange> canonrange;
1618 1692
1619 1693
1620 // Only emits non-letters (things that don't have case). Only used for case 1694 // Only emits non-letters (things that don't have case). Only used for case
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
1853 } 1927 }
1854 macro_assembler->Bind(&success); 1928 macro_assembler->Bind(&success);
1855 } 1929 }
1856 1930
1857 1931
1858 RegExpNode::~RegExpNode() { 1932 RegExpNode::~RegExpNode() {
1859 } 1933 }
1860 1934
1861 1935
1862 RegExpNode::LimitResult RegExpNode::LimitVersions(RegExpCompiler* compiler, 1936 RegExpNode::LimitResult RegExpNode::LimitVersions(RegExpCompiler* compiler,
1863 GenerationVariant* variant) { 1937 Trace* trace) {
1864 // TODO(erikcorry): Implement support. 1938 // TODO(erikcorry): Implement support.
1865 if (info_.follows_word_interest || 1939 if (info_.follows_word_interest ||
1866 info_.follows_newline_interest || 1940 info_.follows_newline_interest ||
1867 info_.follows_start_interest) { 1941 info_.follows_start_interest) {
1868 return FAIL; 1942 return FAIL;
1869 } 1943 }
1870 1944
1871 // If we are generating a greedy loop then don't stop and don't reuse code. 1945 // If we are generating a greedy loop then don't stop and don't reuse code.
1872 if (variant->stop_node() != NULL) { 1946 if (trace->stop_node() != NULL) {
1873 return CONTINUE; 1947 return CONTINUE;
1874 } 1948 }
1875 1949
1876 RegExpMacroAssembler* macro_assembler = compiler->macro_assembler(); 1950 RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
1877 if (variant->is_trivial()) { 1951 if (trace->is_trivial()) {
1878 if (label_.is_bound()) { 1952 if (label_.is_bound()) {
1879 // We are being asked to generate a generic version, but that's already 1953 // We are being asked to generate a generic version, but that's already
1880 // been done so just go to it. 1954 // been done so just go to it.
1881 macro_assembler->GoTo(&label_); 1955 macro_assembler->GoTo(&label_);
1882 return DONE; 1956 return DONE;
1883 } 1957 }
1884 if (compiler->recursion_depth() >= RegExpCompiler::kMaxRecursion) { 1958 if (compiler->recursion_depth() >= RegExpCompiler::kMaxRecursion) {
1885 // To avoid too deep recursion we push the node to the work queue and just 1959 // To avoid too deep recursion we push the node to the work queue and just
1886 // generate a goto here. 1960 // generate a goto here.
1887 compiler->AddWork(this); 1961 compiler->AddWork(this);
1888 macro_assembler->GoTo(&label_); 1962 macro_assembler->GoTo(&label_);
1889 return DONE; 1963 return DONE;
1890 } 1964 }
1891 // Generate generic version of the node and bind the label for later use. 1965 // Generate generic version of the node and bind the label for later use.
1892 macro_assembler->Bind(&label_); 1966 macro_assembler->Bind(&label_);
1893 return CONTINUE; 1967 return CONTINUE;
1894 } 1968 }
1895 1969
1896 // We are being asked to make a non-generic version. Keep track of how many 1970 // We are being asked to make a non-generic version. Keep track of how many
1897 // non-generic versions we generate so as not to overdo it. 1971 // non-generic versions we generate so as not to overdo it.
1898 variants_generated_++; 1972 trace_count_++;
1899 if (variants_generated_ < kMaxVariantsGenerated && 1973 if (trace_count_ < kMaxCopiesCodeGenerated &&
1900 compiler->recursion_depth() <= RegExpCompiler::kMaxRecursion) { 1974 compiler->recursion_depth() <= RegExpCompiler::kMaxRecursion) {
1901 return CONTINUE; 1975 return CONTINUE;
1902 } 1976 }
1903 1977
1904 // If we get here there have been too many variants generated or recursion 1978 // If we get here code has been generated for this node too many times or
1905 // is too deep. Time to switch to a generic version. The code for 1979 // recursion is too deep. Time to switch to a generic version. The code for
1906 // generic versions above can handle deep recursion properly. 1980 // generic versions above can handle deep recursion properly.
1907 bool ok = variant->Flush(compiler, this); 1981 bool ok = trace->Flush(compiler, this);
1908 return ok ? DONE : FAIL; 1982 return ok ? DONE : FAIL;
1909 } 1983 }
1910 1984
1911 1985
1912 int ActionNode::EatsAtLeast(int recursion_depth) { 1986 int ActionNode::EatsAtLeast(int recursion_depth) {
1913 if (recursion_depth > RegExpCompiler::kMaxRecursion) return 0; 1987 if (recursion_depth > RegExpCompiler::kMaxRecursion) return 0;
1914 if (type_ == POSITIVE_SUBMATCH_SUCCESS) return 0; // Rewinds input! 1988 if (type_ == POSITIVE_SUBMATCH_SUCCESS) return 0; // Rewinds input!
1915 return on_success()->EatsAtLeast(recursion_depth + 1); 1989 return on_success()->EatsAtLeast(recursion_depth + 1);
1916 } 1990 }
1917 1991
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
1978 } 2052 }
1979 mask_ |= (pos->mask & char_mask) << char_shift; 2053 mask_ |= (pos->mask & char_mask) << char_shift;
1980 value_ |= (pos->value & char_mask) << char_shift; 2054 value_ |= (pos->value & char_mask) << char_shift;
1981 char_shift += asc ? 8 : 16; 2055 char_shift += asc ? 8 : 16;
1982 } 2056 }
1983 return found_useful_op; 2057 return found_useful_op;
1984 } 2058 }
1985 2059
1986 2060
1987 bool RegExpNode::EmitQuickCheck(RegExpCompiler* compiler, 2061 bool RegExpNode::EmitQuickCheck(RegExpCompiler* compiler,
1988 GenerationVariant* variant, 2062 Trace* trace,
1989 bool preload_has_checked_bounds, 2063 bool preload_has_checked_bounds,
1990 Label* on_possible_success, 2064 Label* on_possible_success,
1991 QuickCheckDetails* details, 2065 QuickCheckDetails* details,
1992 bool fall_through_on_failure) { 2066 bool fall_through_on_failure) {
1993 if (details->characters() == 0) return false; 2067 if (details->characters() == 0) return false;
1994 GetQuickCheckDetails(details, compiler, 0); 2068 GetQuickCheckDetails(details, compiler, 0);
1995 if (!details->Rationalize(compiler->ascii())) return false; 2069 if (!details->Rationalize(compiler->ascii())) return false;
1996 uint32_t mask = details->mask(); 2070 uint32_t mask = details->mask();
1997 uint32_t value = details->value(); 2071 uint32_t value = details->value();
1998 2072
1999 RegExpMacroAssembler* assembler = compiler->macro_assembler(); 2073 RegExpMacroAssembler* assembler = compiler->macro_assembler();
2000 2074
2001 if (variant->characters_preloaded() != details->characters()) { 2075 if (trace->characters_preloaded() != details->characters()) {
2002 assembler->LoadCurrentCharacter(variant->cp_offset(), 2076 assembler->LoadCurrentCharacter(trace->cp_offset(),
2003 variant->backtrack(), 2077 trace->backtrack(),
2004 !preload_has_checked_bounds, 2078 !preload_has_checked_bounds,
2005 details->characters()); 2079 details->characters());
2006 } 2080 }
2007 2081
2008 2082
2009 bool need_mask = true; 2083 bool need_mask = true;
2010 2084
2011 if (details->characters() == 1) { 2085 if (details->characters() == 1) {
2012 // If number of characters preloaded is 1 then we used a byte or 16 bit 2086 // If number of characters preloaded is 1 then we used a byte or 16 bit
2013 // load so the value is already masked down. 2087 // load so the value is already masked down.
(...skipping 16 matching lines...) Expand all
2030 } 2104 }
2031 2105
2032 if (fall_through_on_failure) { 2106 if (fall_through_on_failure) {
2033 if (need_mask) { 2107 if (need_mask) {
2034 assembler->CheckCharacterAfterAnd(value, mask, on_possible_success); 2108 assembler->CheckCharacterAfterAnd(value, mask, on_possible_success);
2035 } else { 2109 } else {
2036 assembler->CheckCharacter(value, on_possible_success); 2110 assembler->CheckCharacter(value, on_possible_success);
2037 } 2111 }
2038 } else { 2112 } else {
2039 if (need_mask) { 2113 if (need_mask) {
2040 assembler->CheckNotCharacterAfterAnd(value, mask, variant->backtrack()); 2114 assembler->CheckNotCharacterAfterAnd(value, mask, trace->backtrack());
2041 } else { 2115 } else {
2042 assembler->CheckNotCharacter(value, variant->backtrack()); 2116 assembler->CheckNotCharacter(value, trace->backtrack());
2043 } 2117 }
2044 } 2118 }
2045 return true; 2119 return true;
2046 } 2120 }
2047 2121
2048 2122
2049 // Here is the meat of GetQuickCheckDetails (see also the comment on the 2123 // Here is the meat of GetQuickCheckDetails (see also the comment on the
2050 // super-class in the .h file). 2124 // super-class in the .h file).
2051 // 2125 //
2052 // We iterate along the text object, building up for each character a 2126 // We iterate along the text object, building up for each character a
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
2218 pos->mask &= other_pos->mask; 2292 pos->mask &= other_pos->mask;
2219 pos->value &= pos->mask; 2293 pos->value &= pos->mask;
2220 other_pos->value &= pos->mask; 2294 other_pos->value &= pos->mask;
2221 uc16 differing_bits = (pos->value ^ other_pos->value); 2295 uc16 differing_bits = (pos->value ^ other_pos->value);
2222 pos->mask &= ~differing_bits; 2296 pos->mask &= ~differing_bits;
2223 pos->value &= pos->mask; 2297 pos->value &= pos->mask;
2224 } 2298 }
2225 } 2299 }
2226 2300
2227 2301
2302 class VisitMarker {
2303 public:
2304 explicit VisitMarker(NodeInfo* info) : info_(info) {
2305 ASSERT(!info->visited);
2306 info->visited = true;
2307 }
2308 ~VisitMarker() {
2309 info_->visited = false;
2310 }
2311 private:
2312 NodeInfo* info_;
2313 };
2314
2315
2228 void LoopChoiceNode::GetQuickCheckDetails(QuickCheckDetails* details, 2316 void LoopChoiceNode::GetQuickCheckDetails(QuickCheckDetails* details,
2229 RegExpCompiler* compiler, 2317 RegExpCompiler* compiler,
2230 int characters_filled_in) { 2318 int characters_filled_in) {
2231 if (body_can_be_zero_length_) return; 2319 if (body_can_be_zero_length_ || info()->visited) return;
2320 VisitMarker marker(info());
2232 return ChoiceNode::GetQuickCheckDetails(details, 2321 return ChoiceNode::GetQuickCheckDetails(details,
2233 compiler, 2322 compiler,
2234 characters_filled_in); 2323 characters_filled_in);
2235 } 2324 }
2236 2325
2237 2326
2238 void ChoiceNode::GetQuickCheckDetails(QuickCheckDetails* details, 2327 void ChoiceNode::GetQuickCheckDetails(QuickCheckDetails* details,
2239 RegExpCompiler* compiler, 2328 RegExpCompiler* compiler,
2240 int characters_filled_in) { 2329 int characters_filled_in) {
2241 int choice_count = alternatives_->length(); 2330 int choice_count = alternatives_->length();
(...skipping 25 matching lines...) Expand all
2267 // end-of-input when loading the putative 'r'. 2356 // end-of-input when loading the putative 'r'.
2268 // 2357 //
2269 // A slight complication involves the fact that the first character may already 2358 // A slight complication involves the fact that the first character may already
2270 // be fetched into a register by the previous node. In this case we want to 2359 // be fetched into a register by the previous node. In this case we want to
2271 // do the test for that character first. We do this in separate passes. The 2360 // do the test for that character first. We do this in separate passes. The
2272 // 'preloaded' argument indicates that we are doing such a 'pass'. If such a 2361 // 'preloaded' argument indicates that we are doing such a 'pass'. If such a
2273 // pass has been performed then subsequent passes will have true in 2362 // pass has been performed then subsequent passes will have true in
2274 // first_element_checked to indicate that that character does not need to be 2363 // first_element_checked to indicate that that character does not need to be
2275 // checked again. 2364 // checked again.
2276 // 2365 //
2277 // In addition to all this we are passed a GenerationVariant, which can 2366 // In addition to all this we are passed a Trace, which can
2278 // contain an AlternativeGeneration object. In this AlternativeGeneration 2367 // contain an AlternativeGeneration object. In this AlternativeGeneration
2279 // object we can see details of any quick check that was already passed in 2368 // object we can see details of any quick check that was already passed in
2280 // order to get to the code we are now generating. The quick check can involve 2369 // order to get to the code we are now generating. The quick check can involve
2281 // loading characters, which means we do not need to recheck the bounds 2370 // loading characters, which means we do not need to recheck the bounds
2282 // up to the limit the quick check already checked. In addition the quick 2371 // up to the limit the quick check already checked. In addition the quick
2283 // check can have involved a mask and compare operation which may simplify 2372 // check can have involved a mask and compare operation which may simplify
2284 // or obviate the need for further checks at some character positions. 2373 // or obviate the need for further checks at some character positions.
2285 void TextNode::TextEmitPass(RegExpCompiler* compiler, 2374 void TextNode::TextEmitPass(RegExpCompiler* compiler,
2286 TextEmitPassType pass, 2375 TextEmitPassType pass,
2287 bool preloaded, 2376 bool preloaded,
2288 GenerationVariant* variant, 2377 Trace* trace,
2289 bool first_element_checked, 2378 bool first_element_checked,
2290 int* checked_up_to) { 2379 int* checked_up_to) {
2291 RegExpMacroAssembler* assembler = compiler->macro_assembler(); 2380 RegExpMacroAssembler* assembler = compiler->macro_assembler();
2292 bool ascii = compiler->ascii(); 2381 bool ascii = compiler->ascii();
2293 Label* backtrack = variant->backtrack(); 2382 Label* backtrack = trace->backtrack();
2294 QuickCheckDetails* quick_check = variant->quick_check_performed(); 2383 QuickCheckDetails* quick_check = trace->quick_check_performed();
2295 int element_count = elms_->length(); 2384 int element_count = elms_->length();
2296 for (int i = preloaded ? 0 : element_count - 1; i >= 0; i--) { 2385 for (int i = preloaded ? 0 : element_count - 1; i >= 0; i--) {
2297 TextElement elm = elms_->at(i); 2386 TextElement elm = elms_->at(i);
2298 int cp_offset = variant->cp_offset() + elm.cp_offset; 2387 int cp_offset = trace->cp_offset() + elm.cp_offset;
2299 if (elm.type == TextElement::ATOM) { 2388 if (elm.type == TextElement::ATOM) {
2300 if (pass == NON_ASCII_MATCH || 2389 if (pass == NON_ASCII_MATCH ||
2301 pass == CHARACTER_MATCH || 2390 pass == CHARACTER_MATCH ||
2302 pass == CASE_CHARACTER_MATCH) { 2391 pass == CASE_CHARACTER_MATCH) {
2303 Vector<const uc16> quarks = elm.data.u_atom->data(); 2392 Vector<const uc16> quarks = elm.data.u_atom->data();
2304 for (int j = preloaded ? 0 : quarks.length() - 1; j >= 0; j--) { 2393 for (int j = preloaded ? 0 : quarks.length() - 1; j >= 0; j--) {
2305 bool bound_checked = true; // Most ops will check their bounds. 2394 bool bound_checked = true; // Most ops will check their bounds.
2306 if (first_element_checked && i == 0 && j == 0) continue; 2395 if (first_element_checked && i == 0 && j == 0) continue;
2307 if (quick_check != NULL && 2396 if (quick_check != NULL &&
2308 elm.cp_offset + j < quick_check->characters() && 2397 elm.cp_offset + j < quick_check->characters() &&
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
2385 } 2474 }
2386 } 2475 }
2387 2476
2388 2477
2389 // This generates the code to match a text node. A text node can contain 2478 // This generates the code to match a text node. A text node can contain
2390 // straight character sequences (possibly to be matched in a case-independent 2479 // straight character sequences (possibly to be matched in a case-independent
2391 // way) and character classes. For efficiency we do not do this in a single 2480 // way) and character classes. For efficiency we do not do this in a single
2392 // pass from left to right. Instead we pass over the text node several times, 2481 // pass from left to right. Instead we pass over the text node several times,
2393 // emitting code for some character positions every time. See the comment on 2482 // emitting code for some character positions every time. See the comment on
2394 // TextEmitPass for details. 2483 // TextEmitPass for details.
2395 bool TextNode::Emit(RegExpCompiler* compiler, GenerationVariant* variant) { 2484 bool TextNode::Emit(RegExpCompiler* compiler, Trace* trace) {
2396 LimitResult limit_result = LimitVersions(compiler, variant); 2485 LimitResult limit_result = LimitVersions(compiler, trace);
2397 if (limit_result == FAIL) return false; 2486 if (limit_result == FAIL) return false;
2398 if (limit_result == DONE) return true; 2487 if (limit_result == DONE) return true;
2399 ASSERT(limit_result == CONTINUE); 2488 ASSERT(limit_result == CONTINUE);
2400 2489
2401 if (info()->follows_word_interest || 2490 if (info()->follows_word_interest ||
2402 info()->follows_newline_interest || 2491 info()->follows_newline_interest ||
2403 info()->follows_start_interest) { 2492 info()->follows_start_interest) {
2404 return false; 2493 return false;
2405 } 2494 }
2406 2495
2407 if (info()->at_end) { 2496 if (info()->at_end) {
2408 compiler->macro_assembler()->GoTo(variant->backtrack()); 2497 compiler->macro_assembler()->GoTo(trace->backtrack());
2409 return true; 2498 return true;
2410 } 2499 }
2411 2500
2412 if (compiler->ascii()) { 2501 if (compiler->ascii()) {
2413 int dummy = 0; 2502 int dummy = 0;
2414 TextEmitPass(compiler, NON_ASCII_MATCH, false, variant, false, &dummy); 2503 TextEmitPass(compiler, NON_ASCII_MATCH, false, trace, false, &dummy);
2415 } 2504 }
2416 2505
2417 bool first_elt_done = false; 2506 bool first_elt_done = false;
2418 int bound_checked_to = variant->cp_offset() - 1; 2507 int bound_checked_to = trace->cp_offset() - 1;
2419 bound_checked_to += variant->bound_checked_up_to(); 2508 bound_checked_to += trace->bound_checked_up_to();
2420 2509
2421 // If a character is preloaded into the current character register then 2510 // If a character is preloaded into the current character register then
2422 // check that now. 2511 // check that now.
2423 if (variant->characters_preloaded() == 1) { 2512 if (trace->characters_preloaded() == 1) {
2424 TextEmitPass(compiler, 2513 TextEmitPass(compiler,
2425 CHARACTER_MATCH, 2514 CHARACTER_MATCH,
2426 true, 2515 true,
2427 variant, 2516 trace,
2428 false, 2517 false,
2429 &bound_checked_to); 2518 &bound_checked_to);
2430 if (compiler->ignore_case()) { 2519 if (compiler->ignore_case()) {
2431 TextEmitPass(compiler, 2520 TextEmitPass(compiler,
2432 CASE_CHARACTER_MATCH, 2521 CASE_CHARACTER_MATCH,
2433 true, 2522 true,
2434 variant, 2523 trace,
2435 false, 2524 false,
2436 &bound_checked_to); 2525 &bound_checked_to);
2437 } 2526 }
2438 TextEmitPass(compiler, 2527 TextEmitPass(compiler,
2439 CHARACTER_CLASS_MATCH, 2528 CHARACTER_CLASS_MATCH,
2440 true, 2529 true,
2441 variant, 2530 trace,
2442 false, 2531 false,
2443 &bound_checked_to); 2532 &bound_checked_to);
2444 first_elt_done = true; 2533 first_elt_done = true;
2445 } 2534 }
2446 2535
2447 TextEmitPass(compiler, 2536 TextEmitPass(compiler,
2448 CHARACTER_MATCH, 2537 CHARACTER_MATCH,
2449 false, 2538 false,
2450 variant, 2539 trace,
2451 first_elt_done, 2540 first_elt_done,
2452 &bound_checked_to); 2541 &bound_checked_to);
2453 if (compiler->ignore_case()) { 2542 if (compiler->ignore_case()) {
2454 TextEmitPass(compiler, 2543 TextEmitPass(compiler,
2455 CASE_CHARACTER_MATCH, 2544 CASE_CHARACTER_MATCH,
2456 false, 2545 false,
2457 variant, 2546 trace,
2458 first_elt_done, 2547 first_elt_done,
2459 &bound_checked_to); 2548 &bound_checked_to);
2460 } 2549 }
2461 TextEmitPass(compiler, 2550 TextEmitPass(compiler,
2462 CHARACTER_CLASS_MATCH, 2551 CHARACTER_CLASS_MATCH,
2463 false, 2552 false,
2464 variant, 2553 trace,
2465 first_elt_done, 2554 first_elt_done,
2466 &bound_checked_to); 2555 &bound_checked_to);
2467 2556
2468 GenerationVariant successor_variant(*variant); 2557 Trace successor_trace(*trace);
2469 successor_variant.AdvanceVariant(Length(), compiler->ascii()); 2558 successor_trace.AdvanceCurrentPositionInTrace(Length(), compiler->ascii());
2470 RecursionCheck rc(compiler); 2559 RecursionCheck rc(compiler);
2471 return on_success()->Emit(compiler, &successor_variant); 2560 return on_success()->Emit(compiler, &successor_trace);
2472 } 2561 }
2473 2562
2474 2563
2475 void GenerationVariant::AdvanceVariant(int by, bool ascii) { 2564 void Trace::AdvanceCurrentPositionInTrace(int by, bool ascii) {
2476 ASSERT(by > 0); 2565 ASSERT(by > 0);
2477 // We don't have an instruction for shifting the current character register 2566 // We don't have an instruction for shifting the current character register
2478 // down or for using a shifted value for anything so lets just forget that 2567 // down or for using a shifted value for anything so lets just forget that
2479 // we preloaded any characters into it. 2568 // we preloaded any characters into it.
2480 characters_preloaded_ = 0; 2569 characters_preloaded_ = 0;
2481 // Adjust the offsets of the quick check performed information. This 2570 // Adjust the offsets of the quick check performed information. This
2482 // information is used to find out what we already determined about the 2571 // information is used to find out what we already determined about the
2483 // characters by means of mask and compare. 2572 // characters by means of mask and compare.
2484 quick_check_performed_.Advance(by, ascii); 2573 quick_check_performed_.Advance(by, ascii);
2485 cp_offset_ += by; 2574 cp_offset_ += by;
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
2552 } 2641 }
2553 2642
2554 2643
2555 void LoopChoiceNode::AddContinueAlternative(GuardedAlternative alt) { 2644 void LoopChoiceNode::AddContinueAlternative(GuardedAlternative alt) {
2556 ASSERT_EQ(continue_node_, NULL); 2645 ASSERT_EQ(continue_node_, NULL);
2557 AddAlternative(alt); 2646 AddAlternative(alt);
2558 continue_node_ = alt.node(); 2647 continue_node_ = alt.node();
2559 } 2648 }
2560 2649
2561 2650
2562 bool LoopChoiceNode::Emit(RegExpCompiler* compiler, 2651 bool LoopChoiceNode::Emit(RegExpCompiler* compiler, Trace* trace) {
2563 GenerationVariant* variant) {
2564 RegExpMacroAssembler* macro_assembler = compiler->macro_assembler(); 2652 RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
2565 if (variant->stop_node() == this) { 2653 if (trace->stop_node() == this) {
2566 int text_length = GreedyLoopTextLength(&(alternatives_->at(0))); 2654 int text_length = GreedyLoopTextLength(&(alternatives_->at(0)));
2567 ASSERT(text_length != kNodeIsTooComplexForGreedyLoops); 2655 ASSERT(text_length != kNodeIsTooComplexForGreedyLoops);
2568 // Update the counter-based backtracking info on the stack. This is an 2656 // Update the counter-based backtracking info on the stack. This is an
2569 // optimization for greedy loops (see below). 2657 // optimization for greedy loops (see below).
2570 ASSERT(variant->cp_offset() == text_length); 2658 ASSERT(trace->cp_offset() == text_length);
2571 macro_assembler->AdvanceCurrentPosition(text_length); 2659 macro_assembler->AdvanceCurrentPosition(text_length);
2572 macro_assembler->GoTo(variant->loop_label()); 2660 macro_assembler->GoTo(trace->loop_label());
2573 return true; 2661 return true;
2574 } 2662 }
2575 ASSERT(variant->stop_node() == NULL); 2663 ASSERT(trace->stop_node() == NULL);
2576 if (!variant->is_trivial()) { 2664 if (!trace->is_trivial()) {
2577 return variant->Flush(compiler, this); 2665 return trace->Flush(compiler, this);
2578 } 2666 }
2579 return ChoiceNode::Emit(compiler, variant); 2667 return ChoiceNode::Emit(compiler, trace);
2580 } 2668 }
2581 2669
2582 2670
2583 int ChoiceNode::CalculatePreloadCharacters(RegExpCompiler* compiler) { 2671 int ChoiceNode::CalculatePreloadCharacters(RegExpCompiler* compiler) {
2584 int preload_characters = EatsAtLeast(0); 2672 int preload_characters = EatsAtLeast(0);
2585 #ifdef CAN_READ_UNALIGNED 2673 #ifdef CAN_READ_UNALIGNED
2586 bool ascii = compiler->ascii(); 2674 bool ascii = compiler->ascii();
2587 if (ascii) { 2675 if (ascii) {
2588 if (preload_characters > 4) preload_characters = 4; 2676 if (preload_characters > 4) preload_characters = 4;
2589 // We can't preload 3 characters because there is no machine instruction 2677 // We can't preload 3 characters because there is no machine instruction
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
2722 * | / | 2810 * | / |
2723 * | R | 2811 * | R |
2724 * | / | 2812 * | / |
2725 * F VL | 2813 * F VL |
2726 * <------U | 2814 * <------U |
2727 * back |S | 2815 * back |S |
2728 * \______________/ 2816 * \______________/
2729 */ 2817 */
2730 2818
2731 2819
2732 bool ChoiceNode::Emit(RegExpCompiler* compiler, GenerationVariant* variant) { 2820 bool ChoiceNode::Emit(RegExpCompiler* compiler, Trace* trace) {
2733 RegExpMacroAssembler* macro_assembler = compiler->macro_assembler(); 2821 RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
2734 int choice_count = alternatives_->length(); 2822 int choice_count = alternatives_->length();
2735 #ifdef DEBUG 2823 #ifdef DEBUG
2736 for (int i = 0; i < choice_count - 1; i++) { 2824 for (int i = 0; i < choice_count - 1; i++) {
2737 GuardedAlternative alternative = alternatives_->at(i); 2825 GuardedAlternative alternative = alternatives_->at(i);
2738 ZoneList<Guard*>* guards = alternative.guards(); 2826 ZoneList<Guard*>* guards = alternative.guards();
2739 int guard_count = (guards == NULL) ? 0 : guards->length(); 2827 int guard_count = (guards == NULL) ? 0 : guards->length();
2740 for (int j = 0; j < guard_count; j++) { 2828 for (int j = 0; j < guard_count; j++) {
2741 ASSERT(!variant->mentions_reg(guards->at(j)->reg())); 2829 ASSERT(!trace->mentions_reg(guards->at(j)->reg()));
2742 } 2830 }
2743 } 2831 }
2744 #endif 2832 #endif
2745 2833
2746 LimitResult limit_result = LimitVersions(compiler, variant); 2834 LimitResult limit_result = LimitVersions(compiler, trace);
2747 if (limit_result == DONE) return true; 2835 if (limit_result == DONE) return true;
2748 if (limit_result == FAIL) return false; 2836 if (limit_result == FAIL) return false;
2749 ASSERT(limit_result == CONTINUE); 2837 ASSERT(limit_result == CONTINUE);
2750 2838
2751 RecursionCheck rc(compiler); 2839 RecursionCheck rc(compiler);
2752 2840
2753 GenerationVariant* current_variant = variant; 2841 Trace* current_trace = trace;
2754 2842
2755 int text_length = GreedyLoopTextLength(&(alternatives_->at(0))); 2843 int text_length = GreedyLoopTextLength(&(alternatives_->at(0)));
2756 bool greedy_loop = false; 2844 bool greedy_loop = false;
2757 Label greedy_loop_label; 2845 Label greedy_loop_label;
2758 GenerationVariant counter_backtrack_variant; 2846 Trace counter_backtrack_trace;
2759 counter_backtrack_variant.set_backtrack(&greedy_loop_label); 2847 counter_backtrack_trace.set_backtrack(&greedy_loop_label);
2760 if (choice_count > 1 && text_length != kNodeIsTooComplexForGreedyLoops) { 2848 if (choice_count > 1 && text_length != kNodeIsTooComplexForGreedyLoops) {
2761 // Here we have special handling for greedy loops containing only text nodes 2849 // Here we have special handling for greedy loops containing only text nodes
2762 // and other simple nodes. These are handled by pushing the current 2850 // and other simple nodes. These are handled by pushing the current
2763 // position on the stack and then incrementing the current position each 2851 // position on the stack and then incrementing the current position each
2764 // time around the switch. On backtrack we decrement the current position 2852 // time around the switch. On backtrack we decrement the current position
2765 // and check it against the pushed value. This avoids pushing backtrack 2853 // and check it against the pushed value. This avoids pushing backtrack
2766 // information for each iteration of the loop, which could take up a lot of 2854 // information for each iteration of the loop, which could take up a lot of
2767 // space. 2855 // space.
2768 greedy_loop = true; 2856 greedy_loop = true;
2769 ASSERT(variant->stop_node() == NULL); 2857 ASSERT(trace->stop_node() == NULL);
2770 macro_assembler->PushCurrentPosition(); 2858 macro_assembler->PushCurrentPosition();
2771 current_variant = &counter_backtrack_variant; 2859 current_trace = &counter_backtrack_trace;
2772 Label greedy_match_failed; 2860 Label greedy_match_failed;
2773 GenerationVariant greedy_match_variant; 2861 Trace greedy_match_trace;
2774 greedy_match_variant.set_backtrack(&greedy_match_failed); 2862 greedy_match_trace.set_backtrack(&greedy_match_failed);
2775 Label loop_label; 2863 Label loop_label;
2776 macro_assembler->Bind(&loop_label); 2864 macro_assembler->Bind(&loop_label);
2777 greedy_match_variant.set_stop_node(this); 2865 greedy_match_trace.set_stop_node(this);
2778 greedy_match_variant.set_loop_label(&loop_label); 2866 greedy_match_trace.set_loop_label(&loop_label);
2779 bool ok = alternatives_->at(0).node()->Emit(compiler, 2867 bool ok = alternatives_->at(0).node()->Emit(compiler,
2780 &greedy_match_variant); 2868 &greedy_match_trace);
2781 macro_assembler->Bind(&greedy_match_failed); 2869 macro_assembler->Bind(&greedy_match_failed);
2782 if (!ok) { 2870 if (!ok) {
2783 greedy_loop_label.Unuse(); 2871 greedy_loop_label.Unuse();
2784 return false; 2872 return false;
2785 } 2873 }
2786 } 2874 }
2787 2875
2788 Label second_choice; // For use in greedy matches. 2876 Label second_choice; // For use in greedy matches.
2789 macro_assembler->Bind(&second_choice); 2877 macro_assembler->Bind(&second_choice);
2790 2878
2791 int first_normal_choice = greedy_loop ? 1 : 0; 2879 int first_normal_choice = greedy_loop ? 1 : 0;
2792 2880
2793 int preload_characters = CalculatePreloadCharacters(compiler); 2881 int preload_characters = CalculatePreloadCharacters(compiler);
2794 bool preload_is_current = 2882 bool preload_is_current =
2795 (current_variant->characters_preloaded() == preload_characters); 2883 (current_trace->characters_preloaded() == preload_characters);
2796 bool preload_has_checked_bounds = preload_is_current; 2884 bool preload_has_checked_bounds = preload_is_current;
2797 2885
2798 AlternativeGenerationList alt_gens(choice_count); 2886 AlternativeGenerationList alt_gens(choice_count);
2799 2887
2800 // For now we just call all choices one after the other. The idea ultimately 2888 // For now we just call all choices one after the other. The idea ultimately
2801 // is to use the Dispatch table to try only the relevant ones. 2889 // is to use the Dispatch table to try only the relevant ones.
2802 for (int i = first_normal_choice; i < choice_count; i++) { 2890 for (int i = first_normal_choice; i < choice_count; i++) {
2803 GuardedAlternative alternative = alternatives_->at(i); 2891 GuardedAlternative alternative = alternatives_->at(i);
2804 AlternativeGeneration* alt_gen(alt_gens.at(i)); 2892 AlternativeGeneration* alt_gen = alt_gens.at(i);
2805 alt_gen->quick_check_details.set_characters(preload_characters); 2893 alt_gen->quick_check_details.set_characters(preload_characters);
2806 ZoneList<Guard*>* guards = alternative.guards(); 2894 ZoneList<Guard*>* guards = alternative.guards();
2807 int guard_count = (guards == NULL) ? 0 : guards->length(); 2895 int guard_count = (guards == NULL) ? 0 : guards->length();
2808 GenerationVariant new_variant(*current_variant); 2896 Trace new_trace(*current_trace);
2809 new_variant.set_characters_preloaded(preload_is_current ? 2897 new_trace.set_characters_preloaded(preload_is_current ?
2810 preload_characters : 2898 preload_characters :
2811 0); 2899 0);
2812 if (preload_has_checked_bounds) { 2900 if (preload_has_checked_bounds) {
2813 new_variant.set_bound_checked_up_to(preload_characters); 2901 new_trace.set_bound_checked_up_to(preload_characters);
2814 } 2902 }
2815 new_variant.quick_check_performed()->Clear(); 2903 new_trace.quick_check_performed()->Clear();
2816 alt_gen->expects_preload = preload_is_current; 2904 alt_gen->expects_preload = preload_is_current;
2817 bool generate_full_check_inline = false; 2905 bool generate_full_check_inline = false;
2818 if (alternative.node()->EmitQuickCheck(compiler, 2906 if (alternative.node()->EmitQuickCheck(compiler,
2819 &new_variant, 2907 &new_trace,
2820 preload_has_checked_bounds, 2908 preload_has_checked_bounds,
2821 &alt_gen->possible_success, 2909 &alt_gen->possible_success,
2822 &alt_gen->quick_check_details, 2910 &alt_gen->quick_check_details,
2823 i < choice_count - 1)) { 2911 i < choice_count - 1)) {
2824 // Quick check was generated for this choice. 2912 // Quick check was generated for this choice.
2825 preload_is_current = true; 2913 preload_is_current = true;
2826 preload_has_checked_bounds = true; 2914 preload_has_checked_bounds = true;
2827 // On the last choice in the ChoiceNode we generated the quick 2915 // On the last choice in the ChoiceNode we generated the quick
2828 // check to fall through on possible success. So now we need to 2916 // check to fall through on possible success. So now we need to
2829 // generate the full check inline. 2917 // generate the full check inline.
2830 if (i == choice_count - 1) { 2918 if (i == choice_count - 1) {
2831 macro_assembler->Bind(&alt_gen->possible_success); 2919 macro_assembler->Bind(&alt_gen->possible_success);
2832 new_variant.set_quick_check_performed(&alt_gen->quick_check_details); 2920 new_trace.set_quick_check_performed(&alt_gen->quick_check_details);
2833 new_variant.set_characters_preloaded(preload_characters); 2921 new_trace.set_characters_preloaded(preload_characters);
2834 new_variant.set_bound_checked_up_to(preload_characters); 2922 new_trace.set_bound_checked_up_to(preload_characters);
2835 generate_full_check_inline = true; 2923 generate_full_check_inline = true;
2836 } 2924 }
2837 } else { 2925 } else {
2838 // No quick check was generated. Put the full code here. 2926 // No quick check was generated. Put the full code here.
2839 // If this is not the first choice then there could be slow checks from 2927 // If this is not the first choice then there could be slow checks from
2840 // previous cases that go here when they fail. There's no reason to 2928 // previous cases that go here when they fail. There's no reason to
2841 // insist that they preload characters since the slow check we are about 2929 // insist that they preload characters since the slow check we are about
2842 // to generate probably can't use it. 2930 // to generate probably can't use it.
2843 if (i != first_normal_choice) { 2931 if (i != first_normal_choice) {
2844 alt_gen->expects_preload = false; 2932 alt_gen->expects_preload = false;
2845 new_variant.set_characters_preloaded(0); 2933 new_trace.set_characters_preloaded(0);
2846 } 2934 }
2847 if (i < choice_count - 1) { 2935 if (i < choice_count - 1) {
2848 new_variant.set_backtrack(&alt_gen->after); 2936 new_trace.set_backtrack(&alt_gen->after);
2849 } 2937 }
2850 generate_full_check_inline = true; 2938 generate_full_check_inline = true;
2851 } 2939 }
2852 if (generate_full_check_inline) { 2940 if (generate_full_check_inline) {
2853 for (int j = 0; j < guard_count; j++) { 2941 for (int j = 0; j < guard_count; j++) {
2854 GenerateGuard(macro_assembler, guards->at(j), &new_variant); 2942 GenerateGuard(macro_assembler, guards->at(j), &new_trace);
2855 } 2943 }
2856 if (!alternative.node()->Emit(compiler, &new_variant)) { 2944 if (!alternative.node()->Emit(compiler, &new_trace)) {
2857 greedy_loop_label.Unuse(); 2945 greedy_loop_label.Unuse();
2858 return false; 2946 return false;
2859 } 2947 }
2860 preload_is_current = false; 2948 preload_is_current = false;
2861 } 2949 }
2862 macro_assembler->Bind(&alt_gen->after); 2950 macro_assembler->Bind(&alt_gen->after);
2863 } 2951 }
2864 if (greedy_loop) { 2952 if (greedy_loop) {
2865 macro_assembler->Bind(&greedy_loop_label); 2953 macro_assembler->Bind(&greedy_loop_label);
2866 // If we have unwound to the bottom then backtrack. 2954 // If we have unwound to the bottom then backtrack.
2867 macro_assembler->CheckGreedyLoop(variant->backtrack()); 2955 macro_assembler->CheckGreedyLoop(trace->backtrack());
2868 // Otherwise try the second priority at an earlier position. 2956 // Otherwise try the second priority at an earlier position.
2869 macro_assembler->AdvanceCurrentPosition(-text_length); 2957 macro_assembler->AdvanceCurrentPosition(-text_length);
2870 macro_assembler->GoTo(&second_choice); 2958 macro_assembler->GoTo(&second_choice);
2871 } 2959 }
2872 // At this point we need to generate slow checks for the alternatives where 2960 // At this point we need to generate slow checks for the alternatives where
2873 // the quick check was inlined. We can recognize these because the associated 2961 // the quick check was inlined. We can recognize these because the associated
2874 // label was bound. 2962 // label was bound.
2875 for (int i = first_normal_choice; i < choice_count - 1; i++) { 2963 for (int i = first_normal_choice; i < choice_count - 1; i++) {
2876 AlternativeGeneration* alt_gen = alt_gens.at(i); 2964 AlternativeGeneration* alt_gen = alt_gens.at(i);
2877 if (!EmitOutOfLineContinuation(compiler, 2965 if (!EmitOutOfLineContinuation(compiler,
2878 current_variant, 2966 current_trace,
2879 alternatives_->at(i), 2967 alternatives_->at(i),
2880 alt_gen, 2968 alt_gen,
2881 preload_characters, 2969 preload_characters,
2882 alt_gens.at(i + 1)->expects_preload)) { 2970 alt_gens.at(i + 1)->expects_preload)) {
2883 return false; 2971 return false;
2884 } 2972 }
2885 } 2973 }
2886 return true; 2974 return true;
2887 } 2975 }
2888 2976
2889 2977
2890 bool ChoiceNode::EmitOutOfLineContinuation(RegExpCompiler* compiler, 2978 bool ChoiceNode::EmitOutOfLineContinuation(RegExpCompiler* compiler,
2891 GenerationVariant* variant, 2979 Trace* trace,
2892 GuardedAlternative alternative, 2980 GuardedAlternative alternative,
2893 AlternativeGeneration* alt_gen, 2981 AlternativeGeneration* alt_gen,
2894 int preload_characters, 2982 int preload_characters,
2895 bool next_expects_preload) { 2983 bool next_expects_preload) {
2896 if (!alt_gen->possible_success.is_linked()) return true; 2984 if (!alt_gen->possible_success.is_linked()) return true;
2897 2985
2898 RegExpMacroAssembler* macro_assembler = compiler->macro_assembler(); 2986 RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
2899 macro_assembler->Bind(&alt_gen->possible_success); 2987 macro_assembler->Bind(&alt_gen->possible_success);
2900 GenerationVariant out_of_line_variant(*variant); 2988 Trace out_of_line_trace(*trace);
2901 out_of_line_variant.set_characters_preloaded(preload_characters); 2989 out_of_line_trace.set_characters_preloaded(preload_characters);
2902 out_of_line_variant.set_quick_check_performed(&alt_gen->quick_check_details); 2990 out_of_line_trace.set_quick_check_performed(&alt_gen->quick_check_details);
2903 ZoneList<Guard*>* guards = alternative.guards(); 2991 ZoneList<Guard*>* guards = alternative.guards();
2904 int guard_count = (guards == NULL) ? 0 : guards->length(); 2992 int guard_count = (guards == NULL) ? 0 : guards->length();
2905 if (next_expects_preload) { 2993 if (next_expects_preload) {
2906 Label reload_current_char; 2994 Label reload_current_char;
2907 out_of_line_variant.set_backtrack(&reload_current_char); 2995 out_of_line_trace.set_backtrack(&reload_current_char);
2908 for (int j = 0; j < guard_count; j++) { 2996 for (int j = 0; j < guard_count; j++) {
2909 GenerateGuard(macro_assembler, guards->at(j), &out_of_line_variant); 2997 GenerateGuard(macro_assembler, guards->at(j), &out_of_line_trace);
2910 } 2998 }
2911 bool ok = alternative.node()->Emit(compiler, &out_of_line_variant); 2999 bool ok = alternative.node()->Emit(compiler, &out_of_line_trace);
2912 macro_assembler->Bind(&reload_current_char); 3000 macro_assembler->Bind(&reload_current_char);
2913 // Reload the current character, since the next quick check expects that. 3001 // Reload the current character, since the next quick check expects that.
2914 // We don't need to check bounds here because we only get into this 3002 // We don't need to check bounds here because we only get into this
2915 // code through a quick check which already did the checked load. 3003 // code through a quick check which already did the checked load.
2916 macro_assembler->LoadCurrentCharacter(variant->cp_offset(), 3004 macro_assembler->LoadCurrentCharacter(trace->cp_offset(),
2917 NULL, 3005 NULL,
2918 false, 3006 false,
2919 preload_characters); 3007 preload_characters);
2920 macro_assembler->GoTo(&(alt_gen->after)); 3008 macro_assembler->GoTo(&(alt_gen->after));
2921 return ok; 3009 return ok;
2922 } else { 3010 } else {
2923 out_of_line_variant.set_backtrack(&(alt_gen->after)); 3011 out_of_line_trace.set_backtrack(&(alt_gen->after));
2924 for (int j = 0; j < guard_count; j++) { 3012 for (int j = 0; j < guard_count; j++) {
2925 GenerateGuard(macro_assembler, guards->at(j), &out_of_line_variant); 3013 GenerateGuard(macro_assembler, guards->at(j), &out_of_line_trace);
2926 } 3014 }
2927 return alternative.node()->Emit(compiler, &out_of_line_variant); 3015 return alternative.node()->Emit(compiler, &out_of_line_trace);
2928 } 3016 }
2929 } 3017 }
2930 3018
2931 3019
2932 bool ActionNode::Emit(RegExpCompiler* compiler, GenerationVariant* variant) { 3020 bool ActionNode::Emit(RegExpCompiler* compiler, Trace* trace) {
2933 RegExpMacroAssembler* assembler = compiler->macro_assembler(); 3021 RegExpMacroAssembler* assembler = compiler->macro_assembler();
2934 LimitResult limit_result = LimitVersions(compiler, variant); 3022 LimitResult limit_result = LimitVersions(compiler, trace);
2935 if (limit_result == DONE) return true; 3023 if (limit_result == DONE) return true;
2936 if (limit_result == FAIL) return false; 3024 if (limit_result == FAIL) return false;
2937 ASSERT(limit_result == CONTINUE); 3025 ASSERT(limit_result == CONTINUE);
2938 3026
2939 RecursionCheck rc(compiler); 3027 RecursionCheck rc(compiler);
2940 3028
2941 switch (type_) { 3029 switch (type_) {
2942 case STORE_POSITION: { 3030 case STORE_POSITION: {
2943 GenerationVariant::DeferredCapture 3031 Trace::DeferredCapture
2944 new_capture(data_.u_position_register.reg, variant); 3032 new_capture(data_.u_position_register.reg, trace);
2945 GenerationVariant new_variant = *variant; 3033 Trace new_trace = *trace;
2946 new_variant.add_action(&new_capture); 3034 new_trace.add_action(&new_capture);
2947 return on_success()->Emit(compiler, &new_variant); 3035 return on_success()->Emit(compiler, &new_trace);
2948 } 3036 }
2949 case INCREMENT_REGISTER: { 3037 case INCREMENT_REGISTER: {
2950 GenerationVariant::DeferredIncrementRegister 3038 Trace::DeferredIncrementRegister
2951 new_increment(data_.u_increment_register.reg); 3039 new_increment(data_.u_increment_register.reg);
2952 GenerationVariant new_variant = *variant; 3040 Trace new_trace = *trace;
2953 new_variant.add_action(&new_increment); 3041 new_trace.add_action(&new_increment);
2954 return on_success()->Emit(compiler, &new_variant); 3042 return on_success()->Emit(compiler, &new_trace);
2955 } 3043 }
2956 case SET_REGISTER: { 3044 case SET_REGISTER: {
2957 GenerationVariant::DeferredSetRegister 3045 Trace::DeferredSetRegister
2958 new_set(data_.u_store_register.reg, data_.u_store_register.value); 3046 new_set(data_.u_store_register.reg, data_.u_store_register.value);
2959 GenerationVariant new_variant = *variant; 3047 Trace new_trace = *trace;
2960 new_variant.add_action(&new_set); 3048 new_trace.add_action(&new_set);
2961 return on_success()->Emit(compiler, &new_variant); 3049 return on_success()->Emit(compiler, &new_trace);
3050 }
3051 case CLEAR_CAPTURES: {
3052 Trace::DeferredClearCaptures
3053 new_capture(Interval(data_.u_clear_captures.range_from,
3054 data_.u_clear_captures.range_to));
3055 Trace new_trace = *trace;
3056 new_trace.add_action(&new_capture);
3057 return on_success()->Emit(compiler, &new_trace);
2962 } 3058 }
2963 case BEGIN_SUBMATCH: 3059 case BEGIN_SUBMATCH:
2964 if (!variant->is_trivial()) return variant->Flush(compiler, this); 3060 if (!trace->is_trivial()) return trace->Flush(compiler, this);
2965 assembler->WriteCurrentPositionToRegister( 3061 assembler->WriteCurrentPositionToRegister(
2966 data_.u_submatch.current_position_register, 0); 3062 data_.u_submatch.current_position_register, 0);
2967 assembler->WriteStackPointerToRegister( 3063 assembler->WriteStackPointerToRegister(
2968 data_.u_submatch.stack_pointer_register); 3064 data_.u_submatch.stack_pointer_register);
2969 return on_success()->Emit(compiler, variant); 3065 return on_success()->Emit(compiler, trace);
3066 case EMPTY_MATCH_CHECK: {
3067 int start_pos_reg = data_.u_empty_match_check.start_register;
3068 int stored_pos = 0;
3069 int rep_reg = data_.u_empty_match_check.repetition_register;
3070 bool has_minimum = (rep_reg != RegExpCompiler::kNoRegister);
3071 bool know_dist = trace->GetStoredPosition(start_pos_reg, &stored_pos);
3072 if (know_dist && !has_minimum && stored_pos == trace->cp_offset()) {
3073 // If we know we haven't advanced and there is no minimum we
3074 // can just backtrack immediately.
3075 assembler->GoTo(trace->backtrack());
3076 return true;
3077 } else if (know_dist && stored_pos < trace->cp_offset()) {
3078 // If we know we've advanced we can generate the continuation
3079 // immediately.
3080 return on_success()->Emit(compiler, trace);
3081 }
3082 if (!trace->is_trivial()) return trace->Flush(compiler, this);
3083 Label skip_empty_check;
3084 // If we have a minimum number of repetitions we check the current
3085 // number first and skip the empty check if it's not enough.
3086 if (has_minimum) {
3087 int limit = data_.u_empty_match_check.repetition_limit;
3088 assembler->IfRegisterLT(rep_reg, limit, &skip_empty_check);
3089 }
3090 // If the match is empty we bail out, otherwise we fall through
3091 // to the on-success continuation.
3092 assembler->IfRegisterEqPos(data_.u_empty_match_check.start_register,
3093 trace->backtrack());
3094 assembler->Bind(&skip_empty_check);
3095 return on_success()->Emit(compiler, trace);
3096 }
2970 case POSITIVE_SUBMATCH_SUCCESS: 3097 case POSITIVE_SUBMATCH_SUCCESS:
2971 if (!variant->is_trivial()) return variant->Flush(compiler, this); 3098 if (!trace->is_trivial()) return trace->Flush(compiler, this);
2972 // TODO(erikcorry): Implement support. 3099 // TODO(erikcorry): Implement support.
2973 if (info()->follows_word_interest || 3100 if (info()->follows_word_interest ||
2974 info()->follows_newline_interest || 3101 info()->follows_newline_interest ||
2975 info()->follows_start_interest) { 3102 info()->follows_start_interest) {
2976 return false; 3103 return false;
2977 } 3104 }
2978 if (info()->at_end) { 3105 if (info()->at_end) {
2979 Label at_end; 3106 Label at_end;
2980 // Load current character jumps to the label if we are beyond the string 3107 // Load current character jumps to the label if we are beyond the string
2981 // end. 3108 // end.
2982 assembler->LoadCurrentCharacter(0, &at_end); 3109 assembler->LoadCurrentCharacter(0, &at_end);
2983 assembler->GoTo(variant->backtrack()); 3110 assembler->GoTo(trace->backtrack());
2984 assembler->Bind(&at_end); 3111 assembler->Bind(&at_end);
2985 } 3112 }
2986 assembler->ReadCurrentPositionFromRegister( 3113 assembler->ReadCurrentPositionFromRegister(
2987 data_.u_submatch.current_position_register); 3114 data_.u_submatch.current_position_register);
2988 assembler->ReadStackPointerFromRegister( 3115 assembler->ReadStackPointerFromRegister(
2989 data_.u_submatch.stack_pointer_register); 3116 data_.u_submatch.stack_pointer_register);
2990 return on_success()->Emit(compiler, variant); 3117 return on_success()->Emit(compiler, trace);
2991 default: 3118 default:
2992 UNREACHABLE(); 3119 UNREACHABLE();
2993 return false; 3120 return false;
2994 } 3121 }
2995 } 3122 }
2996 3123
2997 3124
2998 bool BackReferenceNode::Emit(RegExpCompiler* compiler, 3125 bool BackReferenceNode::Emit(RegExpCompiler* compiler, Trace* trace) {
2999 GenerationVariant* variant) {
3000 RegExpMacroAssembler* assembler = compiler->macro_assembler(); 3126 RegExpMacroAssembler* assembler = compiler->macro_assembler();
3001 if (!variant->is_trivial()) { 3127 if (!trace->is_trivial()) {
3002 return variant->Flush(compiler, this); 3128 return trace->Flush(compiler, this);
3003 } 3129 }
3004 3130
3005 LimitResult limit_result = LimitVersions(compiler, variant); 3131 LimitResult limit_result = LimitVersions(compiler, trace);
3006 if (limit_result == DONE) return true; 3132 if (limit_result == DONE) return true;
3007 if (limit_result == FAIL) return false; 3133 if (limit_result == FAIL) return false;
3008 ASSERT(limit_result == CONTINUE); 3134 ASSERT(limit_result == CONTINUE);
3009 3135
3010 RecursionCheck rc(compiler); 3136 RecursionCheck rc(compiler);
3011 3137
3012 ASSERT_EQ(start_reg_ + 1, end_reg_); 3138 ASSERT_EQ(start_reg_ + 1, end_reg_);
3013 if (info()->at_end) { 3139 if (info()->at_end) {
3014 // If we are constrained to match at the end of the input then succeed 3140 // If we are constrained to match at the end of the input then succeed
3015 // iff the back reference is empty. 3141 // iff the back reference is empty.
3016 assembler->CheckNotRegistersEqual(start_reg_, 3142 assembler->CheckNotRegistersEqual(start_reg_,
3017 end_reg_, 3143 end_reg_,
3018 variant->backtrack()); 3144 trace->backtrack());
3019 } else { 3145 } else {
3020 if (compiler->ignore_case()) { 3146 if (compiler->ignore_case()) {
3021 assembler->CheckNotBackReferenceIgnoreCase(start_reg_, 3147 assembler->CheckNotBackReferenceIgnoreCase(start_reg_,
3022 variant->backtrack()); 3148 trace->backtrack());
3023 } else { 3149 } else {
3024 assembler->CheckNotBackReference(start_reg_, variant->backtrack()); 3150 assembler->CheckNotBackReference(start_reg_, trace->backtrack());
3025 } 3151 }
3026 } 3152 }
3027 return on_success()->Emit(compiler, variant); 3153 return on_success()->Emit(compiler, trace);
3028 } 3154 }
3029 3155
3030 3156
3031 // ------------------------------------------------------------------- 3157 // -------------------------------------------------------------------
3032 // Dot/dotty output 3158 // Dot/dotty output
3033 3159
3034 3160
3035 #ifdef DEBUG 3161 #ifdef DEBUG
3036 3162
3037 3163
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after
3279 stream()->Add("label=\"$%i:=$pos\", shape=octagon", 3405 stream()->Add("label=\"$%i:=$pos\", shape=octagon",
3280 that->data_.u_position_register.reg); 3406 that->data_.u_position_register.reg);
3281 break; 3407 break;
3282 case ActionNode::BEGIN_SUBMATCH: 3408 case ActionNode::BEGIN_SUBMATCH:
3283 stream()->Add("label=\"$%i:=$pos,begin\", shape=septagon", 3409 stream()->Add("label=\"$%i:=$pos,begin\", shape=septagon",
3284 that->data_.u_submatch.current_position_register); 3410 that->data_.u_submatch.current_position_register);
3285 break; 3411 break;
3286 case ActionNode::POSITIVE_SUBMATCH_SUCCESS: 3412 case ActionNode::POSITIVE_SUBMATCH_SUCCESS:
3287 stream()->Add("label=\"escape\", shape=septagon"); 3413 stream()->Add("label=\"escape\", shape=septagon");
3288 break; 3414 break;
3415 case ActionNode::EMPTY_MATCH_CHECK:
3416 stream()->Add("label=\"$%i=$pos?,$%i<%i?\", shape=septagon",
3417 that->data_.u_empty_match_check.start_register,
3418 that->data_.u_empty_match_check.repetition_register,
3419 that->data_.u_empty_match_check.repetition_limit);
3420 break;
3421 case ActionNode::CLEAR_CAPTURES: {
3422 stream()->Add("label=\"clear $%i to $%i\", shape=septagon",
3423 that->data_.u_clear_captures.range_from,
3424 that->data_.u_clear_captures.range_to);
3425 break;
3426 }
3289 } 3427 }
3290 stream()->Add("];\n"); 3428 stream()->Add("];\n");
3291 PrintAttributes(that); 3429 PrintAttributes(that);
3292 RegExpNode* successor = that->on_success(); 3430 RegExpNode* successor = that->on_success();
3293 stream()->Add(" n%p -> n%p;\n", that, successor); 3431 stream()->Add(" n%p -> n%p;\n", that, successor);
3294 Visit(successor); 3432 Visit(successor);
3295 } 3433 }
3296 3434
3297 3435
3298 class DispatchTableDumper { 3436 class DispatchTableDumper {
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after
3504 // where max_match is zero the parser has removed the quantifier if min was 3642 // where max_match is zero the parser has removed the quantifier if min was
3505 // > 0 and removed the atom if min was 0. See AddQuantifierToAtom. 3643 // > 0 and removed the atom if min was 0. See AddQuantifierToAtom.
3506 3644
3507 // If we know that we cannot match zero length then things are a little 3645 // If we know that we cannot match zero length then things are a little
3508 // simpler since we don't need to make the special zero length match check 3646 // simpler since we don't need to make the special zero length match check
3509 // from step 2.1. If the min and max are small we can unroll a little in 3647 // from step 2.1. If the min and max are small we can unroll a little in
3510 // this case. 3648 // this case.
3511 static const int kMaxUnrolledMinMatches = 3; // Unroll (foo)+ and (foo){3,} 3649 static const int kMaxUnrolledMinMatches = 3; // Unroll (foo)+ and (foo){3,}
3512 static const int kMaxUnrolledMaxMatches = 3; // Unroll (foo)? and (foo){x,3} 3650 static const int kMaxUnrolledMaxMatches = 3; // Unroll (foo)? and (foo){x,3}
3513 if (max == 0) return on_success; // This can happen due to recursion. 3651 if (max == 0) return on_success; // This can happen due to recursion.
3514 if (body->min_match() > 0) { 3652 bool body_can_be_empty = (body->min_match() == 0);
3653 int body_start_reg = RegExpCompiler::kNoRegister;
3654 Interval capture_registers = body->CaptureRegisters();
3655 bool needs_capture_clearing = !capture_registers.is_empty();
3656 if (body_can_be_empty) {
3657 body_start_reg = compiler->AllocateRegister();
3658 } else if (!needs_capture_clearing) {
3659 // Only unroll if there are no captures and the body can't be
3660 // empty.
3515 if (min > 0 && min <= kMaxUnrolledMinMatches) { 3661 if (min > 0 && min <= kMaxUnrolledMinMatches) {
3516 int new_max = (max == kInfinity) ? max : max - min; 3662 int new_max = (max == kInfinity) ? max : max - min;
3517 // Recurse once to get the loop or optional matches after the fixed ones. 3663 // Recurse once to get the loop or optional matches after the fixed ones.
3518 RegExpNode* answer = 3664 RegExpNode* answer =
3519 ToNode(0, new_max, is_greedy, body, compiler, on_success); 3665 ToNode(0, new_max, is_greedy, body, compiler, on_success);
3520 // Unroll the forced matches from 0 to min. This can cause chains of 3666 // Unroll the forced matches from 0 to min. This can cause chains of
3521 // TextNodes (which the parser does not generate). These should be 3667 // TextNodes (which the parser does not generate). These should be
3522 // combined if it turns out they hinder good code generation. 3668 // combined if it turns out they hinder good code generation.
3523 for (int i = 0; i < min; i++) { 3669 for (int i = 0; i < min; i++) {
3524 answer = body->ToNode(compiler, answer); 3670 answer = body->ToNode(compiler, answer);
(...skipping 16 matching lines...) Expand all
3541 answer))); 3687 answer)));
3542 } 3688 }
3543 answer = alternation; 3689 answer = alternation;
3544 } 3690 }
3545 return answer; 3691 return answer;
3546 } 3692 }
3547 } 3693 }
3548 bool has_min = min > 0; 3694 bool has_min = min > 0;
3549 bool has_max = max < RegExpTree::kInfinity; 3695 bool has_max = max < RegExpTree::kInfinity;
3550 bool needs_counter = has_min || has_max; 3696 bool needs_counter = has_min || has_max;
3551 int reg_ctr = needs_counter ? compiler->AllocateRegister() : -1; 3697 int reg_ctr = needs_counter
3698 ? compiler->AllocateRegister()
3699 : RegExpCompiler::kNoRegister;
3552 LoopChoiceNode* center = new LoopChoiceNode(body->min_match() == 0); 3700 LoopChoiceNode* center = new LoopChoiceNode(body->min_match() == 0);
3553 RegExpNode* loop_return = needs_counter 3701 RegExpNode* loop_return = needs_counter
3554 ? static_cast<RegExpNode*>(ActionNode::IncrementRegister(reg_ctr, center)) 3702 ? static_cast<RegExpNode*>(ActionNode::IncrementRegister(reg_ctr, center))
3555 : static_cast<RegExpNode*>(center); 3703 : static_cast<RegExpNode*>(center);
3704 if (body_can_be_empty) {
3705 // If the body can be empty we need to check if it was and then
3706 // backtrack.
3707 loop_return = ActionNode::EmptyMatchCheck(body_start_reg,
3708 reg_ctr,
3709 min,
3710 loop_return);
3711 }
3556 RegExpNode* body_node = body->ToNode(compiler, loop_return); 3712 RegExpNode* body_node = body->ToNode(compiler, loop_return);
3713 if (body_can_be_empty) {
3714 // If the body can be empty we need to store the start position
3715 // so we can bail out if it was empty.
3716 body_node = ActionNode::StorePosition(body_start_reg, body_node);
3717 }
3718 if (needs_capture_clearing) {
3719 // Before entering the body of this loop we need to clear captures.
3720 body_node = ActionNode::ClearCaptures(capture_registers, body_node);
3721 }
3557 GuardedAlternative body_alt(body_node); 3722 GuardedAlternative body_alt(body_node);
3558 if (has_max) { 3723 if (has_max) {
3559 Guard* body_guard = new Guard(reg_ctr, Guard::LT, max); 3724 Guard* body_guard = new Guard(reg_ctr, Guard::LT, max);
3560 body_alt.AddGuard(body_guard); 3725 body_alt.AddGuard(body_guard);
3561 } 3726 }
3562 GuardedAlternative rest_alt(on_success); 3727 GuardedAlternative rest_alt(on_success);
3563 if (has_min) { 3728 if (has_min) {
3564 Guard* rest_guard = new Guard(reg_ctr, Guard::GEQ, min); 3729 Guard* rest_guard = new Guard(reg_ctr, Guard::GEQ, min);
3565 rest_alt.AddGuard(rest_guard); 3730 rest_alt.AddGuard(rest_guard);
3566 } 3731 }
(...skipping 820 matching lines...) Expand 10 before | Expand all | Expand 10 after
4387 EmbeddedVector<byte, 1024> codes; 4552 EmbeddedVector<byte, 1024> codes;
4388 RegExpMacroAssemblerIrregexp macro_assembler(codes); 4553 RegExpMacroAssemblerIrregexp macro_assembler(codes);
4389 return compiler.Assemble(&macro_assembler, 4554 return compiler.Assemble(&macro_assembler,
4390 node, 4555 node,
4391 data->capture_count, 4556 data->capture_count,
4392 pattern); 4557 pattern);
4393 } 4558 }
4394 4559
4395 4560
4396 }} // namespace v8::internal 4561 }} // namespace v8::internal
OLDNEW
« no previous file with comments | « src/jsregexp.h ('k') | src/log.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698