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

Side by Side Diff: src/jsregexp.cc

Issue 10408: Uniqueify out sets. (Closed)
Patch Set: Created 12 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 718 matching lines...) Expand 10 before | Expand all | Expand 10 after
729 private: 729 private:
730 RegExpNode* on_failure_; 730 RegExpNode* on_failure_;
731 int start_reg_; 731 int start_reg_;
732 int end_reg_; 732 int end_reg_;
733 }; 733 };
734 734
735 735
736 class CharacterClassNode: public SeqRegExpNode { 736 class CharacterClassNode: public SeqRegExpNode {
737 public: 737 public:
738 CharacterClassNode(ZoneList<CharacterRange>* ranges, 738 CharacterClassNode(ZoneList<CharacterRange>* ranges,
739 bool is_negated,
739 RegExpNode* on_success, 740 RegExpNode* on_success,
740 RegExpNode* on_failure) 741 RegExpNode* on_failure)
741 : SeqRegExpNode(on_success), 742 : SeqRegExpNode(on_success),
742 on_failure_(on_failure), 743 on_failure_(on_failure),
743 ranges_(ranges) { } 744 ranges_(ranges),
745 is_negated_(is_negated ){ }
744 virtual void Accept(NodeVisitor* visitor); 746 virtual void Accept(NodeVisitor* visitor);
745 ZoneList<CharacterRange>* ranges() { return ranges_; } 747 ZoneList<CharacterRange>* ranges() { return ranges_; }
748 bool is_negated() { return is_negated_; }
746 RegExpNode* on_failure() { return on_failure_; } 749 RegExpNode* on_failure() { return on_failure_; }
750 static void AddInverseToTable(List<CharacterRange> ranges,
751 DispatchTable* table,
752 int index);
747 private: 753 private:
748 RegExpNode* on_failure_; 754 RegExpNode* on_failure_;
749 ZoneList<CharacterRange>* ranges_; 755 ZoneList<CharacterRange>* ranges_;
756 bool is_negated_;
750 }; 757 };
751 758
752 759
753 class Guard: public ZoneObject { 760 class Guard: public ZoneObject {
754 public: 761 public:
755 enum Relation { LT, GEQ }; 762 enum Relation { LT, GEQ };
756 Guard(int reg, Relation op, int value) 763 Guard(int reg, Relation op, int value)
757 : reg_(reg), 764 : reg_(reg),
758 op_(op), 765 op_(op),
759 value_(value) { } 766 value_(value) { }
(...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after
1080 DispatchTableDumper(StringStream* stream) : stream_(stream) { } 1087 DispatchTableDumper(StringStream* stream) : stream_(stream) { }
1081 void Call(uc16 key, DispatchTable::Entry entry); 1088 void Call(uc16 key, DispatchTable::Entry entry);
1082 StringStream* stream() { return stream_; } 1089 StringStream* stream() { return stream_; }
1083 private: 1090 private:
1084 StringStream* stream_; 1091 StringStream* stream_;
1085 }; 1092 };
1086 1093
1087 1094
1088 void DispatchTableDumper::Call(uc16 key, DispatchTable::Entry entry) { 1095 void DispatchTableDumper::Call(uc16 key, DispatchTable::Entry entry) {
1089 stream()->Add("[%k-%k]: {", key, entry.to()); 1096 stream()->Add("[%k-%k]: {", key, entry.to());
1090 OutSet set = entry.out_set(); 1097 OutSet* set = entry.out_set();
1091 bool first = true; 1098 bool first = true;
1092 for (unsigned i = 0; i < OutSet::kFirstLimit; i++) { 1099 for (unsigned i = 0; i < OutSet::kFirstLimit; i++) {
1093 if (set.Get(i)) { 1100 if (set->Get(i)) {
1094 if (first) first = false; 1101 if (first) first = false;
1095 else stream()->Add(", "); 1102 else stream()->Add(", ");
1096 stream()->Add("%i", i); 1103 stream()->Add("%i", i);
1097 } 1104 }
1098 } 1105 }
1099 stream()->Add("}\n"); 1106 stream()->Add("}\n");
1100 } 1107 }
1101 1108
1102 1109
1103 void DispatchTable::Dump() { 1110 void DispatchTable::Dump() {
(...skipping 20 matching lines...) Expand all
1124 RegExpNode* RegExpAtom::ToNode(RegExpCompiler* compiler, 1131 RegExpNode* RegExpAtom::ToNode(RegExpCompiler* compiler,
1125 RegExpNode* on_success, 1132 RegExpNode* on_success,
1126 RegExpNode* on_failure) { 1133 RegExpNode* on_failure) {
1127 return new AtomNode(data(), on_success, on_failure); 1134 return new AtomNode(data(), on_success, on_failure);
1128 } 1135 }
1129 1136
1130 1137
1131 RegExpNode* RegExpCharacterClass::ToNode(RegExpCompiler* compiler, 1138 RegExpNode* RegExpCharacterClass::ToNode(RegExpCompiler* compiler,
1132 RegExpNode* on_success, 1139 RegExpNode* on_success,
1133 RegExpNode* on_failure) { 1140 RegExpNode* on_failure) {
1134 return new CharacterClassNode(ranges(), on_success, on_failure); 1141 return new CharacterClassNode(ranges(),
1142 is_negated(),
1143 on_success,
1144 on_failure);
1135 } 1145 }
1136 1146
1137 1147
1138 RegExpNode* RegExpDisjunction::ToNode(RegExpCompiler* compiler, 1148 RegExpNode* RegExpDisjunction::ToNode(RegExpCompiler* compiler,
1139 RegExpNode* on_success, 1149 RegExpNode* on_success,
1140 RegExpNode* on_failure) { 1150 RegExpNode* on_failure) {
1141 ZoneList<RegExpTree*>* children = nodes(); 1151 ZoneList<RegExpTree*>* children = nodes();
1142 int length = children->length(); 1152 int length = children->length();
1143 ChoiceNode* result = new ChoiceNode(length, on_failure); 1153 ChoiceNode* result = new ChoiceNode(length, on_failure);
1144 for (int i = 0; i < length; i++) { 1154 for (int i = 0; i < length; i++) {
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after
1366 default: 1376 default:
1367 UNREACHABLE(); 1377 UNREACHABLE();
1368 } 1378 }
1369 } 1379 }
1370 1380
1371 1381
1372 // ------------------------------------------------------------------- 1382 // -------------------------------------------------------------------
1373 // Splay tree 1383 // Splay tree
1374 1384
1375 1385
1386 OutSet* OutSet::Extend(unsigned value) {
1387 if (Get(value))
1388 return this;
1389 if (successors() != NULL) {
1390 for (int i = 0; i < successors()->length(); i++) {
1391 OutSet* successor = successors()->at(i);
1392 if (successor->Get(value))
1393 return successor;
1394 }
1395 } else {
1396 successors_ = new ZoneList<OutSet*>(2);
1397 }
1398 OutSet* result = new OutSet(first_, remaining_);
1399 result->Set(value);
1400 successors()->Add(result);
1401 return result;
1402 }
1403
1404
1376 void OutSet::Set(unsigned value) { 1405 void OutSet::Set(unsigned value) {
1377 if (value < kFirstLimit) { 1406 if (value < kFirstLimit) {
1378 first_ |= (1 << value); 1407 first_ |= (1 << value);
1379 } else { 1408 } else {
1380 if (remaining_ == NULL) 1409 if (remaining_ == NULL)
1381 remaining_ = new ZoneList<unsigned>(1); 1410 remaining_ = new ZoneList<unsigned>(1);
1382 if (remaining_->is_empty() || !remaining_->Contains(value)) 1411 if (remaining_->is_empty() || !remaining_->Contains(value))
1383 remaining_->Add(value); 1412 remaining_->Add(value);
1384 } 1413 }
1385 } 1414 }
1386 1415
1387 1416
1388 bool OutSet::Get(unsigned value) { 1417 bool OutSet::Get(unsigned value) {
1389 if (value < kFirstLimit) { 1418 if (value < kFirstLimit) {
1390 return (first_ & (1 << value)) != 0; 1419 return (first_ & (1 << value)) != 0;
1391 } else if (remaining_ == NULL) { 1420 } else if (remaining_ == NULL) {
1392 return false; 1421 return false;
1393 } else { 1422 } else {
1394 return remaining_->Contains(value); 1423 return remaining_->Contains(value);
1395 } 1424 }
1396 } 1425 }
1397 1426
1398 1427
1399 OutSet OutSet::Clone() {
1400 if (remaining_ == NULL) {
1401 return OutSet(first_, NULL);
1402 } else {
1403 int length = remaining_->length();
1404 ZoneList<unsigned>* clone = new ZoneList<unsigned>(length);
1405 for (int i = 0; i < length; i++)
1406 clone->Add(remaining_->at(i));
1407 return OutSet(first_, clone);
1408 }
1409 }
1410
1411
1412 const uc16 DispatchTable::Config::kNoKey = unibrow::Utf8::kBadChar; 1428 const uc16 DispatchTable::Config::kNoKey = unibrow::Utf8::kBadChar;
1413 const DispatchTable::Entry DispatchTable::Config::kNoValue; 1429 const DispatchTable::Entry DispatchTable::Config::kNoValue;
1414 1430
1415 1431
1416 void DispatchTable::AddRange(CharacterRange full_range, int value) { 1432 void DispatchTable::AddRange(CharacterRange full_range, int value) {
1417 CharacterRange current = full_range; 1433 CharacterRange current = full_range;
1418 if (tree()->is_empty()) { 1434 if (tree()->is_empty()) {
1419 // If this is the first range we just insert into the table. 1435 // If this is the first range we just insert into the table.
1420 ZoneSplayTree<Config>::Locator loc; 1436 ZoneSplayTree<Config>::Locator loc;
1421 ASSERT_RESULT(tree()->Insert(current.from(), &loc)); 1437 ASSERT_RESULT(tree()->Insert(current.from(), &loc));
1422 loc.set_value(Entry(current.from(), current.to(), value)); 1438 loc.set_value(Entry(current.from(), current.to(), empty()->Extend(value)));
1423 return; 1439 return;
1424 } 1440 }
1425 // First see if there is a range to the left of this one that 1441 // First see if there is a range to the left of this one that
1426 // overlaps. 1442 // overlaps.
1427 ZoneSplayTree<Config>::Locator loc; 1443 ZoneSplayTree<Config>::Locator loc;
1428 if (tree()->FindGreatestLessThan(current.from(), &loc)) { 1444 if (tree()->FindGreatestLessThan(current.from(), &loc)) {
1429 Entry* entry = &loc.value(); 1445 Entry* entry = &loc.value();
1430 // If we've found a range that overlaps with this one, and it 1446 // If we've found a range that overlaps with this one, and it
1431 // starts strictly to the left of this one, we have to fix it 1447 // starts strictly to the left of this one, we have to fix it
1432 // because the following code only handles ranges that start on 1448 // because the following code only handles ranges that start on
1433 // or after the start point of the range we're adding. 1449 // or after the start point of the range we're adding.
1434 if (entry->from() < current.from() && entry->to() >= current.from()) { 1450 if (entry->from() < current.from() && entry->to() >= current.from()) {
1435 // Snap the overlapping range in half around the start point of 1451 // Snap the overlapping range in half around the start point of
1436 // the range we're adding. 1452 // the range we're adding.
1437 CharacterRange left(entry->from(), current.from() - 1); 1453 CharacterRange left(entry->from(), current.from() - 1);
1438 CharacterRange right(current.from(), entry->to()); 1454 CharacterRange right(current.from(), entry->to());
1439 // The left part of the overlapping range doesn't overlap. 1455 // The left part of the overlapping range doesn't overlap.
1440 // Truncate the whole entry to be just the left part. 1456 // Truncate the whole entry to be just the left part.
1441 entry->set_to(left.to()); 1457 entry->set_to(left.to());
1442 // The right part is the one that overlaps. We add this part 1458 // The right part is the one that overlaps. We add this part
1443 // to the map and let the next step deal with merging it with 1459 // to the map and let the next step deal with merging it with
1444 // the range we're adding. 1460 // the range we're adding.
1445 ZoneSplayTree<Config>::Locator loc; 1461 ZoneSplayTree<Config>::Locator loc;
1446 ASSERT_RESULT(tree()->Insert(right.from(), &loc)); 1462 ASSERT_RESULT(tree()->Insert(right.from(), &loc));
1447 loc.set_value(Entry(right.from(), 1463 loc.set_value(Entry(right.from(),
1448 right.to(), 1464 right.to(),
1449 entry->out_set().Clone())); 1465 entry->out_set()));
1450 } 1466 }
1451 } 1467 }
1452 while (current.is_valid()) { 1468 while (current.is_valid()) {
1453 if (tree()->FindLeastGreaterThan(current.from(), &loc) && 1469 if (tree()->FindLeastGreaterThan(current.from(), &loc) &&
1454 (loc.value().from() <= current.to())) { 1470 (loc.value().from() <= current.to())) {
1455 Entry* entry = &loc.value(); 1471 Entry* entry = &loc.value();
1456 // We have overlap. If there is space between the start point of 1472 // We have overlap. If there is space between the start point of
1457 // the range we're adding and where the overlapping range starts 1473 // the range we're adding and where the overlapping range starts
1458 // then we have to add a range covering just that space. 1474 // then we have to add a range covering just that space.
1459 if (current.from() < entry->from()) { 1475 if (current.from() < entry->from()) {
1460 ZoneSplayTree<Config>::Locator ins; 1476 ZoneSplayTree<Config>::Locator ins;
1461 ASSERT_RESULT(tree()->Insert(current.from(), &ins)); 1477 ASSERT_RESULT(tree()->Insert(current.from(), &ins));
1462 ins.set_value(Entry(current.from(), entry->from() - 1, value)); 1478 ins.set_value(Entry(current.from(),
1479 entry->from() - 1,
1480 empty()->Extend(value)));
1463 current.set_from(entry->from()); 1481 current.set_from(entry->from());
1464 } 1482 }
1465 ASSERT_EQ(current.from(), entry->from()); 1483 ASSERT_EQ(current.from(), entry->from());
1466 // If the overlapping range extends beyond the one we want to add 1484 // If the overlapping range extends beyond the one we want to add
1467 // we have to snap the right part off and add it separately. 1485 // we have to snap the right part off and add it separately.
1468 if (entry->to() > current.to()) { 1486 if (entry->to() > current.to()) {
1469 ZoneSplayTree<Config>::Locator ins; 1487 ZoneSplayTree<Config>::Locator ins;
1470 ASSERT_RESULT(tree()->Insert(current.to() + 1, &ins)); 1488 ASSERT_RESULT(tree()->Insert(current.to() + 1, &ins));
1471 ins.set_value(Entry(current.to() + 1, 1489 ins.set_value(Entry(current.to() + 1,
1472 entry->to(), 1490 entry->to(),
1473 entry->out_set().Clone())); 1491 entry->out_set()));
1474 entry->set_to(current.to()); 1492 entry->set_to(current.to());
1475 } 1493 }
1476 ASSERT(entry->to() <= current.to()); 1494 ASSERT(entry->to() <= current.to());
1477 // The overlapping range is now completely contained by the range 1495 // The overlapping range is now completely contained by the range
1478 // we're adding so we can just update it and move the start point 1496 // we're adding so we can just update it and move the start point
1479 // of the range we're adding just past it. 1497 // of the range we're adding just past it.
1480 entry->AddValue(value); 1498 entry->AddValue(value);
1481 current.set_from(entry->to() + 1); 1499 current.set_from(entry->to() + 1);
1482 } else { 1500 } else {
1483 // There is no overlap so we can just add the range 1501 // There is no overlap so we can just add the range
1484 ZoneSplayTree<Config>::Locator ins; 1502 ZoneSplayTree<Config>::Locator ins;
1485 ASSERT_RESULT(tree()->Insert(current.from(), &ins)); 1503 ASSERT_RESULT(tree()->Insert(current.from(), &ins));
1486 ins.set_value(Entry(current.from(), current.to(), value)); 1504 ins.set_value(Entry(current.from(),
1505 current.to(),
1506 empty()->Extend(value)));
1487 break; 1507 break;
1488 } 1508 }
1489 } 1509 }
1490 } 1510 }
1491 1511
1492 1512
1493 OutSet DispatchTable::Get(uc16 value) { 1513 OutSet* DispatchTable::Get(uc16 value) {
1494 ZoneSplayTree<Config>::Locator loc; 1514 ZoneSplayTree<Config>::Locator loc;
1495 if (!tree()->FindGreatestLessThan(value, &loc)) 1515 if (!tree()->FindGreatestLessThan(value, &loc))
1496 return OutSet::empty(); 1516 return empty();
1497 Entry* entry = &loc.value(); 1517 Entry* entry = &loc.value();
1498 if (value <= entry->to()) 1518 if (value <= entry->to())
1499 return entry->out_set(); 1519 return entry->out_set();
1500 else 1520 else
1501 return OutSet::empty(); 1521 return empty();
1502 } 1522 }
1503 1523
1504 1524
1505 // ------------------------------------------------------------------- 1525 // -------------------------------------------------------------------
1506 // Analysis 1526 // Analysis
1507 1527
1508 1528
1509 class Analysis: public NodeVisitor { 1529 class Analysis: public NodeVisitor {
1510 public: 1530 public:
1511 Analysis(RegExpCompiler* compiler) 1531 Analysis(RegExpCompiler* compiler)
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
1626 RegExpNode* RegExpEngine::Compile(RegExpParseResult* input) { 1646 RegExpNode* RegExpEngine::Compile(RegExpParseResult* input) {
1627 RegExpCompiler compiler(input->capture_count); 1647 RegExpCompiler compiler(input->capture_count);
1628 RegExpNode* node = compiler.Compile(input->tree, 1648 RegExpNode* node = compiler.Compile(input->tree,
1629 EndNode::GetAccept(), 1649 EndNode::GetAccept(),
1630 EndNode::GetBacktrack()); 1650 EndNode::GetBacktrack());
1631 return node; 1651 return node;
1632 } 1652 }
1633 1653
1634 1654
1635 }} // namespace v8::internal 1655 }} // namespace v8::internal
OLDNEW
« no previous file with comments | « src/jsregexp.h ('k') | src/jsregexp-inl.h » ('j') | test/cctest/test-regexp.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698