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

Side by Side Diff: src/jsregexp.cc

Issue 18091: Noone really liked the name "GenerationVariant" so here it gets renamed... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
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') | no next file » | 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 1092 matching lines...) Expand 10 before | Expand all | Expand 10 after
1103 // space. 1103 // space.
1104 // * The current state is virtualized. 1104 // * The current state is virtualized.
1105 // 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
1106 // 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
1107 // 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
1108 // explained in the section below. 1108 // explained in the section below.
1109 // 1109 //
1110 // Execution state virtualization. 1110 // Execution state virtualization.
1111 // 1111 //
1112 // 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
1113 // manipulation in an object called the GenerationVariant. The 1113 // manipulation in an object called the Trace. The Trace object can record a
1114 // GenerationVariant object can record a current position offset, an 1114 // current position offset, an optional backtrack code location on the top of
1115 // optional backtrack code location on the top of the virtualized backtrack 1115 // the virtualized backtrack stack and some register changes. When a node is
1116 // 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
1117 // the GenerationVariant or update it. Flushing the GenerationVariant
1118 // 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.
1119 // 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
1120 // registers). Postponing work can save time when executing the regular 1119 // registers). Postponing work can save time when executing the regular
1121 // 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
1122 // 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
1123 // 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
1124 // location from the stack and jump there. 1123 // location from the stack and jump there.
1125 // 1124 //
1126 // The virtual state found in the GenerationVariant affects code generation. 1125 // The virtual state found in the Trace affects code generation. For example
1127 // For example the virtual state contains the difference between the actual 1126 // the virtual state contains the difference between the actual current
1128 // current position and the virtual current position, and matching code needs 1127 // position and the virtual current position, and matching code needs to use
1129 // 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
1130 // string. Therefore code generated for a non-trivial GenerationVariant is 1129 // string. Therefore code generated for a non-trivial trace is specialized
1131 // specialized to that GenerationVariant. The code generator therefore 1130 // to that trace. The code generator therefore has the ability to generate
1132 // 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
1133 // 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
1134 // 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
1135 // 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.
1136 // 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
1137 // 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
1138 // 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.
1139 // is requested for an identical GenerationVariant.
1140 1138
1141 1139
1142 void RegExpTree::AppendToText(RegExpText* text) { 1140 void RegExpTree::AppendToText(RegExpText* text) {
1143 UNREACHABLE(); 1141 UNREACHABLE();
1144 } 1142 }
1145 1143
1146 1144
1147 void RegExpAtom::AppendToText(RegExpText* text) { 1145 void RegExpAtom::AppendToText(RegExpText* text) {
1148 text->AddElement(TextElement::Atom(this)); 1146 text->AddElement(TextElement::Atom(this));
1149 } 1147 }
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
1266 #ifdef DEBUG 1264 #ifdef DEBUG
1267 if (FLAG_trace_regexp_assembler) 1265 if (FLAG_trace_regexp_assembler)
1268 macro_assembler_ = new RegExpMacroAssemblerTracer(macro_assembler); 1266 macro_assembler_ = new RegExpMacroAssemblerTracer(macro_assembler);
1269 else 1267 else
1270 #endif 1268 #endif
1271 macro_assembler_ = macro_assembler; 1269 macro_assembler_ = macro_assembler;
1272 List <RegExpNode*> work_list(0); 1270 List <RegExpNode*> work_list(0);
1273 work_list_ = &work_list; 1271 work_list_ = &work_list;
1274 Label fail; 1272 Label fail;
1275 macro_assembler->PushBacktrack(&fail); 1273 macro_assembler->PushBacktrack(&fail);
1276 GenerationVariant generic_variant; 1274 Trace new_trace;
1277 if (!start->Emit(this, &generic_variant)) { 1275 if (!start->Emit(this, &new_trace)) {
1278 fail.Unuse(); 1276 fail.Unuse();
1279 return Handle<FixedArray>::null(); 1277 return Handle<FixedArray>::null();
1280 } 1278 }
1281 macro_assembler_->Bind(&fail); 1279 macro_assembler_->Bind(&fail);
1282 macro_assembler_->Fail(); 1280 macro_assembler_->Fail();
1283 while (!work_list.is_empty()) { 1281 while (!work_list.is_empty()) {
1284 if (!work_list.RemoveLast()->Emit(this, &generic_variant)) { 1282 if (!work_list.RemoveLast()->Emit(this, &new_trace)) {
1285 return Handle<FixedArray>::null(); 1283 return Handle<FixedArray>::null();
1286 } 1284 }
1287 } 1285 }
1288 Handle<FixedArray> array = 1286 Handle<FixedArray> array =
1289 Factory::NewFixedArray(RegExpImpl::kIrregexpDataLength); 1287 Factory::NewFixedArray(RegExpImpl::kIrregexpDataLength);
1290 array->set(RegExpImpl::kIrregexpImplementationIndex, 1288 array->set(RegExpImpl::kIrregexpImplementationIndex,
1291 Smi::FromInt(macro_assembler_->Implementation())); 1289 Smi::FromInt(macro_assembler_->Implementation()));
1292 array->set(RegExpImpl::kIrregexpNumberOfRegistersIndex, 1290 array->set(RegExpImpl::kIrregexpNumberOfRegistersIndex,
1293 Smi::FromInt(next_register_)); 1291 Smi::FromInt(next_register_));
1294 array->set(RegExpImpl::kIrregexpNumberOfCapturesIndex, 1292 array->set(RegExpImpl::kIrregexpNumberOfCapturesIndex,
1295 Smi::FromInt(capture_count)); 1293 Smi::FromInt(capture_count));
1296 Handle<Object> code = macro_assembler_->GetCode(pattern); 1294 Handle<Object> code = macro_assembler_->GetCode(pattern);
1297 array->set(RegExpImpl::kIrregexpCodeIndex, *code); 1295 array->set(RegExpImpl::kIrregexpCodeIndex, *code);
1298 work_list_ = NULL; 1296 work_list_ = NULL;
1299 #ifdef DEBUG 1297 #ifdef DEBUG
1300 if (FLAG_trace_regexp_assembler) { 1298 if (FLAG_trace_regexp_assembler) {
1301 delete macro_assembler_; 1299 delete macro_assembler_;
1302 } 1300 }
1303 #endif 1301 #endif
1304 return array; 1302 return array;
1305 } 1303 }
1306 1304
1307 bool GenerationVariant::DeferredAction::Mentions(int that) { 1305 bool Trace::DeferredAction::Mentions(int that) {
1308 if (type() == ActionNode::CLEAR_CAPTURES) { 1306 if (type() == ActionNode::CLEAR_CAPTURES) {
1309 Interval range = static_cast<DeferredClearCaptures*>(this)->range(); 1307 Interval range = static_cast<DeferredClearCaptures*>(this)->range();
1310 return range.Contains(that); 1308 return range.Contains(that);
1311 } else { 1309 } else {
1312 return reg() == that; 1310 return reg() == that;
1313 } 1311 }
1314 } 1312 }
1315 1313
1316 1314
1317 bool GenerationVariant::mentions_reg(int reg) { 1315 bool Trace::mentions_reg(int reg) {
1318 for (DeferredAction* action = actions_; 1316 for (DeferredAction* action = actions_;
1319 action != NULL; 1317 action != NULL;
1320 action = action->next()) { 1318 action = action->next()) {
1321 if (action->Mentions(reg)) 1319 if (action->Mentions(reg))
1322 return true; 1320 return true;
1323 } 1321 }
1324 return false; 1322 return false;
1325 } 1323 }
1326 1324
1327 1325
1328 bool GenerationVariant::GetStoredPosition(int reg, int* cp_offset) { 1326 bool Trace::GetStoredPosition(int reg, int* cp_offset) {
1329 ASSERT_EQ(0, *cp_offset); 1327 ASSERT_EQ(0, *cp_offset);
1330 for (DeferredAction* action = actions_; 1328 for (DeferredAction* action = actions_;
1331 action != NULL; 1329 action != NULL;
1332 action = action->next()) { 1330 action = action->next()) {
1333 if (action->Mentions(reg)) { 1331 if (action->Mentions(reg)) {
1334 if (action->type() == ActionNode::STORE_POSITION) { 1332 if (action->type() == ActionNode::STORE_POSITION) {
1335 *cp_offset = static_cast<DeferredCapture*>(action)->cp_offset(); 1333 *cp_offset = static_cast<DeferredCapture*>(action)->cp_offset();
1336 return true; 1334 return true;
1337 } else { 1335 } else {
1338 return false; 1336 return false;
1339 } 1337 }
1340 } 1338 }
1341 } 1339 }
1342 return false; 1340 return false;
1343 } 1341 }
1344 1342
1345 1343
1346 int GenerationVariant::FindAffectedRegisters(OutSet* affected_registers) { 1344 int Trace::FindAffectedRegisters(OutSet* affected_registers) {
1347 int max_register = RegExpCompiler::kNoRegister; 1345 int max_register = RegExpCompiler::kNoRegister;
1348 for (DeferredAction* action = actions_; 1346 for (DeferredAction* action = actions_;
1349 action != NULL; 1347 action != NULL;
1350 action = action->next()) { 1348 action = action->next()) {
1351 if (action->type() == ActionNode::CLEAR_CAPTURES) { 1349 if (action->type() == ActionNode::CLEAR_CAPTURES) {
1352 Interval range = static_cast<DeferredClearCaptures*>(action)->range(); 1350 Interval range = static_cast<DeferredClearCaptures*>(action)->range();
1353 for (int i = range.from(); i <= range.to(); i++) 1351 for (int i = range.from(); i <= range.to(); i++)
1354 affected_registers->Set(i); 1352 affected_registers->Set(i);
1355 if (range.to() > max_register) max_register = range.to(); 1353 if (range.to() > max_register) max_register = range.to();
1356 } else { 1354 } else {
1357 affected_registers->Set(action->reg()); 1355 affected_registers->Set(action->reg());
1358 if (action->reg() > max_register) max_register = action->reg(); 1356 if (action->reg() > max_register) max_register = action->reg();
1359 } 1357 }
1360 } 1358 }
1361 return max_register; 1359 return max_register;
1362 } 1360 }
1363 1361
1364 1362
1365 void GenerationVariant::PushAffectedRegisters(RegExpMacroAssembler* assembler, 1363 void Trace::PushAffectedRegisters(RegExpMacroAssembler* assembler,
1366 int max_register, 1364 int max_register,
1367 OutSet& affected_registers) { 1365 OutSet& affected_registers) {
1368 // Stay safe and check every half times the limit. 1366 // Stay safe and check every half times the limit.
1369 // (Round up in case the limit is 1). 1367 // (Round up in case the limit is 1).
1370 int push_limit = (assembler->stack_limit_slack() + 1) / 2; 1368 int push_limit = (assembler->stack_limit_slack() + 1) / 2;
1371 for (int reg = 0, pushes = 0; reg <= max_register; reg++) { 1369 for (int reg = 0, pushes = 0; reg <= max_register; reg++) {
1372 if (affected_registers.Get(reg)) { 1370 if (affected_registers.Get(reg)) {
1373 pushes++; 1371 pushes++;
1374 RegExpMacroAssembler::StackCheckFlag check_stack_limit = 1372 RegExpMacroAssembler::StackCheckFlag check_stack_limit =
1375 (pushes % push_limit) == 0 ? 1373 (pushes % push_limit) == 0 ?
1376 RegExpMacroAssembler::kCheckStackLimit : 1374 RegExpMacroAssembler::kCheckStackLimit :
1377 RegExpMacroAssembler::kNoStackLimitCheck; 1375 RegExpMacroAssembler::kNoStackLimitCheck;
1378 assembler->PushRegister(reg, check_stack_limit); 1376 assembler->PushRegister(reg, check_stack_limit);
1379 } 1377 }
1380 } 1378 }
1381 } 1379 }
1382 1380
1383 1381
1384 void GenerationVariant::RestoreAffectedRegisters( 1382 void Trace::RestoreAffectedRegisters(RegExpMacroAssembler* assembler,
1385 RegExpMacroAssembler* assembler, 1383 int max_register,
1386 int max_register, 1384 OutSet& affected_registers) {
1387 OutSet& affected_registers) {
1388 for (int reg = max_register; reg >= 0; reg--) { 1385 for (int reg = max_register; reg >= 0; reg--) {
1389 if (affected_registers.Get(reg)) assembler->PopRegister(reg); 1386 if (affected_registers.Get(reg)) assembler->PopRegister(reg);
1390 } 1387 }
1391 } 1388 }
1392 1389
1393 1390
1394 void GenerationVariant::PerformDeferredActions(RegExpMacroAssembler* assembler, 1391 void Trace::PerformDeferredActions(RegExpMacroAssembler* assembler,
1395 int max_register, 1392 int max_register,
1396 OutSet& affected_registers) { 1393 OutSet& affected_registers) {
1397 for (int reg = 0; reg <= max_register; reg++) { 1394 for (int reg = 0; reg <= max_register; reg++) {
1398 if (!affected_registers.Get(reg)) { 1395 if (!affected_registers.Get(reg)) {
1399 continue; 1396 continue;
1400 } 1397 }
1401 int value = 0; 1398 int value = 0;
1402 bool absolute = false; 1399 bool absolute = false;
1403 bool clear = false; 1400 bool clear = false;
1404 int store_position = -1; 1401 int store_position = -1;
1405 // 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
1406 // historical order (newest first). 1403 // historical order (newest first).
1407 for (DeferredAction* action = actions_; 1404 for (DeferredAction* action = actions_;
1408 action != NULL; 1405 action != NULL;
1409 action = action->next()) { 1406 action = action->next()) {
1410 if (action->Mentions(reg)) { 1407 if (action->Mentions(reg)) {
1411 switch (action->type()) { 1408 switch (action->type()) {
1412 case ActionNode::SET_REGISTER: { 1409 case ActionNode::SET_REGISTER: {
1413 GenerationVariant::DeferredSetRegister* psr = 1410 Trace::DeferredSetRegister* psr =
1414 static_cast<GenerationVariant::DeferredSetRegister*>(action); 1411 static_cast<Trace::DeferredSetRegister*>(action);
1415 value += psr->value(); 1412 value += psr->value();
1416 absolute = true; 1413 absolute = true;
1417 ASSERT_EQ(store_position, -1); 1414 ASSERT_EQ(store_position, -1);
1418 ASSERT(!clear); 1415 ASSERT(!clear);
1419 break; 1416 break;
1420 } 1417 }
1421 case ActionNode::INCREMENT_REGISTER: 1418 case ActionNode::INCREMENT_REGISTER:
1422 if (!absolute) { 1419 if (!absolute) {
1423 value++; 1420 value++;
1424 } 1421 }
1425 ASSERT_EQ(store_position, -1); 1422 ASSERT_EQ(store_position, -1);
1426 ASSERT(!clear); 1423 ASSERT(!clear);
1427 break; 1424 break;
1428 case ActionNode::STORE_POSITION: { 1425 case ActionNode::STORE_POSITION: {
1429 GenerationVariant::DeferredCapture* pc = 1426 Trace::DeferredCapture* pc =
1430 static_cast<GenerationVariant::DeferredCapture*>(action); 1427 static_cast<Trace::DeferredCapture*>(action);
1431 if (!clear && store_position == -1) { 1428 if (!clear && store_position == -1) {
1432 store_position = pc->cp_offset(); 1429 store_position = pc->cp_offset();
1433 } 1430 }
1434 ASSERT(!absolute); 1431 ASSERT(!absolute);
1435 ASSERT_EQ(value, 0); 1432 ASSERT_EQ(value, 0);
1436 break; 1433 break;
1437 } 1434 }
1438 case ActionNode::CLEAR_CAPTURES: { 1435 case ActionNode::CLEAR_CAPTURES: {
1439 // Since we're scanning in reverse order, if we've already 1436 // Since we're scanning in reverse order, if we've already
1440 // set the position we have to ignore historically earlier 1437 // set the position we have to ignore historically earlier
(...skipping 19 matching lines...) Expand all
1460 } else if (value != 0) { 1457 } else if (value != 0) {
1461 assembler->AdvanceRegister(reg, value); 1458 assembler->AdvanceRegister(reg, value);
1462 } 1459 }
1463 } 1460 }
1464 } 1461 }
1465 1462
1466 1463
1467 // 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
1468 // 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
1469 // generate generic code. 1466 // generate generic code.
1470 bool GenerationVariant::Flush(RegExpCompiler* compiler, RegExpNode* successor) { 1467 bool Trace::Flush(RegExpCompiler* compiler, RegExpNode* successor) {
1471 RegExpMacroAssembler* assembler = compiler->macro_assembler(); 1468 RegExpMacroAssembler* assembler = compiler->macro_assembler();
1472 1469
1473 ASSERT(actions_ != NULL || 1470 ASSERT(actions_ != NULL ||
1474 cp_offset_ != 0 || 1471 cp_offset_ != 0 ||
1475 backtrack() != NULL || 1472 backtrack() != NULL ||
1476 characters_preloaded_ != 0 || 1473 characters_preloaded_ != 0 ||
1477 quick_check_performed_.characters() != 0 || 1474 quick_check_performed_.characters() != 0 ||
1478 bound_checked_up_to_ != 0); 1475 bound_checked_up_to_ != 0);
1479 1476
1480 if (actions_ == NULL && backtrack() == NULL) { 1477 if (actions_ == NULL && backtrack() == NULL) {
1481 // 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
1482 // 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
1483 // through a quick check that was already performed. 1480 // through a quick check that was already performed.
1484 if (cp_offset_ != 0) assembler->AdvanceCurrentPosition(cp_offset_); 1481 if (cp_offset_ != 0) assembler->AdvanceCurrentPosition(cp_offset_);
1485 // Create a new trivial state and generate the node with that. 1482 // Create a new trivial state and generate the node with that.
1486 GenerationVariant new_state; 1483 Trace new_state;
1487 return successor->Emit(compiler, &new_state); 1484 return successor->Emit(compiler, &new_state);
1488 } 1485 }
1489 1486
1490 // Generate deferred actions here along with code to undo them again. 1487 // Generate deferred actions here along with code to undo them again.
1491 OutSet affected_registers; 1488 OutSet affected_registers;
1492 int max_register = FindAffectedRegisters(&affected_registers); 1489 int max_register = FindAffectedRegisters(&affected_registers);
1493 PushAffectedRegisters(assembler, max_register, affected_registers); 1490 PushAffectedRegisters(assembler, max_register, affected_registers);
1494 PerformDeferredActions(assembler, max_register, affected_registers); 1491 PerformDeferredActions(assembler, max_register, affected_registers);
1495 if (backtrack() != NULL) { 1492 if (backtrack() != NULL) {
1496 // 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
1497 // 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
1498 // position which we may need to emit here. 1495 // position which we may need to emit here.
1499 assembler->PushCurrentPosition(); 1496 assembler->PushCurrentPosition();
1500 } 1497 }
1501 if (cp_offset_ != 0) { 1498 if (cp_offset_ != 0) {
1502 assembler->AdvanceCurrentPosition(cp_offset_); 1499 assembler->AdvanceCurrentPosition(cp_offset_);
1503 } 1500 }
1504 1501
1505 // Create a new trivial state and generate the node with that. 1502 // Create a new trivial state and generate the node with that.
1506 Label undo; 1503 Label undo;
1507 assembler->PushBacktrack(&undo); 1504 assembler->PushBacktrack(&undo);
1508 GenerationVariant new_state; 1505 Trace new_state;
1509 bool ok = successor->Emit(compiler, &new_state); 1506 bool ok = successor->Emit(compiler, &new_state);
1510 1507
1511 // On backtrack we need to restore state. 1508 // On backtrack we need to restore state.
1512 assembler->Bind(&undo); 1509 assembler->Bind(&undo);
1513 if (!ok) return false; 1510 if (!ok) return false;
1514 if (backtrack() != NULL) { 1511 if (backtrack() != NULL) {
1515 assembler->PopCurrentPosition(); 1512 assembler->PopCurrentPosition();
1516 } 1513 }
1517 RestoreAffectedRegisters(assembler, max_register, affected_registers); 1514 RestoreAffectedRegisters(assembler, max_register, affected_registers);
1518 if (backtrack() == NULL) { 1515 if (backtrack() == NULL) {
1519 assembler->Backtrack(); 1516 assembler->Backtrack();
1520 } else { 1517 } else {
1521 assembler->GoTo(backtrack()); 1518 assembler->GoTo(backtrack());
1522 } 1519 }
1523 1520
1524 return true; 1521 return true;
1525 } 1522 }
1526 1523
1527 1524
1528 void EndNode::EmitInfoChecks(RegExpMacroAssembler* assembler, 1525 void EndNode::EmitInfoChecks(RegExpMacroAssembler* assembler, Trace* trace) {
1529 GenerationVariant* variant) {
1530 if (info()->at_end) { 1526 if (info()->at_end) {
1531 Label succeed; 1527 Label succeed;
1532 // 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
1533 // input string. 1529 // input string.
1534 assembler->LoadCurrentCharacter(0, &succeed); 1530 assembler->LoadCurrentCharacter(0, &succeed);
1535 assembler->GoTo(variant->backtrack()); 1531 assembler->GoTo(trace->backtrack());
1536 assembler->Bind(&succeed); 1532 assembler->Bind(&succeed);
1537 } 1533 }
1538 } 1534 }
1539 1535
1540 1536
1541 bool NegativeSubmatchSuccess::Emit(RegExpCompiler* compiler, 1537 bool NegativeSubmatchSuccess::Emit(RegExpCompiler* compiler, Trace* trace) {
1542 GenerationVariant* variant) { 1538 if (!trace->is_trivial()) {
1543 if (!variant->is_trivial()) { 1539 return trace->Flush(compiler, this);
1544 return variant->Flush(compiler, this);
1545 } 1540 }
1546 RegExpMacroAssembler* assembler = compiler->macro_assembler(); 1541 RegExpMacroAssembler* assembler = compiler->macro_assembler();
1547 if (!label()->is_bound()) { 1542 if (!label()->is_bound()) {
1548 assembler->Bind(label()); 1543 assembler->Bind(label());
1549 } 1544 }
1550 EmitInfoChecks(assembler, variant); 1545 EmitInfoChecks(assembler, trace);
1551 assembler->ReadCurrentPositionFromRegister(current_position_register_); 1546 assembler->ReadCurrentPositionFromRegister(current_position_register_);
1552 assembler->ReadStackPointerFromRegister(stack_pointer_register_); 1547 assembler->ReadStackPointerFromRegister(stack_pointer_register_);
1553 // 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
1554 // backtrack that the BeginSubmatch node got. 1549 // backtrack that the BeginSubmatch node got.
1555 assembler->Backtrack(); 1550 assembler->Backtrack();
1556 return true; 1551 return true;
1557 } 1552 }
1558 1553
1559 1554
1560 bool EndNode::Emit(RegExpCompiler* compiler, GenerationVariant* variant) { 1555 bool EndNode::Emit(RegExpCompiler* compiler, Trace* trace) {
1561 if (!variant->is_trivial()) { 1556 if (!trace->is_trivial()) {
1562 return variant->Flush(compiler, this); 1557 return trace->Flush(compiler, this);
1563 } 1558 }
1564 RegExpMacroAssembler* assembler = compiler->macro_assembler(); 1559 RegExpMacroAssembler* assembler = compiler->macro_assembler();
1565 if (!label()->is_bound()) { 1560 if (!label()->is_bound()) {
1566 assembler->Bind(label()); 1561 assembler->Bind(label());
1567 } 1562 }
1568 switch (action_) { 1563 switch (action_) {
1569 case ACCEPT: 1564 case ACCEPT:
1570 EmitInfoChecks(assembler, variant); 1565 EmitInfoChecks(assembler, trace);
1571 assembler->Succeed(); 1566 assembler->Succeed();
1572 return true; 1567 return true;
1573 case BACKTRACK: 1568 case BACKTRACK:
1574 ASSERT(!info()->at_end); 1569 ASSERT(!info()->at_end);
1575 assembler->GoTo(variant->backtrack()); 1570 assembler->GoTo(trace->backtrack());
1576 return true; 1571 return true;
1577 case NEGATIVE_SUBMATCH_SUCCESS: 1572 case NEGATIVE_SUBMATCH_SUCCESS:
1578 // This case is handled in a different virtual method. 1573 // This case is handled in a different virtual method.
1579 UNREACHABLE(); 1574 UNREACHABLE();
1580 } 1575 }
1581 UNIMPLEMENTED(); 1576 UNIMPLEMENTED();
1582 return false; 1577 return false;
1583 } 1578 }
1584 1579
1585 1580
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
1667 visitor->VisitLoopChoice(this); 1662 visitor->VisitLoopChoice(this);
1668 } 1663 }
1669 1664
1670 1665
1671 // ------------------------------------------------------------------- 1666 // -------------------------------------------------------------------
1672 // Emit code. 1667 // Emit code.
1673 1668
1674 1669
1675 void ChoiceNode::GenerateGuard(RegExpMacroAssembler* macro_assembler, 1670 void ChoiceNode::GenerateGuard(RegExpMacroAssembler* macro_assembler,
1676 Guard* guard, 1671 Guard* guard,
1677 GenerationVariant* variant) { 1672 Trace* trace) {
1678 switch (guard->op()) { 1673 switch (guard->op()) {
1679 case Guard::LT: 1674 case Guard::LT:
1680 ASSERT(!variant->mentions_reg(guard->reg())); 1675 ASSERT(!trace->mentions_reg(guard->reg()));
1681 macro_assembler->IfRegisterGE(guard->reg(), 1676 macro_assembler->IfRegisterGE(guard->reg(),
1682 guard->value(), 1677 guard->value(),
1683 variant->backtrack()); 1678 trace->backtrack());
1684 break; 1679 break;
1685 case Guard::GEQ: 1680 case Guard::GEQ:
1686 ASSERT(!variant->mentions_reg(guard->reg())); 1681 ASSERT(!trace->mentions_reg(guard->reg()));
1687 macro_assembler->IfRegisterLT(guard->reg(), 1682 macro_assembler->IfRegisterLT(guard->reg(),
1688 guard->value(), 1683 guard->value(),
1689 variant->backtrack()); 1684 trace->backtrack());
1690 break; 1685 break;
1691 } 1686 }
1692 } 1687 }
1693 1688
1694 1689
1695 static unibrow::Mapping<unibrow::Ecma262UnCanonicalize> uncanonicalize; 1690 static unibrow::Mapping<unibrow::Ecma262UnCanonicalize> uncanonicalize;
1696 static unibrow::Mapping<unibrow::CanonicalizationRange> canonrange; 1691 static unibrow::Mapping<unibrow::CanonicalizationRange> canonrange;
1697 1692
1698 1693
1699 // 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
1932 } 1927 }
1933 macro_assembler->Bind(&success); 1928 macro_assembler->Bind(&success);
1934 } 1929 }
1935 1930
1936 1931
1937 RegExpNode::~RegExpNode() { 1932 RegExpNode::~RegExpNode() {
1938 } 1933 }
1939 1934
1940 1935
1941 RegExpNode::LimitResult RegExpNode::LimitVersions(RegExpCompiler* compiler, 1936 RegExpNode::LimitResult RegExpNode::LimitVersions(RegExpCompiler* compiler,
1942 GenerationVariant* variant) { 1937 Trace* trace) {
1943 // TODO(erikcorry): Implement support. 1938 // TODO(erikcorry): Implement support.
1944 if (info_.follows_word_interest || 1939 if (info_.follows_word_interest ||
1945 info_.follows_newline_interest || 1940 info_.follows_newline_interest ||
1946 info_.follows_start_interest) { 1941 info_.follows_start_interest) {
1947 return FAIL; 1942 return FAIL;
1948 } 1943 }
1949 1944
1950 // 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.
1951 if (variant->stop_node() != NULL) { 1946 if (trace->stop_node() != NULL) {
1952 return CONTINUE; 1947 return CONTINUE;
1953 } 1948 }
1954 1949
1955 RegExpMacroAssembler* macro_assembler = compiler->macro_assembler(); 1950 RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
1956 if (variant->is_trivial()) { 1951 if (trace->is_trivial()) {
1957 if (label_.is_bound()) { 1952 if (label_.is_bound()) {
1958 // 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
1959 // been done so just go to it. 1954 // been done so just go to it.
1960 macro_assembler->GoTo(&label_); 1955 macro_assembler->GoTo(&label_);
1961 return DONE; 1956 return DONE;
1962 } 1957 }
1963 if (compiler->recursion_depth() >= RegExpCompiler::kMaxRecursion) { 1958 if (compiler->recursion_depth() >= RegExpCompiler::kMaxRecursion) {
1964 // 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
1965 // generate a goto here. 1960 // generate a goto here.
1966 compiler->AddWork(this); 1961 compiler->AddWork(this);
1967 macro_assembler->GoTo(&label_); 1962 macro_assembler->GoTo(&label_);
1968 return DONE; 1963 return DONE;
1969 } 1964 }
1970 // 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.
1971 macro_assembler->Bind(&label_); 1966 macro_assembler->Bind(&label_);
1972 return CONTINUE; 1967 return CONTINUE;
1973 } 1968 }
1974 1969
1975 // 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
1976 // non-generic versions we generate so as not to overdo it. 1971 // non-generic versions we generate so as not to overdo it.
1977 variants_generated_++; 1972 trace_count_++;
1978 if (variants_generated_ < kMaxVariantsGenerated && 1973 if (trace_count_ < kMaxCopiesCodeGenerated &&
1979 compiler->recursion_depth() <= RegExpCompiler::kMaxRecursion) { 1974 compiler->recursion_depth() <= RegExpCompiler::kMaxRecursion) {
1980 return CONTINUE; 1975 return CONTINUE;
1981 } 1976 }
1982 1977
1983 // 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
1984 // 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
1985 // generic versions above can handle deep recursion properly. 1980 // generic versions above can handle deep recursion properly.
1986 bool ok = variant->Flush(compiler, this); 1981 bool ok = trace->Flush(compiler, this);
1987 return ok ? DONE : FAIL; 1982 return ok ? DONE : FAIL;
1988 } 1983 }
1989 1984
1990 1985
1991 int ActionNode::EatsAtLeast(int recursion_depth) { 1986 int ActionNode::EatsAtLeast(int recursion_depth) {
1992 if (recursion_depth > RegExpCompiler::kMaxRecursion) return 0; 1987 if (recursion_depth > RegExpCompiler::kMaxRecursion) return 0;
1993 if (type_ == POSITIVE_SUBMATCH_SUCCESS) return 0; // Rewinds input! 1988 if (type_ == POSITIVE_SUBMATCH_SUCCESS) return 0; // Rewinds input!
1994 return on_success()->EatsAtLeast(recursion_depth + 1); 1989 return on_success()->EatsAtLeast(recursion_depth + 1);
1995 } 1990 }
1996 1991
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
2057 } 2052 }
2058 mask_ |= (pos->mask & char_mask) << char_shift; 2053 mask_ |= (pos->mask & char_mask) << char_shift;
2059 value_ |= (pos->value & char_mask) << char_shift; 2054 value_ |= (pos->value & char_mask) << char_shift;
2060 char_shift += asc ? 8 : 16; 2055 char_shift += asc ? 8 : 16;
2061 } 2056 }
2062 return found_useful_op; 2057 return found_useful_op;
2063 } 2058 }
2064 2059
2065 2060
2066 bool RegExpNode::EmitQuickCheck(RegExpCompiler* compiler, 2061 bool RegExpNode::EmitQuickCheck(RegExpCompiler* compiler,
2067 GenerationVariant* variant, 2062 Trace* trace,
2068 bool preload_has_checked_bounds, 2063 bool preload_has_checked_bounds,
2069 Label* on_possible_success, 2064 Label* on_possible_success,
2070 QuickCheckDetails* details, 2065 QuickCheckDetails* details,
2071 bool fall_through_on_failure) { 2066 bool fall_through_on_failure) {
2072 if (details->characters() == 0) return false; 2067 if (details->characters() == 0) return false;
2073 GetQuickCheckDetails(details, compiler, 0); 2068 GetQuickCheckDetails(details, compiler, 0);
2074 if (!details->Rationalize(compiler->ascii())) return false; 2069 if (!details->Rationalize(compiler->ascii())) return false;
2075 uint32_t mask = details->mask(); 2070 uint32_t mask = details->mask();
2076 uint32_t value = details->value(); 2071 uint32_t value = details->value();
2077 2072
2078 RegExpMacroAssembler* assembler = compiler->macro_assembler(); 2073 RegExpMacroAssembler* assembler = compiler->macro_assembler();
2079 2074
2080 if (variant->characters_preloaded() != details->characters()) { 2075 if (trace->characters_preloaded() != details->characters()) {
2081 assembler->LoadCurrentCharacter(variant->cp_offset(), 2076 assembler->LoadCurrentCharacter(trace->cp_offset(),
2082 variant->backtrack(), 2077 trace->backtrack(),
2083 !preload_has_checked_bounds, 2078 !preload_has_checked_bounds,
2084 details->characters()); 2079 details->characters());
2085 } 2080 }
2086 2081
2087 2082
2088 bool need_mask = true; 2083 bool need_mask = true;
2089 2084
2090 if (details->characters() == 1) { 2085 if (details->characters() == 1) {
2091 // 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
2092 // load so the value is already masked down. 2087 // load so the value is already masked down.
(...skipping 16 matching lines...) Expand all
2109 } 2104 }
2110 2105
2111 if (fall_through_on_failure) { 2106 if (fall_through_on_failure) {
2112 if (need_mask) { 2107 if (need_mask) {
2113 assembler->CheckCharacterAfterAnd(value, mask, on_possible_success); 2108 assembler->CheckCharacterAfterAnd(value, mask, on_possible_success);
2114 } else { 2109 } else {
2115 assembler->CheckCharacter(value, on_possible_success); 2110 assembler->CheckCharacter(value, on_possible_success);
2116 } 2111 }
2117 } else { 2112 } else {
2118 if (need_mask) { 2113 if (need_mask) {
2119 assembler->CheckNotCharacterAfterAnd(value, mask, variant->backtrack()); 2114 assembler->CheckNotCharacterAfterAnd(value, mask, trace->backtrack());
2120 } else { 2115 } else {
2121 assembler->CheckNotCharacter(value, variant->backtrack()); 2116 assembler->CheckNotCharacter(value, trace->backtrack());
2122 } 2117 }
2123 } 2118 }
2124 return true; 2119 return true;
2125 } 2120 }
2126 2121
2127 2122
2128 // 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
2129 // super-class in the .h file). 2124 // super-class in the .h file).
2130 // 2125 //
2131 // 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 229 matching lines...) Expand 10 before | Expand all | Expand 10 after
2361 // end-of-input when loading the putative 'r'. 2356 // end-of-input when loading the putative 'r'.
2362 // 2357 //
2363 // 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
2364 // 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
2365 // 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
2366 // '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
2367 // pass has been performed then subsequent passes will have true in 2362 // pass has been performed then subsequent passes will have true in
2368 // 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
2369 // checked again. 2364 // checked again.
2370 // 2365 //
2371 // 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
2372 // contain an AlternativeGeneration object. In this AlternativeGeneration 2367 // contain an AlternativeGeneration object. In this AlternativeGeneration
2373 // 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
2374 // 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
2375 // 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
2376 // 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
2377 // 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
2378 // or obviate the need for further checks at some character positions. 2373 // or obviate the need for further checks at some character positions.
2379 void TextNode::TextEmitPass(RegExpCompiler* compiler, 2374 void TextNode::TextEmitPass(RegExpCompiler* compiler,
2380 TextEmitPassType pass, 2375 TextEmitPassType pass,
2381 bool preloaded, 2376 bool preloaded,
2382 GenerationVariant* variant, 2377 Trace* trace,
2383 bool first_element_checked, 2378 bool first_element_checked,
2384 int* checked_up_to) { 2379 int* checked_up_to) {
2385 RegExpMacroAssembler* assembler = compiler->macro_assembler(); 2380 RegExpMacroAssembler* assembler = compiler->macro_assembler();
2386 bool ascii = compiler->ascii(); 2381 bool ascii = compiler->ascii();
2387 Label* backtrack = variant->backtrack(); 2382 Label* backtrack = trace->backtrack();
2388 QuickCheckDetails* quick_check = variant->quick_check_performed(); 2383 QuickCheckDetails* quick_check = trace->quick_check_performed();
2389 int element_count = elms_->length(); 2384 int element_count = elms_->length();
2390 for (int i = preloaded ? 0 : element_count - 1; i >= 0; i--) { 2385 for (int i = preloaded ? 0 : element_count - 1; i >= 0; i--) {
2391 TextElement elm = elms_->at(i); 2386 TextElement elm = elms_->at(i);
2392 int cp_offset = variant->cp_offset() + elm.cp_offset; 2387 int cp_offset = trace->cp_offset() + elm.cp_offset;
2393 if (elm.type == TextElement::ATOM) { 2388 if (elm.type == TextElement::ATOM) {
2394 if (pass == NON_ASCII_MATCH || 2389 if (pass == NON_ASCII_MATCH ||
2395 pass == CHARACTER_MATCH || 2390 pass == CHARACTER_MATCH ||
2396 pass == CASE_CHARACTER_MATCH) { 2391 pass == CASE_CHARACTER_MATCH) {
2397 Vector<const uc16> quarks = elm.data.u_atom->data(); 2392 Vector<const uc16> quarks = elm.data.u_atom->data();
2398 for (int j = preloaded ? 0 : quarks.length() - 1; j >= 0; j--) { 2393 for (int j = preloaded ? 0 : quarks.length() - 1; j >= 0; j--) {
2399 bool bound_checked = true; // Most ops will check their bounds. 2394 bool bound_checked = true; // Most ops will check their bounds.
2400 if (first_element_checked && i == 0 && j == 0) continue; 2395 if (first_element_checked && i == 0 && j == 0) continue;
2401 if (quick_check != NULL && 2396 if (quick_check != NULL &&
2402 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
2479 } 2474 }
2480 } 2475 }
2481 2476
2482 2477
2483 // 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
2484 // straight character sequences (possibly to be matched in a case-independent 2479 // straight character sequences (possibly to be matched in a case-independent
2485 // 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
2486 // 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,
2487 // 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
2488 // TextEmitPass for details. 2483 // TextEmitPass for details.
2489 bool TextNode::Emit(RegExpCompiler* compiler, GenerationVariant* variant) { 2484 bool TextNode::Emit(RegExpCompiler* compiler, Trace* trace) {
2490 LimitResult limit_result = LimitVersions(compiler, variant); 2485 LimitResult limit_result = LimitVersions(compiler, trace);
2491 if (limit_result == FAIL) return false; 2486 if (limit_result == FAIL) return false;
2492 if (limit_result == DONE) return true; 2487 if (limit_result == DONE) return true;
2493 ASSERT(limit_result == CONTINUE); 2488 ASSERT(limit_result == CONTINUE);
2494 2489
2495 if (info()->follows_word_interest || 2490 if (info()->follows_word_interest ||
2496 info()->follows_newline_interest || 2491 info()->follows_newline_interest ||
2497 info()->follows_start_interest) { 2492 info()->follows_start_interest) {
2498 return false; 2493 return false;
2499 } 2494 }
2500 2495
2501 if (info()->at_end) { 2496 if (info()->at_end) {
2502 compiler->macro_assembler()->GoTo(variant->backtrack()); 2497 compiler->macro_assembler()->GoTo(trace->backtrack());
2503 return true; 2498 return true;
2504 } 2499 }
2505 2500
2506 if (compiler->ascii()) { 2501 if (compiler->ascii()) {
2507 int dummy = 0; 2502 int dummy = 0;
2508 TextEmitPass(compiler, NON_ASCII_MATCH, false, variant, false, &dummy); 2503 TextEmitPass(compiler, NON_ASCII_MATCH, false, trace, false, &dummy);
2509 } 2504 }
2510 2505
2511 bool first_elt_done = false; 2506 bool first_elt_done = false;
2512 int bound_checked_to = variant->cp_offset() - 1; 2507 int bound_checked_to = trace->cp_offset() - 1;
2513 bound_checked_to += variant->bound_checked_up_to(); 2508 bound_checked_to += trace->bound_checked_up_to();
2514 2509
2515 // If a character is preloaded into the current character register then 2510 // If a character is preloaded into the current character register then
2516 // check that now. 2511 // check that now.
2517 if (variant->characters_preloaded() == 1) { 2512 if (trace->characters_preloaded() == 1) {
2518 TextEmitPass(compiler, 2513 TextEmitPass(compiler,
2519 CHARACTER_MATCH, 2514 CHARACTER_MATCH,
2520 true, 2515 true,
2521 variant, 2516 trace,
2522 false, 2517 false,
2523 &bound_checked_to); 2518 &bound_checked_to);
2524 if (compiler->ignore_case()) { 2519 if (compiler->ignore_case()) {
2525 TextEmitPass(compiler, 2520 TextEmitPass(compiler,
2526 CASE_CHARACTER_MATCH, 2521 CASE_CHARACTER_MATCH,
2527 true, 2522 true,
2528 variant, 2523 trace,
2529 false, 2524 false,
2530 &bound_checked_to); 2525 &bound_checked_to);
2531 } 2526 }
2532 TextEmitPass(compiler, 2527 TextEmitPass(compiler,
2533 CHARACTER_CLASS_MATCH, 2528 CHARACTER_CLASS_MATCH,
2534 true, 2529 true,
2535 variant, 2530 trace,
2536 false, 2531 false,
2537 &bound_checked_to); 2532 &bound_checked_to);
2538 first_elt_done = true; 2533 first_elt_done = true;
2539 } 2534 }
2540 2535
2541 TextEmitPass(compiler, 2536 TextEmitPass(compiler,
2542 CHARACTER_MATCH, 2537 CHARACTER_MATCH,
2543 false, 2538 false,
2544 variant, 2539 trace,
2545 first_elt_done, 2540 first_elt_done,
2546 &bound_checked_to); 2541 &bound_checked_to);
2547 if (compiler->ignore_case()) { 2542 if (compiler->ignore_case()) {
2548 TextEmitPass(compiler, 2543 TextEmitPass(compiler,
2549 CASE_CHARACTER_MATCH, 2544 CASE_CHARACTER_MATCH,
2550 false, 2545 false,
2551 variant, 2546 trace,
2552 first_elt_done, 2547 first_elt_done,
2553 &bound_checked_to); 2548 &bound_checked_to);
2554 } 2549 }
2555 TextEmitPass(compiler, 2550 TextEmitPass(compiler,
2556 CHARACTER_CLASS_MATCH, 2551 CHARACTER_CLASS_MATCH,
2557 false, 2552 false,
2558 variant, 2553 trace,
2559 first_elt_done, 2554 first_elt_done,
2560 &bound_checked_to); 2555 &bound_checked_to);
2561 2556
2562 GenerationVariant successor_variant(*variant); 2557 Trace successor_trace(*trace);
2563 successor_variant.AdvanceVariant(Length(), compiler->ascii()); 2558 successor_trace.AdvanceCurrentPositionInTrace(Length(), compiler->ascii());
2564 RecursionCheck rc(compiler); 2559 RecursionCheck rc(compiler);
2565 return on_success()->Emit(compiler, &successor_variant); 2560 return on_success()->Emit(compiler, &successor_trace);
2566 } 2561 }
2567 2562
2568 2563
2569 void GenerationVariant::AdvanceVariant(int by, bool ascii) { 2564 void Trace::AdvanceCurrentPositionInTrace(int by, bool ascii) {
2570 ASSERT(by > 0); 2565 ASSERT(by > 0);
2571 // 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
2572 // 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
2573 // we preloaded any characters into it. 2568 // we preloaded any characters into it.
2574 characters_preloaded_ = 0; 2569 characters_preloaded_ = 0;
2575 // Adjust the offsets of the quick check performed information. This 2570 // Adjust the offsets of the quick check performed information. This
2576 // 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
2577 // characters by means of mask and compare. 2572 // characters by means of mask and compare.
2578 quick_check_performed_.Advance(by, ascii); 2573 quick_check_performed_.Advance(by, ascii);
2579 cp_offset_ += by; 2574 cp_offset_ += by;
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
2646 } 2641 }
2647 2642
2648 2643
2649 void LoopChoiceNode::AddContinueAlternative(GuardedAlternative alt) { 2644 void LoopChoiceNode::AddContinueAlternative(GuardedAlternative alt) {
2650 ASSERT_EQ(continue_node_, NULL); 2645 ASSERT_EQ(continue_node_, NULL);
2651 AddAlternative(alt); 2646 AddAlternative(alt);
2652 continue_node_ = alt.node(); 2647 continue_node_ = alt.node();
2653 } 2648 }
2654 2649
2655 2650
2656 bool LoopChoiceNode::Emit(RegExpCompiler* compiler, 2651 bool LoopChoiceNode::Emit(RegExpCompiler* compiler, Trace* trace) {
2657 GenerationVariant* variant) {
2658 RegExpMacroAssembler* macro_assembler = compiler->macro_assembler(); 2652 RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
2659 if (variant->stop_node() == this) { 2653 if (trace->stop_node() == this) {
2660 int text_length = GreedyLoopTextLength(&(alternatives_->at(0))); 2654 int text_length = GreedyLoopTextLength(&(alternatives_->at(0)));
2661 ASSERT(text_length != kNodeIsTooComplexForGreedyLoops); 2655 ASSERT(text_length != kNodeIsTooComplexForGreedyLoops);
2662 // 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
2663 // optimization for greedy loops (see below). 2657 // optimization for greedy loops (see below).
2664 ASSERT(variant->cp_offset() == text_length); 2658 ASSERT(trace->cp_offset() == text_length);
2665 macro_assembler->AdvanceCurrentPosition(text_length); 2659 macro_assembler->AdvanceCurrentPosition(text_length);
2666 macro_assembler->GoTo(variant->loop_label()); 2660 macro_assembler->GoTo(trace->loop_label());
2667 return true; 2661 return true;
2668 } 2662 }
2669 ASSERT(variant->stop_node() == NULL); 2663 ASSERT(trace->stop_node() == NULL);
2670 if (!variant->is_trivial()) { 2664 if (!trace->is_trivial()) {
2671 return variant->Flush(compiler, this); 2665 return trace->Flush(compiler, this);
2672 } 2666 }
2673 return ChoiceNode::Emit(compiler, variant); 2667 return ChoiceNode::Emit(compiler, trace);
2674 } 2668 }
2675 2669
2676 2670
2677 int ChoiceNode::CalculatePreloadCharacters(RegExpCompiler* compiler) { 2671 int ChoiceNode::CalculatePreloadCharacters(RegExpCompiler* compiler) {
2678 int preload_characters = EatsAtLeast(0); 2672 int preload_characters = EatsAtLeast(0);
2679 #ifdef CAN_READ_UNALIGNED 2673 #ifdef CAN_READ_UNALIGNED
2680 bool ascii = compiler->ascii(); 2674 bool ascii = compiler->ascii();
2681 if (ascii) { 2675 if (ascii) {
2682 if (preload_characters > 4) preload_characters = 4; 2676 if (preload_characters > 4) preload_characters = 4;
2683 // 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
2816 * | / | 2810 * | / |
2817 * | R | 2811 * | R |
2818 * | / | 2812 * | / |
2819 * F VL | 2813 * F VL |
2820 * <------U | 2814 * <------U |
2821 * back |S | 2815 * back |S |
2822 * \______________/ 2816 * \______________/
2823 */ 2817 */
2824 2818
2825 2819
2826 bool ChoiceNode::Emit(RegExpCompiler* compiler, GenerationVariant* variant) { 2820 bool ChoiceNode::Emit(RegExpCompiler* compiler, Trace* trace) {
2827 RegExpMacroAssembler* macro_assembler = compiler->macro_assembler(); 2821 RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
2828 int choice_count = alternatives_->length(); 2822 int choice_count = alternatives_->length();
2829 #ifdef DEBUG 2823 #ifdef DEBUG
2830 for (int i = 0; i < choice_count - 1; i++) { 2824 for (int i = 0; i < choice_count - 1; i++) {
2831 GuardedAlternative alternative = alternatives_->at(i); 2825 GuardedAlternative alternative = alternatives_->at(i);
2832 ZoneList<Guard*>* guards = alternative.guards(); 2826 ZoneList<Guard*>* guards = alternative.guards();
2833 int guard_count = (guards == NULL) ? 0 : guards->length(); 2827 int guard_count = (guards == NULL) ? 0 : guards->length();
2834 for (int j = 0; j < guard_count; j++) { 2828 for (int j = 0; j < guard_count; j++) {
2835 ASSERT(!variant->mentions_reg(guards->at(j)->reg())); 2829 ASSERT(!trace->mentions_reg(guards->at(j)->reg()));
2836 } 2830 }
2837 } 2831 }
2838 #endif 2832 #endif
2839 2833
2840 LimitResult limit_result = LimitVersions(compiler, variant); 2834 LimitResult limit_result = LimitVersions(compiler, trace);
2841 if (limit_result == DONE) return true; 2835 if (limit_result == DONE) return true;
2842 if (limit_result == FAIL) return false; 2836 if (limit_result == FAIL) return false;
2843 ASSERT(limit_result == CONTINUE); 2837 ASSERT(limit_result == CONTINUE);
2844 2838
2845 RecursionCheck rc(compiler); 2839 RecursionCheck rc(compiler);
2846 2840
2847 GenerationVariant* current_variant = variant; 2841 Trace* current_trace = trace;
2848 2842
2849 int text_length = GreedyLoopTextLength(&(alternatives_->at(0))); 2843 int text_length = GreedyLoopTextLength(&(alternatives_->at(0)));
2850 bool greedy_loop = false; 2844 bool greedy_loop = false;
2851 Label greedy_loop_label; 2845 Label greedy_loop_label;
2852 GenerationVariant counter_backtrack_variant; 2846 Trace counter_backtrack_trace;
2853 counter_backtrack_variant.set_backtrack(&greedy_loop_label); 2847 counter_backtrack_trace.set_backtrack(&greedy_loop_label);
2854 if (choice_count > 1 && text_length != kNodeIsTooComplexForGreedyLoops) { 2848 if (choice_count > 1 && text_length != kNodeIsTooComplexForGreedyLoops) {
2855 // 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
2856 // and other simple nodes. These are handled by pushing the current 2850 // and other simple nodes. These are handled by pushing the current
2857 // position on the stack and then incrementing the current position each 2851 // position on the stack and then incrementing the current position each
2858 // time around the switch. On backtrack we decrement the current position 2852 // time around the switch. On backtrack we decrement the current position
2859 // and check it against the pushed value. This avoids pushing backtrack 2853 // and check it against the pushed value. This avoids pushing backtrack
2860 // 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
2861 // space. 2855 // space.
2862 greedy_loop = true; 2856 greedy_loop = true;
2863 ASSERT(variant->stop_node() == NULL); 2857 ASSERT(trace->stop_node() == NULL);
2864 macro_assembler->PushCurrentPosition(); 2858 macro_assembler->PushCurrentPosition();
2865 current_variant = &counter_backtrack_variant; 2859 current_trace = &counter_backtrack_trace;
2866 Label greedy_match_failed; 2860 Label greedy_match_failed;
2867 GenerationVariant greedy_match_variant; 2861 Trace greedy_match_trace;
2868 greedy_match_variant.set_backtrack(&greedy_match_failed); 2862 greedy_match_trace.set_backtrack(&greedy_match_failed);
2869 Label loop_label; 2863 Label loop_label;
2870 macro_assembler->Bind(&loop_label); 2864 macro_assembler->Bind(&loop_label);
2871 greedy_match_variant.set_stop_node(this); 2865 greedy_match_trace.set_stop_node(this);
2872 greedy_match_variant.set_loop_label(&loop_label); 2866 greedy_match_trace.set_loop_label(&loop_label);
2873 bool ok = alternatives_->at(0).node()->Emit(compiler, 2867 bool ok = alternatives_->at(0).node()->Emit(compiler,
2874 &greedy_match_variant); 2868 &greedy_match_trace);
2875 macro_assembler->Bind(&greedy_match_failed); 2869 macro_assembler->Bind(&greedy_match_failed);
2876 if (!ok) { 2870 if (!ok) {
2877 greedy_loop_label.Unuse(); 2871 greedy_loop_label.Unuse();
2878 return false; 2872 return false;
2879 } 2873 }
2880 } 2874 }
2881 2875
2882 Label second_choice; // For use in greedy matches. 2876 Label second_choice; // For use in greedy matches.
2883 macro_assembler->Bind(&second_choice); 2877 macro_assembler->Bind(&second_choice);
2884 2878
2885 int first_normal_choice = greedy_loop ? 1 : 0; 2879 int first_normal_choice = greedy_loop ? 1 : 0;
2886 2880
2887 int preload_characters = CalculatePreloadCharacters(compiler); 2881 int preload_characters = CalculatePreloadCharacters(compiler);
2888 bool preload_is_current = 2882 bool preload_is_current =
2889 (current_variant->characters_preloaded() == preload_characters); 2883 (current_trace->characters_preloaded() == preload_characters);
2890 bool preload_has_checked_bounds = preload_is_current; 2884 bool preload_has_checked_bounds = preload_is_current;
2891 2885
2892 AlternativeGenerationList alt_gens(choice_count); 2886 AlternativeGenerationList alt_gens(choice_count);
2893 2887
2894 // 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
2895 // 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.
2896 for (int i = first_normal_choice; i < choice_count; i++) { 2890 for (int i = first_normal_choice; i < choice_count; i++) {
2897 GuardedAlternative alternative = alternatives_->at(i); 2891 GuardedAlternative alternative = alternatives_->at(i);
2898 AlternativeGeneration* alt_gen = alt_gens.at(i); 2892 AlternativeGeneration* alt_gen = alt_gens.at(i);
2899 alt_gen->quick_check_details.set_characters(preload_characters); 2893 alt_gen->quick_check_details.set_characters(preload_characters);
2900 ZoneList<Guard*>* guards = alternative.guards(); 2894 ZoneList<Guard*>* guards = alternative.guards();
2901 int guard_count = (guards == NULL) ? 0 : guards->length(); 2895 int guard_count = (guards == NULL) ? 0 : guards->length();
2902 GenerationVariant new_variant(*current_variant); 2896 Trace new_trace(*current_trace);
2903 new_variant.set_characters_preloaded(preload_is_current ? 2897 new_trace.set_characters_preloaded(preload_is_current ?
2904 preload_characters : 2898 preload_characters :
2905 0); 2899 0);
2906 if (preload_has_checked_bounds) { 2900 if (preload_has_checked_bounds) {
2907 new_variant.set_bound_checked_up_to(preload_characters); 2901 new_trace.set_bound_checked_up_to(preload_characters);
2908 } 2902 }
2909 new_variant.quick_check_performed()->Clear(); 2903 new_trace.quick_check_performed()->Clear();
2910 alt_gen->expects_preload = preload_is_current; 2904 alt_gen->expects_preload = preload_is_current;
2911 bool generate_full_check_inline = false; 2905 bool generate_full_check_inline = false;
2912 if (alternative.node()->EmitQuickCheck(compiler, 2906 if (alternative.node()->EmitQuickCheck(compiler,
2913 &new_variant, 2907 &new_trace,
2914 preload_has_checked_bounds, 2908 preload_has_checked_bounds,
2915 &alt_gen->possible_success, 2909 &alt_gen->possible_success,
2916 &alt_gen->quick_check_details, 2910 &alt_gen->quick_check_details,
2917 i < choice_count - 1)) { 2911 i < choice_count - 1)) {
2918 // Quick check was generated for this choice. 2912 // Quick check was generated for this choice.
2919 preload_is_current = true; 2913 preload_is_current = true;
2920 preload_has_checked_bounds = true; 2914 preload_has_checked_bounds = true;
2921 // On the last choice in the ChoiceNode we generated the quick 2915 // On the last choice in the ChoiceNode we generated the quick
2922 // 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
2923 // generate the full check inline. 2917 // generate the full check inline.
2924 if (i == choice_count - 1) { 2918 if (i == choice_count - 1) {
2925 macro_assembler->Bind(&alt_gen->possible_success); 2919 macro_assembler->Bind(&alt_gen->possible_success);
2926 new_variant.set_quick_check_performed(&alt_gen->quick_check_details); 2920 new_trace.set_quick_check_performed(&alt_gen->quick_check_details);
2927 new_variant.set_characters_preloaded(preload_characters); 2921 new_trace.set_characters_preloaded(preload_characters);
2928 new_variant.set_bound_checked_up_to(preload_characters); 2922 new_trace.set_bound_checked_up_to(preload_characters);
2929 generate_full_check_inline = true; 2923 generate_full_check_inline = true;
2930 } 2924 }
2931 } else { 2925 } else {
2932 // No quick check was generated. Put the full code here. 2926 // No quick check was generated. Put the full code here.
2933 // 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
2934 // 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
2935 // 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
2936 // to generate probably can't use it. 2930 // to generate probably can't use it.
2937 if (i != first_normal_choice) { 2931 if (i != first_normal_choice) {
2938 alt_gen->expects_preload = false; 2932 alt_gen->expects_preload = false;
2939 new_variant.set_characters_preloaded(0); 2933 new_trace.set_characters_preloaded(0);
2940 } 2934 }
2941 if (i < choice_count - 1) { 2935 if (i < choice_count - 1) {
2942 new_variant.set_backtrack(&alt_gen->after); 2936 new_trace.set_backtrack(&alt_gen->after);
2943 } 2937 }
2944 generate_full_check_inline = true; 2938 generate_full_check_inline = true;
2945 } 2939 }
2946 if (generate_full_check_inline) { 2940 if (generate_full_check_inline) {
2947 for (int j = 0; j < guard_count; j++) { 2941 for (int j = 0; j < guard_count; j++) {
2948 GenerateGuard(macro_assembler, guards->at(j), &new_variant); 2942 GenerateGuard(macro_assembler, guards->at(j), &new_trace);
2949 } 2943 }
2950 if (!alternative.node()->Emit(compiler, &new_variant)) { 2944 if (!alternative.node()->Emit(compiler, &new_trace)) {
2951 greedy_loop_label.Unuse(); 2945 greedy_loop_label.Unuse();
2952 return false; 2946 return false;
2953 } 2947 }
2954 preload_is_current = false; 2948 preload_is_current = false;
2955 } 2949 }
2956 macro_assembler->Bind(&alt_gen->after); 2950 macro_assembler->Bind(&alt_gen->after);
2957 } 2951 }
2958 if (greedy_loop) { 2952 if (greedy_loop) {
2959 macro_assembler->Bind(&greedy_loop_label); 2953 macro_assembler->Bind(&greedy_loop_label);
2960 // If we have unwound to the bottom then backtrack. 2954 // If we have unwound to the bottom then backtrack.
2961 macro_assembler->CheckGreedyLoop(variant->backtrack()); 2955 macro_assembler->CheckGreedyLoop(trace->backtrack());
2962 // Otherwise try the second priority at an earlier position. 2956 // Otherwise try the second priority at an earlier position.
2963 macro_assembler->AdvanceCurrentPosition(-text_length); 2957 macro_assembler->AdvanceCurrentPosition(-text_length);
2964 macro_assembler->GoTo(&second_choice); 2958 macro_assembler->GoTo(&second_choice);
2965 } 2959 }
2966 // 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
2967 // 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
2968 // label was bound. 2962 // label was bound.
2969 for (int i = first_normal_choice; i < choice_count - 1; i++) { 2963 for (int i = first_normal_choice; i < choice_count - 1; i++) {
2970 AlternativeGeneration* alt_gen = alt_gens.at(i); 2964 AlternativeGeneration* alt_gen = alt_gens.at(i);
2971 if (!EmitOutOfLineContinuation(compiler, 2965 if (!EmitOutOfLineContinuation(compiler,
2972 current_variant, 2966 current_trace,
2973 alternatives_->at(i), 2967 alternatives_->at(i),
2974 alt_gen, 2968 alt_gen,
2975 preload_characters, 2969 preload_characters,
2976 alt_gens.at(i + 1)->expects_preload)) { 2970 alt_gens.at(i + 1)->expects_preload)) {
2977 return false; 2971 return false;
2978 } 2972 }
2979 } 2973 }
2980 return true; 2974 return true;
2981 } 2975 }
2982 2976
2983 2977
2984 bool ChoiceNode::EmitOutOfLineContinuation(RegExpCompiler* compiler, 2978 bool ChoiceNode::EmitOutOfLineContinuation(RegExpCompiler* compiler,
2985 GenerationVariant* variant, 2979 Trace* trace,
2986 GuardedAlternative alternative, 2980 GuardedAlternative alternative,
2987 AlternativeGeneration* alt_gen, 2981 AlternativeGeneration* alt_gen,
2988 int preload_characters, 2982 int preload_characters,
2989 bool next_expects_preload) { 2983 bool next_expects_preload) {
2990 if (!alt_gen->possible_success.is_linked()) return true; 2984 if (!alt_gen->possible_success.is_linked()) return true;
2991 2985
2992 RegExpMacroAssembler* macro_assembler = compiler->macro_assembler(); 2986 RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
2993 macro_assembler->Bind(&alt_gen->possible_success); 2987 macro_assembler->Bind(&alt_gen->possible_success);
2994 GenerationVariant out_of_line_variant(*variant); 2988 Trace out_of_line_trace(*trace);
2995 out_of_line_variant.set_characters_preloaded(preload_characters); 2989 out_of_line_trace.set_characters_preloaded(preload_characters);
2996 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);
2997 ZoneList<Guard*>* guards = alternative.guards(); 2991 ZoneList<Guard*>* guards = alternative.guards();
2998 int guard_count = (guards == NULL) ? 0 : guards->length(); 2992 int guard_count = (guards == NULL) ? 0 : guards->length();
2999 if (next_expects_preload) { 2993 if (next_expects_preload) {
3000 Label reload_current_char; 2994 Label reload_current_char;
3001 out_of_line_variant.set_backtrack(&reload_current_char); 2995 out_of_line_trace.set_backtrack(&reload_current_char);
3002 for (int j = 0; j < guard_count; j++) { 2996 for (int j = 0; j < guard_count; j++) {
3003 GenerateGuard(macro_assembler, guards->at(j), &out_of_line_variant); 2997 GenerateGuard(macro_assembler, guards->at(j), &out_of_line_trace);
3004 } 2998 }
3005 bool ok = alternative.node()->Emit(compiler, &out_of_line_variant); 2999 bool ok = alternative.node()->Emit(compiler, &out_of_line_trace);
3006 macro_assembler->Bind(&reload_current_char); 3000 macro_assembler->Bind(&reload_current_char);
3007 // Reload the current character, since the next quick check expects that. 3001 // Reload the current character, since the next quick check expects that.
3008 // 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
3009 // code through a quick check which already did the checked load. 3003 // code through a quick check which already did the checked load.
3010 macro_assembler->LoadCurrentCharacter(variant->cp_offset(), 3004 macro_assembler->LoadCurrentCharacter(trace->cp_offset(),
3011 NULL, 3005 NULL,
3012 false, 3006 false,
3013 preload_characters); 3007 preload_characters);
3014 macro_assembler->GoTo(&(alt_gen->after)); 3008 macro_assembler->GoTo(&(alt_gen->after));
3015 return ok; 3009 return ok;
3016 } else { 3010 } else {
3017 out_of_line_variant.set_backtrack(&(alt_gen->after)); 3011 out_of_line_trace.set_backtrack(&(alt_gen->after));
3018 for (int j = 0; j < guard_count; j++) { 3012 for (int j = 0; j < guard_count; j++) {
3019 GenerateGuard(macro_assembler, guards->at(j), &out_of_line_variant); 3013 GenerateGuard(macro_assembler, guards->at(j), &out_of_line_trace);
3020 } 3014 }
3021 return alternative.node()->Emit(compiler, &out_of_line_variant); 3015 return alternative.node()->Emit(compiler, &out_of_line_trace);
3022 } 3016 }
3023 } 3017 }
3024 3018
3025 3019
3026 bool ActionNode::Emit(RegExpCompiler* compiler, GenerationVariant* variant) { 3020 bool ActionNode::Emit(RegExpCompiler* compiler, Trace* trace) {
3027 RegExpMacroAssembler* assembler = compiler->macro_assembler(); 3021 RegExpMacroAssembler* assembler = compiler->macro_assembler();
3028 LimitResult limit_result = LimitVersions(compiler, variant); 3022 LimitResult limit_result = LimitVersions(compiler, trace);
3029 if (limit_result == DONE) return true; 3023 if (limit_result == DONE) return true;
3030 if (limit_result == FAIL) return false; 3024 if (limit_result == FAIL) return false;
3031 ASSERT(limit_result == CONTINUE); 3025 ASSERT(limit_result == CONTINUE);
3032 3026
3033 RecursionCheck rc(compiler); 3027 RecursionCheck rc(compiler);
3034 3028
3035 switch (type_) { 3029 switch (type_) {
3036 case STORE_POSITION: { 3030 case STORE_POSITION: {
3037 GenerationVariant::DeferredCapture 3031 Trace::DeferredCapture
3038 new_capture(data_.u_position_register.reg, variant); 3032 new_capture(data_.u_position_register.reg, trace);
3039 GenerationVariant new_variant = *variant; 3033 Trace new_trace = *trace;
3040 new_variant.add_action(&new_capture); 3034 new_trace.add_action(&new_capture);
3041 return on_success()->Emit(compiler, &new_variant); 3035 return on_success()->Emit(compiler, &new_trace);
3042 } 3036 }
3043 case INCREMENT_REGISTER: { 3037 case INCREMENT_REGISTER: {
3044 GenerationVariant::DeferredIncrementRegister 3038 Trace::DeferredIncrementRegister
3045 new_increment(data_.u_increment_register.reg); 3039 new_increment(data_.u_increment_register.reg);
3046 GenerationVariant new_variant = *variant; 3040 Trace new_trace = *trace;
3047 new_variant.add_action(&new_increment); 3041 new_trace.add_action(&new_increment);
3048 return on_success()->Emit(compiler, &new_variant); 3042 return on_success()->Emit(compiler, &new_trace);
3049 } 3043 }
3050 case SET_REGISTER: { 3044 case SET_REGISTER: {
3051 GenerationVariant::DeferredSetRegister 3045 Trace::DeferredSetRegister
3052 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);
3053 GenerationVariant new_variant = *variant; 3047 Trace new_trace = *trace;
3054 new_variant.add_action(&new_set); 3048 new_trace.add_action(&new_set);
3055 return on_success()->Emit(compiler, &new_variant); 3049 return on_success()->Emit(compiler, &new_trace);
3056 } 3050 }
3057 case CLEAR_CAPTURES: { 3051 case CLEAR_CAPTURES: {
3058 GenerationVariant::DeferredClearCaptures 3052 Trace::DeferredClearCaptures
3059 new_capture(Interval(data_.u_clear_captures.range_from, 3053 new_capture(Interval(data_.u_clear_captures.range_from,
3060 data_.u_clear_captures.range_to)); 3054 data_.u_clear_captures.range_to));
3061 GenerationVariant new_variant = *variant; 3055 Trace new_trace = *trace;
3062 new_variant.add_action(&new_capture); 3056 new_trace.add_action(&new_capture);
3063 return on_success()->Emit(compiler, &new_variant); 3057 return on_success()->Emit(compiler, &new_trace);
3064 } 3058 }
3065 case BEGIN_SUBMATCH: 3059 case BEGIN_SUBMATCH:
3066 if (!variant->is_trivial()) return variant->Flush(compiler, this); 3060 if (!trace->is_trivial()) return trace->Flush(compiler, this);
3067 assembler->WriteCurrentPositionToRegister( 3061 assembler->WriteCurrentPositionToRegister(
3068 data_.u_submatch.current_position_register, 0); 3062 data_.u_submatch.current_position_register, 0);
3069 assembler->WriteStackPointerToRegister( 3063 assembler->WriteStackPointerToRegister(
3070 data_.u_submatch.stack_pointer_register); 3064 data_.u_submatch.stack_pointer_register);
3071 return on_success()->Emit(compiler, variant); 3065 return on_success()->Emit(compiler, trace);
3072 case EMPTY_MATCH_CHECK: { 3066 case EMPTY_MATCH_CHECK: {
3073 int start_pos_reg = data_.u_empty_match_check.start_register; 3067 int start_pos_reg = data_.u_empty_match_check.start_register;
3074 int stored_pos = 0; 3068 int stored_pos = 0;
3075 int rep_reg = data_.u_empty_match_check.repetition_register; 3069 int rep_reg = data_.u_empty_match_check.repetition_register;
3076 bool has_minimum = (rep_reg != RegExpCompiler::kNoRegister); 3070 bool has_minimum = (rep_reg != RegExpCompiler::kNoRegister);
3077 bool know_dist = variant->GetStoredPosition(start_pos_reg, &stored_pos); 3071 bool know_dist = trace->GetStoredPosition(start_pos_reg, &stored_pos);
3078 if (know_dist && !has_minimum && stored_pos == variant->cp_offset()) { 3072 if (know_dist && !has_minimum && stored_pos == trace->cp_offset()) {
3079 // If we know we haven't advanced and there is no minimum we 3073 // If we know we haven't advanced and there is no minimum we
3080 // can just backtrack immediately. 3074 // can just backtrack immediately.
3081 assembler->GoTo(variant->backtrack()); 3075 assembler->GoTo(trace->backtrack());
3082 return true; 3076 return true;
3083 } else if (know_dist && stored_pos < variant->cp_offset()) { 3077 } else if (know_dist && stored_pos < trace->cp_offset()) {
3084 // If we know we've advanced we can generate the continuation 3078 // If we know we've advanced we can generate the continuation
3085 // immediately. 3079 // immediately.
3086 return on_success()->Emit(compiler, variant); 3080 return on_success()->Emit(compiler, trace);
3087 } 3081 }
3088 if (!variant->is_trivial()) return variant->Flush(compiler, this); 3082 if (!trace->is_trivial()) return trace->Flush(compiler, this);
3089 Label skip_empty_check; 3083 Label skip_empty_check;
3090 // If we have a minimum number of repetitions we check the current 3084 // If we have a minimum number of repetitions we check the current
3091 // number first and skip the empty check if it's not enough. 3085 // number first and skip the empty check if it's not enough.
3092 if (has_minimum) { 3086 if (has_minimum) {
3093 int limit = data_.u_empty_match_check.repetition_limit; 3087 int limit = data_.u_empty_match_check.repetition_limit;
3094 assembler->IfRegisterLT(rep_reg, limit, &skip_empty_check); 3088 assembler->IfRegisterLT(rep_reg, limit, &skip_empty_check);
3095 } 3089 }
3096 // If the match is empty we bail out, otherwise we fall through 3090 // If the match is empty we bail out, otherwise we fall through
3097 // to the on-success continuation. 3091 // to the on-success continuation.
3098 assembler->IfRegisterEqPos(data_.u_empty_match_check.start_register, 3092 assembler->IfRegisterEqPos(data_.u_empty_match_check.start_register,
3099 variant->backtrack()); 3093 trace->backtrack());
3100 assembler->Bind(&skip_empty_check); 3094 assembler->Bind(&skip_empty_check);
3101 return on_success()->Emit(compiler, variant); 3095 return on_success()->Emit(compiler, trace);
3102 } 3096 }
3103 case POSITIVE_SUBMATCH_SUCCESS: 3097 case POSITIVE_SUBMATCH_SUCCESS:
3104 if (!variant->is_trivial()) return variant->Flush(compiler, this); 3098 if (!trace->is_trivial()) return trace->Flush(compiler, this);
3105 // TODO(erikcorry): Implement support. 3099 // TODO(erikcorry): Implement support.
3106 if (info()->follows_word_interest || 3100 if (info()->follows_word_interest ||
3107 info()->follows_newline_interest || 3101 info()->follows_newline_interest ||
3108 info()->follows_start_interest) { 3102 info()->follows_start_interest) {
3109 return false; 3103 return false;
3110 } 3104 }
3111 if (info()->at_end) { 3105 if (info()->at_end) {
3112 Label at_end; 3106 Label at_end;
3113 // 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
3114 // end. 3108 // end.
3115 assembler->LoadCurrentCharacter(0, &at_end); 3109 assembler->LoadCurrentCharacter(0, &at_end);
3116 assembler->GoTo(variant->backtrack()); 3110 assembler->GoTo(trace->backtrack());
3117 assembler->Bind(&at_end); 3111 assembler->Bind(&at_end);
3118 } 3112 }
3119 assembler->ReadCurrentPositionFromRegister( 3113 assembler->ReadCurrentPositionFromRegister(
3120 data_.u_submatch.current_position_register); 3114 data_.u_submatch.current_position_register);
3121 assembler->ReadStackPointerFromRegister( 3115 assembler->ReadStackPointerFromRegister(
3122 data_.u_submatch.stack_pointer_register); 3116 data_.u_submatch.stack_pointer_register);
3123 return on_success()->Emit(compiler, variant); 3117 return on_success()->Emit(compiler, trace);
3124 default: 3118 default:
3125 UNREACHABLE(); 3119 UNREACHABLE();
3126 return false; 3120 return false;
3127 } 3121 }
3128 } 3122 }
3129 3123
3130 3124
3131 bool BackReferenceNode::Emit(RegExpCompiler* compiler, 3125 bool BackReferenceNode::Emit(RegExpCompiler* compiler, Trace* trace) {
3132 GenerationVariant* variant) {
3133 RegExpMacroAssembler* assembler = compiler->macro_assembler(); 3126 RegExpMacroAssembler* assembler = compiler->macro_assembler();
3134 if (!variant->is_trivial()) { 3127 if (!trace->is_trivial()) {
3135 return variant->Flush(compiler, this); 3128 return trace->Flush(compiler, this);
3136 } 3129 }
3137 3130
3138 LimitResult limit_result = LimitVersions(compiler, variant); 3131 LimitResult limit_result = LimitVersions(compiler, trace);
3139 if (limit_result == DONE) return true; 3132 if (limit_result == DONE) return true;
3140 if (limit_result == FAIL) return false; 3133 if (limit_result == FAIL) return false;
3141 ASSERT(limit_result == CONTINUE); 3134 ASSERT(limit_result == CONTINUE);
3142 3135
3143 RecursionCheck rc(compiler); 3136 RecursionCheck rc(compiler);
3144 3137
3145 ASSERT_EQ(start_reg_ + 1, end_reg_); 3138 ASSERT_EQ(start_reg_ + 1, end_reg_);
3146 if (info()->at_end) { 3139 if (info()->at_end) {
3147 // 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
3148 // iff the back reference is empty. 3141 // iff the back reference is empty.
3149 assembler->CheckNotRegistersEqual(start_reg_, 3142 assembler->CheckNotRegistersEqual(start_reg_,
3150 end_reg_, 3143 end_reg_,
3151 variant->backtrack()); 3144 trace->backtrack());
3152 } else { 3145 } else {
3153 if (compiler->ignore_case()) { 3146 if (compiler->ignore_case()) {
3154 assembler->CheckNotBackReferenceIgnoreCase(start_reg_, 3147 assembler->CheckNotBackReferenceIgnoreCase(start_reg_,
3155 variant->backtrack()); 3148 trace->backtrack());
3156 } else { 3149 } else {
3157 assembler->CheckNotBackReference(start_reg_, variant->backtrack()); 3150 assembler->CheckNotBackReference(start_reg_, trace->backtrack());
3158 } 3151 }
3159 } 3152 }
3160 return on_success()->Emit(compiler, variant); 3153 return on_success()->Emit(compiler, trace);
3161 } 3154 }
3162 3155
3163 3156
3164 // ------------------------------------------------------------------- 3157 // -------------------------------------------------------------------
3165 // Dot/dotty output 3158 // Dot/dotty output
3166 3159
3167 3160
3168 #ifdef DEBUG 3161 #ifdef DEBUG
3169 3162
3170 3163
(...skipping 1388 matching lines...) Expand 10 before | Expand all | Expand 10 after
4559 EmbeddedVector<byte, 1024> codes; 4552 EmbeddedVector<byte, 1024> codes;
4560 RegExpMacroAssemblerIrregexp macro_assembler(codes); 4553 RegExpMacroAssemblerIrregexp macro_assembler(codes);
4561 return compiler.Assemble(&macro_assembler, 4554 return compiler.Assemble(&macro_assembler,
4562 node, 4555 node,
4563 data->capture_count, 4556 data->capture_count,
4564 pattern); 4557 pattern);
4565 } 4558 }
4566 4559
4567 4560
4568 }} // namespace v8::internal 4561 }} // namespace v8::internal
OLDNEW
« no previous file with comments | « src/jsregexp.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698