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

Side by Side Diff: src/jsregexp.cc

Issue 14892: Merge changes from bleeding_edge into experimental toiger branch.... (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/toiger/
Patch Set: Created 12 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/jsregexp.h ('k') | src/log.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
207 class OffsetsVector { 207 class OffsetsVector {
208 public: 208 public:
209 inline OffsetsVector(int num_registers) 209 inline OffsetsVector(int num_registers)
210 : offsets_vector_length_(num_registers) { 210 : offsets_vector_length_(num_registers) {
211 if (offsets_vector_length_ > kStaticOffsetsVectorSize) { 211 if (offsets_vector_length_ > kStaticOffsetsVectorSize) {
212 vector_ = NewArray<int>(offsets_vector_length_); 212 vector_ = NewArray<int>(offsets_vector_length_);
213 } else { 213 } else {
214 vector_ = static_offsets_vector_; 214 vector_ = static_offsets_vector_;
215 } 215 }
216 } 216 }
217
218
219 inline ~OffsetsVector() { 217 inline ~OffsetsVector() {
220 if (offsets_vector_length_ > kStaticOffsetsVectorSize) { 218 if (offsets_vector_length_ > kStaticOffsetsVectorSize) {
221 DeleteArray(vector_); 219 DeleteArray(vector_);
222 vector_ = NULL; 220 vector_ = NULL;
223 } 221 }
224 } 222 }
225 223 inline int* vector() { return vector_; }
226 224 inline int length() { return offsets_vector_length_; }
227 inline int* vector() {
228 return vector_;
229 }
230
231
232 inline int length() {
233 return offsets_vector_length_;
234 }
235 225
236 private: 226 private:
237 int* vector_; 227 int* vector_;
238 int offsets_vector_length_; 228 int offsets_vector_length_;
239 static const int kStaticOffsetsVectorSize = 50; 229 static const int kStaticOffsetsVectorSize = 50;
240 static int static_offsets_vector_[kStaticOffsetsVectorSize]; 230 static int static_offsets_vector_[kStaticOffsetsVectorSize];
241 }; 231 };
242 232
243 233
244 int OffsetsVector::static_offsets_vector_[ 234 int OffsetsVector::static_offsets_vector_[
(...skipping 551 matching lines...) Expand 10 before | Expand all | Expand 10 after
796 int previous_index = static_cast<int>(DoubleToInteger(index->Number())); 786 int previous_index = static_cast<int>(DoubleToInteger(index->Number()));
797 787
798 #ifdef DEBUG 788 #ifdef DEBUG
799 if (FLAG_trace_regexp_bytecodes) { 789 if (FLAG_trace_regexp_bytecodes) {
800 String* pattern = regexp->Pattern(); 790 String* pattern = regexp->Pattern();
801 PrintF("\n\nRegexp match: /%s/\n\n", *(pattern->ToCString())); 791 PrintF("\n\nRegexp match: /%s/\n\n", *(pattern->ToCString()));
802 PrintF("\n\nSubject string: '%s'\n\n", *(subject->ToCString())); 792 PrintF("\n\nSubject string: '%s'\n\n", *(subject->ToCString()));
803 } 793 }
804 #endif 794 #endif
805 LOG(RegExpExecEvent(regexp, previous_index, subject)); 795 LOG(RegExpExecEvent(regexp, previous_index, subject));
796
797 if (!subject->IsFlat(StringShape(*subject))) {
798 FlattenString(subject);
799 }
800
806 return IrregexpExecOnce(irregexp, 801 return IrregexpExecOnce(irregexp,
807 num_captures, 802 num_captures,
808 subject, 803 subject,
809 previous_index, 804 previous_index,
810 offsets.vector(), 805 offsets.vector(),
811 offsets.length()); 806 offsets.length());
812 } 807 }
813 808
814 809
815 Handle<Object> RegExpImpl::IrregexpExecGlobal(Handle<JSRegExp> regexp, 810 Handle<Object> RegExpImpl::IrregexpExecGlobal(Handle<JSRegExp> regexp,
(...skipping 14 matching lines...) Expand all
830 int previous_index = 0; 825 int previous_index = 0;
831 826
832 Handle<JSArray> result = Factory::NewJSArray(0); 827 Handle<JSArray> result = Factory::NewJSArray(0);
833 int i = 0; 828 int i = 0;
834 Handle<Object> matches; 829 Handle<Object> matches;
835 830
836 if (!subject->IsFlat(shape)) { 831 if (!subject->IsFlat(shape)) {
837 subject->Flatten(shape); 832 subject->Flatten(shape);
838 } 833 }
839 834
840 do { 835 while (true) {
841 if (previous_index > subject->length() || previous_index < 0) { 836 if (previous_index > subject->length() || previous_index < 0) {
842 // Per ECMA-262 15.10.6.2, if the previous index is greater than the 837 // Per ECMA-262 15.10.6.2, if the previous index is greater than the
843 // string length, there is no match. 838 // string length, there is no match.
844 matches = Factory::null_value(); 839 matches = Factory::null_value();
840 return result;
845 } else { 841 } else {
846 #ifdef DEBUG 842 #ifdef DEBUG
847 if (FLAG_trace_regexp_bytecodes) { 843 if (FLAG_trace_regexp_bytecodes) {
848 String* pattern = regexp->Pattern(); 844 String* pattern = regexp->Pattern();
849 PrintF("\n\nRegexp match: /%s/\n\n", *(pattern->ToCString())); 845 PrintF("\n\nRegexp match: /%s/\n\n", *(pattern->ToCString()));
850 PrintF("\n\nSubject string: '%s'\n\n", *(subject->ToCString())); 846 PrintF("\n\nSubject string: '%s'\n\n", *(subject->ToCString()));
851 } 847 }
852 #endif 848 #endif
853 LOG(RegExpExecEvent(regexp, previous_index, subject)); 849 LOG(RegExpExecEvent(regexp, previous_index, subject));
854 matches = IrregexpExecOnce(irregexp, 850 matches = IrregexpExecOnce(irregexp,
855 IrregexpNumberOfCaptures(irregexp), 851 IrregexpNumberOfCaptures(irregexp),
856 subject, 852 subject,
857 previous_index, 853 previous_index,
858 offsets.vector(), 854 offsets.vector(),
859 offsets.length()); 855 offsets.length());
860 856
861 if (matches->IsJSArray()) { 857 if (matches->IsJSArray()) {
862 SetElement(result, i, matches); 858 SetElement(result, i, matches);
863 i++; 859 i++;
864 previous_index = offsets.vector()[1]; 860 previous_index = offsets.vector()[1];
865 if (offsets.vector()[0] == offsets.vector()[1]) { 861 if (offsets.vector()[0] == offsets.vector()[1]) {
866 previous_index++; 862 previous_index++;
867 } 863 }
864 } else if (matches->IsNull()) {
865 return result;
866 } else {
867 return matches;
868 } 868 }
869 } 869 }
870 } while (matches->IsJSArray());
871
872 // If we exited the loop with an exception, throw it.
873 if (matches->IsNull()) {
874 // Exited loop normally.
875 return result;
876 } else {
877 // Exited loop with the exception in matches.
878 return matches;
879 } 870 }
880 } 871 }
881 872
882 873
883 Handle<Object> RegExpImpl::IrregexpExecOnce(Handle<FixedArray> irregexp, 874 Handle<Object> RegExpImpl::IrregexpExecOnce(Handle<FixedArray> irregexp,
884 int num_captures, 875 int num_captures,
885 Handle<String> subject, 876 Handle<String> subject,
886 int previous_index, 877 int previous_index,
887 int* offsets_vector, 878 int* offsets_vector,
888 int offsets_vector_length) { 879 int offsets_vector_length) {
880 ASSERT(subject->IsFlat(StringShape(*subject)));
889 bool rc; 881 bool rc;
890 882
891 int tag = Smi::cast(irregexp->get(kIrregexpImplementationIndex))->value(); 883 int tag = Smi::cast(irregexp->get(kIrregexpImplementationIndex))->value();
892 884
893 if (!subject->IsFlat(StringShape(*subject))) {
894 FlattenString(subject);
895 }
896
897 switch (tag) { 885 switch (tag) {
898 case RegExpMacroAssembler::kIA32Implementation: { 886 case RegExpMacroAssembler::kIA32Implementation: {
899 #ifndef ARM 887 #ifndef ARM
900 Handle<Code> code = IrregexpNativeCode(irregexp); 888 Handle<Code> code = IrregexpNativeCode(irregexp);
901 889
902 StringShape shape(*subject); 890 StringShape shape(*subject);
903 891
904 // Character offsets into string. 892 // Character offsets into string.
905 int start_offset = previous_index; 893 int start_offset = previous_index;
906 int end_offset = subject->length(shape); 894 int end_offset = subject->length(shape);
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
990 rc = false; 978 rc = false;
991 break; 979 break;
992 } 980 }
993 981
994 if (!rc) { 982 if (!rc) {
995 return Factory::null_value(); 983 return Factory::null_value();
996 } 984 }
997 985
998 Handle<FixedArray> array = Factory::NewFixedArray(2 * (num_captures+1)); 986 Handle<FixedArray> array = Factory::NewFixedArray(2 * (num_captures+1));
999 // The captures come in (start, end+1) pairs. 987 // The captures come in (start, end+1) pairs.
1000 for (int i = 0; i < 2 * (num_captures+1); i += 2) { 988 for (int i = 0; i < 2 * (num_captures + 1); i += 2) {
1001 array->set(i, Smi::FromInt(offsets_vector[i])); 989 array->set(i, Smi::FromInt(offsets_vector[i]));
1002 array->set(i+1, Smi::FromInt(offsets_vector[i+1])); 990 array->set(i + 1, Smi::FromInt(offsets_vector[i + 1]));
1003 } 991 }
1004 return Factory::NewJSArrayWithElements(array); 992 return Factory::NewJSArrayWithElements(array);
1005 } 993 }
1006 994
1007 995
1008 // ------------------------------------------------------------------- 996 // -------------------------------------------------------------------
1009 // Implmentation of the Irregexp regular expression engine. 997 // Implmentation of the Irregexp regular expression engine.
1010 // 998 //
1011 // The Irregexp regular expression engine is intended to be a complete 999 // The Irregexp regular expression engine is intended to be a complete
1012 // implementation of ECMAScript regular expressions. It generates either 1000 // implementation of ECMAScript regular expressions. It generates either
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
1186 1174
1187 1175
1188 TextElement TextElement::CharClass( 1176 TextElement TextElement::CharClass(
1189 RegExpCharacterClass* char_class) { 1177 RegExpCharacterClass* char_class) {
1190 TextElement result = TextElement(CHAR_CLASS); 1178 TextElement result = TextElement(CHAR_CLASS);
1191 result.data.u_char_class = char_class; 1179 result.data.u_char_class = char_class;
1192 return result; 1180 return result;
1193 } 1181 }
1194 1182
1195 1183
1184 int TextElement::length() {
1185 if (type == ATOM) {
1186 return data.u_atom->length();
1187 } else {
1188 ASSERT(type == CHAR_CLASS);
1189 return 1;
1190 }
1191 }
1192
1193
1196 DispatchTable* ChoiceNode::GetTable(bool ignore_case) { 1194 DispatchTable* ChoiceNode::GetTable(bool ignore_case) {
1197 if (table_ == NULL) { 1195 if (table_ == NULL) {
1198 table_ = new DispatchTable(); 1196 table_ = new DispatchTable();
1199 DispatchTableConstructor cons(table_, ignore_case); 1197 DispatchTableConstructor cons(table_, ignore_case);
1200 cons.BuildTable(this); 1198 cons.BuildTable(this);
1201 } 1199 }
1202 return table_; 1200 return table_;
1203 } 1201 }
1204 1202
1205 1203
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
1327 for (DeferredAction* action = actions_; 1325 for (DeferredAction* action = actions_;
1328 action != NULL; 1326 action != NULL;
1329 action = action->next()) { 1327 action = action->next()) {
1330 affected_registers->Set(action->reg()); 1328 affected_registers->Set(action->reg());
1331 if (action->reg() > max_register) max_register = action->reg(); 1329 if (action->reg() > max_register) max_register = action->reg();
1332 } 1330 }
1333 return max_register; 1331 return max_register;
1334 } 1332 }
1335 1333
1336 1334
1337 void GenerationVariant::PushAffectedRegisters(RegExpMacroAssembler* macro, 1335 void GenerationVariant::PushAffectedRegisters(RegExpMacroAssembler* assembler,
1338 int max_register, 1336 int max_register,
1339 OutSet& affected_registers) { 1337 OutSet& affected_registers) {
1340 for (int reg = 0; reg <= max_register; reg++) { 1338 for (int reg = 0; reg <= max_register; reg++) {
1341 if (affected_registers.Get(reg)) macro->PushRegister(reg); 1339 if (affected_registers.Get(reg)) assembler->PushRegister(reg);
1342 } 1340 }
1343 } 1341 }
1344 1342
1345 1343
1346 void GenerationVariant::RestoreAffectedRegisters(RegExpMacroAssembler* macro, 1344 void GenerationVariant::RestoreAffectedRegisters(
1347 int max_register, 1345 RegExpMacroAssembler* assembler,
1348 OutSet& affected_registers) { 1346 int max_register,
1347 OutSet& affected_registers) {
1349 for (int reg = max_register; reg >= 0; reg--) { 1348 for (int reg = max_register; reg >= 0; reg--) {
1350 if (affected_registers.Get(reg)) macro->PopRegister(reg); 1349 if (affected_registers.Get(reg)) assembler->PopRegister(reg);
1351 } 1350 }
1352 } 1351 }
1353 1352
1354 1353
1355 void GenerationVariant::PerformDeferredActions(RegExpMacroAssembler* macro, 1354 void GenerationVariant::PerformDeferredActions(RegExpMacroAssembler* assembler,
1356 int max_register, 1355 int max_register,
1357 OutSet& affected_registers) { 1356 OutSet& affected_registers) {
1358 for (int reg = 0; reg <= max_register; reg++) { 1357 for (int reg = 0; reg <= max_register; reg++) {
1359 if (!affected_registers.Get(reg)) { 1358 if (!affected_registers.Get(reg)) {
1360 continue; 1359 continue;
1361 } 1360 }
1362 int value = 0; 1361 int value = 0;
1363 bool absolute = false; 1362 bool absolute = false;
1364 int store_position = -1; 1363 int store_position = -1;
1365 // This is a little tricky because we are scanning the actions in reverse 1364 // This is a little tricky because we are scanning the actions in reverse
(...skipping 27 matching lines...) Expand all
1393 ASSERT_EQ(value, 0); 1392 ASSERT_EQ(value, 0);
1394 break; 1393 break;
1395 } 1394 }
1396 default: 1395 default:
1397 UNREACHABLE(); 1396 UNREACHABLE();
1398 break; 1397 break;
1399 } 1398 }
1400 } 1399 }
1401 } 1400 }
1402 if (store_position != -1) { 1401 if (store_position != -1) {
1403 macro->WriteCurrentPositionToRegister(reg, store_position); 1402 assembler->WriteCurrentPositionToRegister(reg, store_position);
1404 } else { 1403 } else {
1405 if (absolute) { 1404 if (absolute) {
1406 macro->SetRegister(reg, value); 1405 assembler->SetRegister(reg, value);
1407 } else { 1406 } else {
1408 if (value != 0) { 1407 if (value != 0) {
1409 macro->AdvanceRegister(reg, value); 1408 assembler->AdvanceRegister(reg, value);
1410 } 1409 }
1411 } 1410 }
1412 } 1411 }
1413 } 1412 }
1414 } 1413 }
1415 1414
1416 1415
1417 // This is called as we come into a loop choice node and some other tricky 1416 // This is called as we come into a loop choice node and some other tricky
1418 // nodes. It normalises the state of the code generator to ensure we can 1417 // nodes. It normalises the state of the code generator to ensure we can
1419 // generate generic code. 1418 // generate generic code.
1420 bool GenerationVariant::Flush(RegExpCompiler* compiler, RegExpNode* successor) { 1419 bool GenerationVariant::Flush(RegExpCompiler* compiler, RegExpNode* successor) {
1421 RegExpMacroAssembler* macro = compiler->macro_assembler(); 1420 RegExpMacroAssembler* assembler = compiler->macro_assembler();
1422 1421
1423 ASSERT(actions_ != NULL || cp_offset_ != 0 || backtrack() != NULL); 1422 ASSERT(actions_ != NULL ||
1423 cp_offset_ != 0 ||
1424 backtrack() != NULL ||
1425 characters_preloaded_ != 0 ||
1426 quick_check_performed_.characters() != 0);
1424 1427
1425 if (actions_ == NULL && backtrack() == NULL) { 1428 if (actions_ == NULL && backtrack() == NULL) {
1426 // Here we just have some deferred cp advances to fix and we are back to 1429 // Here we just have some deferred cp advances to fix and we are back to
1427 // a normal situation. 1430 // a normal situation. We may also have to forget some information gained
1428 macro->AdvanceCurrentPosition(cp_offset_); 1431 // through a quick check that was already performed.
1432 if (cp_offset_ != 0) assembler->AdvanceCurrentPosition(cp_offset_);
1429 // Create a new trivial state and generate the node with that. 1433 // Create a new trivial state and generate the node with that.
1430 GenerationVariant new_state; 1434 GenerationVariant new_state;
1431 return successor->Emit(compiler, &new_state); 1435 return successor->Emit(compiler, &new_state);
1432 } 1436 }
1433 1437
1434 // Generate deferred actions here along with code to undo them again. 1438 // Generate deferred actions here along with code to undo them again.
1435 OutSet affected_registers; 1439 OutSet affected_registers;
1436 int max_register = FindAffectedRegisters(&affected_registers); 1440 int max_register = FindAffectedRegisters(&affected_registers);
1437 PushAffectedRegisters(macro, max_register, affected_registers); 1441 PushAffectedRegisters(assembler, max_register, affected_registers);
1438 PerformDeferredActions(macro, max_register, affected_registers); 1442 PerformDeferredActions(assembler, max_register, affected_registers);
1439 if (backtrack() != NULL) { 1443 if (backtrack() != NULL) {
1440 // Here we have a concrete backtrack location. These are set up by choice 1444 // Here we have a concrete backtrack location. These are set up by choice
1441 // nodes and so they indicate that we have a deferred save of the current 1445 // nodes and so they indicate that we have a deferred save of the current
1442 // position which we may need to emit here. 1446 // position which we may need to emit here.
1443 macro->PushCurrentPosition(); 1447 assembler->PushCurrentPosition();
1444 } 1448 }
1445 if (cp_offset_ != 0) { 1449 if (cp_offset_ != 0) {
1446 macro->AdvanceCurrentPosition(cp_offset_); 1450 assembler->AdvanceCurrentPosition(cp_offset_);
1447 } 1451 }
1448 1452
1449 // Create a new trivial state and generate the node with that. 1453 // Create a new trivial state and generate the node with that.
1450 Label undo; 1454 Label undo;
1451 macro->PushBacktrack(&undo); 1455 assembler->PushBacktrack(&undo);
1452 GenerationVariant new_state; 1456 GenerationVariant new_state;
1453 bool ok = successor->Emit(compiler, &new_state); 1457 bool ok = successor->Emit(compiler, &new_state);
1454 1458
1455 // On backtrack we need to restore state. 1459 // On backtrack we need to restore state.
1456 macro->Bind(&undo); 1460 assembler->Bind(&undo);
1457 if (!ok) return false; 1461 if (!ok) return false;
1458 if (backtrack() != NULL) { 1462 if (backtrack() != NULL) {
1459 macro->PopCurrentPosition(); 1463 assembler->PopCurrentPosition();
1460 } 1464 }
1461 RestoreAffectedRegisters(macro, max_register, affected_registers); 1465 RestoreAffectedRegisters(assembler, max_register, affected_registers);
1462 if (backtrack() == NULL) { 1466 if (backtrack() == NULL) {
1463 macro->Backtrack(); 1467 assembler->Backtrack();
1464 } else { 1468 } else {
1465 macro->GoTo(backtrack()); 1469 assembler->GoTo(backtrack());
1466 } 1470 }
1467 1471
1468 return true; 1472 return true;
1469 } 1473 }
1470 1474
1471 1475
1472 void EndNode::EmitInfoChecks(RegExpMacroAssembler* macro, 1476 void EndNode::EmitInfoChecks(RegExpMacroAssembler* assembler,
1473 GenerationVariant* variant) { 1477 GenerationVariant* variant) {
1474 if (info()->at_end) { 1478 if (info()->at_end) {
1475 Label succeed; 1479 Label succeed;
1476 // LoadCurrentCharacter will go to the label if we are at the end of the 1480 // LoadCurrentCharacter will go to the label if we are at the end of the
1477 // input string. 1481 // input string.
1478 macro->LoadCurrentCharacter(0, &succeed); 1482 assembler->LoadCurrentCharacter(0, &succeed);
1479 macro->GoTo(variant->backtrack()); 1483 assembler->GoTo(variant->backtrack());
1480 macro->Bind(&succeed); 1484 assembler->Bind(&succeed);
1481 } 1485 }
1482 } 1486 }
1483 1487
1484 1488
1485 bool NegativeSubmatchSuccess::Emit(RegExpCompiler* compiler, 1489 bool NegativeSubmatchSuccess::Emit(RegExpCompiler* compiler,
1486 GenerationVariant* variant) { 1490 GenerationVariant* variant) {
1487 if (!variant->is_trivial()) { 1491 if (!variant->is_trivial()) {
1488 return variant->Flush(compiler, this); 1492 return variant->Flush(compiler, this);
1489 } 1493 }
1490 RegExpMacroAssembler* macro = compiler->macro_assembler(); 1494 RegExpMacroAssembler* assembler = compiler->macro_assembler();
1491 if (!label()->is_bound()) { 1495 if (!label()->is_bound()) {
1492 macro->Bind(label()); 1496 assembler->Bind(label());
1493 } 1497 }
1494 EmitInfoChecks(macro, variant); 1498 EmitInfoChecks(assembler, variant);
1495 macro->ReadCurrentPositionFromRegister(current_position_register_); 1499 assembler->ReadCurrentPositionFromRegister(current_position_register_);
1496 macro->ReadStackPointerFromRegister(stack_pointer_register_); 1500 assembler->ReadStackPointerFromRegister(stack_pointer_register_);
1497 // Now that we have unwound the stack we find at the top of the stack the 1501 // Now that we have unwound the stack we find at the top of the stack the
1498 // backtrack that the BeginSubmatch node got. 1502 // backtrack that the BeginSubmatch node got.
1499 macro->Backtrack(); 1503 assembler->Backtrack();
1500 return true; 1504 return true;
1501 } 1505 }
1502 1506
1503 1507
1504 bool EndNode::Emit(RegExpCompiler* compiler, GenerationVariant* variant) { 1508 bool EndNode::Emit(RegExpCompiler* compiler, GenerationVariant* variant) {
1505 if (!variant->is_trivial()) { 1509 if (!variant->is_trivial()) {
1506 return variant->Flush(compiler, this); 1510 return variant->Flush(compiler, this);
1507 } 1511 }
1508 RegExpMacroAssembler* macro = compiler->macro_assembler(); 1512 RegExpMacroAssembler* assembler = compiler->macro_assembler();
1509 if (!label()->is_bound()) { 1513 if (!label()->is_bound()) {
1510 macro->Bind(label()); 1514 assembler->Bind(label());
1511 } 1515 }
1512 switch (action_) { 1516 switch (action_) {
1513 case ACCEPT: 1517 case ACCEPT:
1514 EmitInfoChecks(macro, variant); 1518 EmitInfoChecks(assembler, variant);
1515 macro->Succeed(); 1519 assembler->Succeed();
1516 return true; 1520 return true;
1517 case BACKTRACK: 1521 case BACKTRACK:
1518 ASSERT(!info()->at_end); 1522 ASSERT(!info()->at_end);
1519 macro->GoTo(variant->backtrack()); 1523 assembler->GoTo(variant->backtrack());
1520 return true; 1524 return true;
1521 case NEGATIVE_SUBMATCH_SUCCESS: 1525 case NEGATIVE_SUBMATCH_SUCCESS:
1522 // This case is handled in a different virtual method. 1526 // This case is handled in a different virtual method.
1523 UNREACHABLE(); 1527 UNREACHABLE();
1524 } 1528 }
1525 UNIMPLEMENTED(); 1529 UNIMPLEMENTED();
1526 return false; 1530 return false;
1527 } 1531 }
1528 1532
1529 1533
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
1579 1583
1580 1584
1581 #define DEFINE_ACCEPT(Type) \ 1585 #define DEFINE_ACCEPT(Type) \
1582 void Type##Node::Accept(NodeVisitor* visitor) { \ 1586 void Type##Node::Accept(NodeVisitor* visitor) { \
1583 visitor->Visit##Type(this); \ 1587 visitor->Visit##Type(this); \
1584 } 1588 }
1585 FOR_EACH_NODE_TYPE(DEFINE_ACCEPT) 1589 FOR_EACH_NODE_TYPE(DEFINE_ACCEPT)
1586 #undef DEFINE_ACCEPT 1590 #undef DEFINE_ACCEPT
1587 1591
1588 1592
1593 void LoopChoiceNode::Accept(NodeVisitor* visitor) {
1594 visitor->VisitLoopChoice(this);
1595 }
1596
1597
1589 // ------------------------------------------------------------------- 1598 // -------------------------------------------------------------------
1590 // Emit code. 1599 // Emit code.
1591 1600
1592 1601
1593 void ChoiceNode::GenerateGuard(RegExpMacroAssembler* macro_assembler, 1602 void ChoiceNode::GenerateGuard(RegExpMacroAssembler* macro_assembler,
1594 Guard* guard, 1603 Guard* guard,
1595 GenerationVariant* variant) { 1604 GenerationVariant* variant) {
1596 switch (guard->op()) { 1605 switch (guard->op()) {
1597 case Guard::LT: 1606 case Guard::LT:
1598 ASSERT(!variant->mentions_reg(guard->reg())); 1607 ASSERT(!variant->mentions_reg(guard->reg()));
1599 macro_assembler->IfRegisterGE(guard->reg(), 1608 macro_assembler->IfRegisterGE(guard->reg(),
1600 guard->value(), 1609 guard->value(),
1601 variant->backtrack()); 1610 variant->backtrack());
1602 break; 1611 break;
1603 case Guard::GEQ: 1612 case Guard::GEQ:
1604 ASSERT(!variant->mentions_reg(guard->reg())); 1613 ASSERT(!variant->mentions_reg(guard->reg()));
1605 macro_assembler->IfRegisterLT(guard->reg(), 1614 macro_assembler->IfRegisterLT(guard->reg(),
1606 guard->value(), 1615 guard->value(),
1607 variant->backtrack()); 1616 variant->backtrack());
1608 break; 1617 break;
1609 } 1618 }
1610 } 1619 }
1611 1620
1612 1621
1613 static unibrow::Mapping<unibrow::Ecma262UnCanonicalize> uncanonicalize; 1622 static unibrow::Mapping<unibrow::Ecma262UnCanonicalize> uncanonicalize;
1614 static unibrow::Mapping<unibrow::CanonicalizationRange> canonrange; 1623 static unibrow::Mapping<unibrow::CanonicalizationRange> canonrange;
1615 1624
1616 1625
1617 static inline void EmitAtomNonLetters( 1626 // Only emits non-letters (things that don't have case). Only used for case
1627 // independent matches.
1628 static inline bool EmitAtomNonLetter(
1618 RegExpMacroAssembler* macro_assembler, 1629 RegExpMacroAssembler* macro_assembler,
1619 TextElement elm, 1630 uc16 c,
1620 Vector<const uc16> quarks,
1621 Label* on_failure, 1631 Label* on_failure,
1622 int cp_offset, 1632 int cp_offset,
1623 bool check_offset) { 1633 bool check,
1634 bool preloaded) {
1624 unibrow::uchar chars[unibrow::Ecma262UnCanonicalize::kMaxWidth]; 1635 unibrow::uchar chars[unibrow::Ecma262UnCanonicalize::kMaxWidth];
1625 // It is vital that this loop is backwards due to the unchecked character 1636 int length = uncanonicalize.get(c, '\0', chars);
1626 // load below. 1637 bool checked = false;
1627 for (int i = quarks.length() - 1; i >= 0; i--) { 1638 if (length <= 1) {
1628 uc16 c = quarks[i]; 1639 if (!preloaded) {
1629 int length = uncanonicalize.get(c, '\0', chars); 1640 macro_assembler->LoadCurrentCharacter(cp_offset, on_failure, check);
1630 if (length <= 1) { 1641 checked = check;
1631 if (check_offset && i == quarks.length() - 1) {
1632 macro_assembler->LoadCurrentCharacter(cp_offset + i, on_failure);
1633 } else {
1634 // Here we don't need to check against the end of the input string
1635 // since this character lies before a character that matched.
1636 macro_assembler->LoadCurrentCharacterUnchecked(cp_offset + i);
1637 }
1638 macro_assembler->CheckNotCharacter(c, on_failure);
1639 } 1642 }
1643 macro_assembler->CheckNotCharacter(c, on_failure);
1640 } 1644 }
1645 return checked;
1641 } 1646 }
1642 1647
1643 1648
1644 static bool ShortCutEmitCharacterPair(RegExpMacroAssembler* macro_assembler, 1649 static bool ShortCutEmitCharacterPair(RegExpMacroAssembler* macro_assembler,
1645 uc16 c1, 1650 uc16 c1,
1646 uc16 c2, 1651 uc16 c2,
1647 Label* on_failure) { 1652 Label* on_failure) {
1648 uc16 exor = c1 ^ c2; 1653 uc16 exor = c1 ^ c2;
1649 // Check whether exor has only one bit set. 1654 // Check whether exor has only one bit set.
1650 if (((exor - 1) & exor) == 0) { 1655 if (((exor - 1) & exor) == 0) {
1651 // If c1 and c2 differ only by one bit. 1656 // If c1 and c2 differ only by one bit.
1652 // Ecma262UnCanonicalize always gives the highest number last. 1657 // Ecma262UnCanonicalize always gives the highest number last.
1653 ASSERT(c2 > c1); 1658 ASSERT(c2 > c1);
1654 macro_assembler->CheckNotCharacterAfterOr(c2, exor, on_failure); 1659 uc16 mask = String::kMaxUC16CharCode ^ exor;
1660 macro_assembler->CheckNotCharacterAfterAnd(c1, mask, on_failure);
1655 return true; 1661 return true;
1656 } 1662 }
1657 ASSERT(c2 > c1); 1663 ASSERT(c2 > c1);
1658 uc16 diff = c2 - c1; 1664 uc16 diff = c2 - c1;
1659 if (((diff - 1) & diff) == 0 && c1 >= diff) { 1665 if (((diff - 1) & diff) == 0 && c1 >= diff) {
1660 // If the characters differ by 2^n but don't differ by one bit then 1666 // If the characters differ by 2^n but don't differ by one bit then
1661 // subtract the difference from the found character, then do the or 1667 // subtract the difference from the found character, then do the or
1662 // trick. We avoid the theoretical case where negative numbers are 1668 // trick. We avoid the theoretical case where negative numbers are
1663 // involved in order to simplify code generation. 1669 // involved in order to simplify code generation.
1664 macro_assembler->CheckNotCharacterAfterMinusOr(c2 - diff, 1670 uc16 mask = String::kMaxUC16CharCode ^ diff;
1665 diff, 1671 macro_assembler->CheckNotCharacterAfterMinusAnd(c1 - diff,
1666 on_failure); 1672 diff,
1673 mask,
1674 on_failure);
1667 return true; 1675 return true;
1668 } 1676 }
1669 return false; 1677 return false;
1670 } 1678 }
1671 1679
1672 1680
1673 static inline void EmitAtomLetters( 1681 // Only emits letters (things that have case). Only used for case independent
1682 // matches.
1683 static inline bool EmitAtomLetter(
1674 RegExpMacroAssembler* macro_assembler, 1684 RegExpMacroAssembler* macro_assembler,
1675 TextElement elm, 1685 uc16 c,
1676 Vector<const uc16> quarks,
1677 Label* on_failure, 1686 Label* on_failure,
1678 int cp_offset, 1687 int cp_offset,
1679 bool check_offset) { 1688 bool check,
1689 bool preloaded) {
1680 unibrow::uchar chars[unibrow::Ecma262UnCanonicalize::kMaxWidth]; 1690 unibrow::uchar chars[unibrow::Ecma262UnCanonicalize::kMaxWidth];
1681 // It is vital that this loop is backwards due to the unchecked character 1691 int length = uncanonicalize.get(c, '\0', chars);
1682 // load below. 1692 if (length <= 1) return false;
1683 for (int i = quarks.length() - 1; i >= 0; i--) { 1693 // We may not need to check against the end of the input string
1684 uc16 c = quarks[i]; 1694 // if this character lies before a character that matched.
1685 int length = uncanonicalize.get(c, '\0', chars); 1695 if (!preloaded) {
1686 if (length <= 1) continue; 1696 macro_assembler->LoadCurrentCharacter(cp_offset, on_failure, check);
1687 if (check_offset && i == quarks.length() - 1) { 1697 }
1688 macro_assembler->LoadCurrentCharacter(cp_offset + i, on_failure); 1698 Label ok;
1689 } else { 1699 ASSERT(unibrow::Ecma262UnCanonicalize::kMaxWidth == 4);
1690 // Here we don't need to check against the end of the input string 1700 switch (length) {
1691 // since this character lies before a character that matched. 1701 case 2: {
1692 macro_assembler->LoadCurrentCharacterUnchecked(cp_offset + i); 1702 if (ShortCutEmitCharacterPair(macro_assembler,
1703 chars[0],
1704 chars[1],
1705 on_failure)) {
1706 } else {
1707 macro_assembler->CheckCharacter(chars[0], &ok);
1708 macro_assembler->CheckNotCharacter(chars[1], on_failure);
1709 macro_assembler->Bind(&ok);
1710 }
1711 break;
1693 } 1712 }
1694 Label ok; 1713 case 4:
1695 ASSERT(unibrow::Ecma262UnCanonicalize::kMaxWidth == 4); 1714 macro_assembler->CheckCharacter(chars[3], &ok);
1696 switch (length) { 1715 // Fall through!
1697 case 2: { 1716 case 3:
1698 if (ShortCutEmitCharacterPair(macro_assembler, 1717 macro_assembler->CheckCharacter(chars[0], &ok);
1699 chars[0], 1718 macro_assembler->CheckCharacter(chars[1], &ok);
1700 chars[1], 1719 macro_assembler->CheckNotCharacter(chars[2], on_failure);
1701 on_failure)) { 1720 macro_assembler->Bind(&ok);
1702 } else { 1721 break;
1703 macro_assembler->CheckCharacter(chars[0], &ok); 1722 default:
1704 macro_assembler->CheckNotCharacter(chars[1], on_failure); 1723 UNREACHABLE();
1705 macro_assembler->Bind(&ok); 1724 break;
1706 }
1707 break;
1708 }
1709 case 4:
1710 macro_assembler->CheckCharacter(chars[3], &ok);
1711 // Fall through!
1712 case 3:
1713 macro_assembler->CheckCharacter(chars[0], &ok);
1714 macro_assembler->CheckCharacter(chars[1], &ok);
1715 macro_assembler->CheckNotCharacter(chars[2], on_failure);
1716 macro_assembler->Bind(&ok);
1717 break;
1718 default:
1719 UNREACHABLE();
1720 break;
1721 }
1722 } 1725 }
1726 return true;
1723 } 1727 }
1724 1728
1725 1729
1726 static void EmitCharClass(RegExpMacroAssembler* macro_assembler, 1730 static void EmitCharClass(RegExpMacroAssembler* macro_assembler,
1727 RegExpCharacterClass* cc, 1731 RegExpCharacterClass* cc,
1728 int cp_offset, 1732 int cp_offset,
1729 Label* on_failure, 1733 Label* on_failure,
1730 bool check_offset, 1734 bool check_offset,
1731 bool ascii) { 1735 bool ascii,
1736 bool preloaded) {
1732 ZoneList<CharacterRange>* ranges = cc->ranges(); 1737 ZoneList<CharacterRange>* ranges = cc->ranges();
1733 int max_char; 1738 int max_char;
1734 if (ascii) { 1739 if (ascii) {
1735 max_char = String::kMaxAsciiCharCode; 1740 max_char = String::kMaxAsciiCharCode;
1736 } else { 1741 } else {
1737 max_char = String::kMaxUC16CharCode; 1742 max_char = String::kMaxUC16CharCode;
1738 } 1743 }
1739 1744
1740 Label success; 1745 Label success;
1741 1746
(...skipping 25 matching lines...) Expand all
1767 ranges->at(0).IsEverything(max_char)) { 1772 ranges->at(0).IsEverything(max_char)) {
1768 // This is a common case hit by non-anchored expressions. 1773 // This is a common case hit by non-anchored expressions.
1769 // TODO(erikcorry): We should have a macro assembler instruction that just 1774 // TODO(erikcorry): We should have a macro assembler instruction that just
1770 // checks for end of string without loading the character. 1775 // checks for end of string without loading the character.
1771 if (check_offset) { 1776 if (check_offset) {
1772 macro_assembler->LoadCurrentCharacter(cp_offset, on_failure); 1777 macro_assembler->LoadCurrentCharacter(cp_offset, on_failure);
1773 } 1778 }
1774 return; 1779 return;
1775 } 1780 }
1776 1781
1777 if (check_offset) { 1782 if (!preloaded) {
1778 macro_assembler->LoadCurrentCharacter(cp_offset, on_failure); 1783 macro_assembler->LoadCurrentCharacter(cp_offset, on_failure, check_offset);
1779 } else {
1780 // Here we don't need to check against the end of the input string
1781 // since this character lies before a character that matched.
1782 macro_assembler->LoadCurrentCharacterUnchecked(cp_offset);
1783 } 1784 }
1784 1785
1785 for (int i = 0; i <= last_valid_range; i++) { 1786 for (int i = 0; i < last_valid_range; i++) {
1786 CharacterRange& range = ranges->at(i); 1787 CharacterRange& range = ranges->at(i);
1787 Label next_range; 1788 Label next_range;
1788 uc16 from = range.from(); 1789 uc16 from = range.from();
1789 uc16 to = range.to(); 1790 uc16 to = range.to();
1790 if (from > max_char) { 1791 if (from > max_char) {
1791 continue; 1792 continue;
1792 } 1793 }
1793 if (to > max_char) to = max_char; 1794 if (to > max_char) to = max_char;
1794 if (to == from) { 1795 if (to == from) {
1795 macro_assembler->CheckCharacter(to, char_is_in_class); 1796 macro_assembler->CheckCharacter(to, char_is_in_class);
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1836 } else { 1837 } else {
1837 if (cc->is_negated()) { 1838 if (cc->is_negated()) {
1838 macro_assembler->GoTo(on_failure); 1839 macro_assembler->GoTo(on_failure);
1839 } 1840 }
1840 } 1841 }
1841 } 1842 }
1842 macro_assembler->Bind(&success); 1843 macro_assembler->Bind(&success);
1843 } 1844 }
1844 1845
1845 1846
1847 RegExpNode::~RegExpNode() {
1848 }
1849
1850
1846 RegExpNode::LimitResult RegExpNode::LimitVersions(RegExpCompiler* compiler, 1851 RegExpNode::LimitResult RegExpNode::LimitVersions(RegExpCompiler* compiler,
1847 GenerationVariant* variant) { 1852 GenerationVariant* variant) {
1848 // TODO(erikcorry): Implement support. 1853 // TODO(erikcorry): Implement support.
1849 if (info_.follows_word_interest || 1854 if (info_.follows_word_interest ||
1850 info_.follows_newline_interest || 1855 info_.follows_newline_interest ||
1851 info_.follows_start_interest) { 1856 info_.follows_start_interest) {
1852 return FAIL; 1857 return FAIL;
1853 } 1858 }
1854 1859
1855 // If we are generating a greedy loop then don't stop and don't reuse code. 1860 // If we are generating a greedy loop then don't stop and don't reuse code.
(...skipping 30 matching lines...) Expand all
1886 } 1891 }
1887 1892
1888 // If we get here there have been too many variants generated or recursion 1893 // If we get here there have been too many variants generated or recursion
1889 // is too deep. Time to switch to a generic version. The code for 1894 // is too deep. Time to switch to a generic version. The code for
1890 // generic versions above can handle deep recursion properly. 1895 // generic versions above can handle deep recursion properly.
1891 bool ok = variant->Flush(compiler, this); 1896 bool ok = variant->Flush(compiler, this);
1892 return ok ? DONE : FAIL; 1897 return ok ? DONE : FAIL;
1893 } 1898 }
1894 1899
1895 1900
1901 int ActionNode::EatsAtLeast(int recursion_depth) {
1902 if (recursion_depth > RegExpCompiler::kMaxRecursion) return 0;
1903 if (type_ == POSITIVE_SUBMATCH_SUCCESS) return 0; // Rewinds input!
1904 return on_success()->EatsAtLeast(recursion_depth + 1);
1905 }
1906
1907
1908 int TextNode::EatsAtLeast(int recursion_depth) {
1909 int answer = Length();
1910 if (answer >= 4) return answer;
1911 if (recursion_depth > RegExpCompiler::kMaxRecursion) return answer;
1912 return answer + on_success()->EatsAtLeast(recursion_depth + 1);
1913 }
1914
1915
1916 int ChoiceNode::EatsAtLeastHelper(int recursion_depth,
1917 RegExpNode* ignore_this_node) {
1918 if (recursion_depth > RegExpCompiler::kMaxRecursion) return 0;
1919 int min = 100;
1920 int choice_count = alternatives_->length();
1921 for (int i = 0; i < choice_count; i++) {
1922 RegExpNode* node = alternatives_->at(i).node();
1923 if (node == ignore_this_node) continue;
1924 int node_eats_at_least = node->EatsAtLeast(recursion_depth + 1);
1925 if (node_eats_at_least < min) min = node_eats_at_least;
1926 }
1927 return min;
1928 }
1929
1930
1931 int LoopChoiceNode::EatsAtLeast(int recursion_depth) {
1932 return EatsAtLeastHelper(recursion_depth, loop_node_);
1933 }
1934
1935
1936 int ChoiceNode::EatsAtLeast(int recursion_depth) {
1937 return EatsAtLeastHelper(recursion_depth, NULL);
1938 }
1939
1940
1941 // Takes the left-most 1-bit and smears it out, setting all bits to its right.
1942 static inline uint32_t SmearBitsRight(uint32_t v) {
1943 v |= v >> 1;
1944 v |= v >> 2;
1945 v |= v >> 4;
1946 v |= v >> 8;
1947 v |= v >> 16;
1948 return v;
1949 }
1950
1951
1952 bool QuickCheckDetails::Rationalize(bool asc) {
1953 bool found_useful_op = false;
1954 uint32_t char_mask;
1955 if (asc) {
1956 char_mask = String::kMaxAsciiCharCode;
1957 } else {
1958 char_mask = String::kMaxUC16CharCode;
1959 }
1960 mask_ = 0;
1961 value_ = 0;
1962 int char_shift = 0;
1963 for (int i = 0; i < characters_; i++) {
1964 Position* pos = &positions_[i];
1965 if ((pos->mask & String::kMaxAsciiCharCode) != 0) {
1966 found_useful_op = true;
1967 }
1968 mask_ |= (pos->mask & char_mask) << char_shift;
1969 value_ |= (pos->value & char_mask) << char_shift;
1970 char_shift += asc ? 8 : 16;
1971 }
1972 return found_useful_op;
1973 }
1974
1975
1976 bool RegExpNode::EmitQuickCheck(RegExpCompiler* compiler,
1977 GenerationVariant* variant,
1978 bool preload_has_checked_bounds,
1979 Label* on_possible_success,
1980 QuickCheckDetails* details,
1981 bool fall_through_on_failure) {
1982 if (details->characters() == 0) return false;
1983 GetQuickCheckDetails(details, compiler, 0);
1984 if (!details->Rationalize(compiler->ascii())) return false;
1985 uint32_t mask = details->mask();
1986 uint32_t value = details->value();
1987
1988 RegExpMacroAssembler* assembler = compiler->macro_assembler();
1989
1990 if (variant->characters_preloaded() != details->characters()) {
1991 assembler->LoadCurrentCharacter(variant->cp_offset(),
1992 variant->backtrack(),
1993 !preload_has_checked_bounds,
1994 details->characters());
1995 }
1996
1997
1998 bool need_mask = true;
1999
2000 if (details->characters() == 1) {
2001 // If number of characters preloaded is 1 then we used a byte or 16 bit
2002 // load so the value is already masked down.
2003 uint32_t char_mask;
2004 if (compiler->ascii()) {
2005 char_mask = String::kMaxAsciiCharCode;
2006 } else {
2007 char_mask = String::kMaxUC16CharCode;
2008 }
2009 if ((mask & char_mask) == char_mask) need_mask = false;
2010 } else {
2011 // For 2-character preloads in ASCII mode we also use a 16 bit load with
2012 // zero extend.
2013 if (details->characters() == 2 && compiler->ascii()) {
2014 if ((mask & 0xffff) == 0xffff) need_mask = false;
2015 } else {
2016 if (mask == 0xffffffff) need_mask = false;
2017 }
2018 }
2019
2020 if (fall_through_on_failure) {
2021 if (need_mask) {
2022 assembler->CheckCharacterAfterAnd(value, mask, on_possible_success);
2023 } else {
2024 assembler->CheckCharacter(value, on_possible_success);
2025 }
2026 } else {
2027 if (need_mask) {
2028 assembler->CheckNotCharacterAfterAnd(value, mask, variant->backtrack());
2029 } else {
2030 assembler->CheckNotCharacter(value, variant->backtrack());
2031 }
2032 }
2033 return true;
2034 }
2035
2036
2037 // Here is the meat of GetQuickCheckDetails (see also the comment on the
2038 // super-class in the .h file).
2039 //
2040 // We iterate along the text object, building up for each character a
2041 // mask and value that can be used to test for a quick failure to match.
2042 // The masks and values for the positions will be combined into a single
2043 // machine word for the current character width in order to be used in
2044 // generating a quick check.
2045 void TextNode::GetQuickCheckDetails(QuickCheckDetails* details,
2046 RegExpCompiler* compiler,
2047 int characters_filled_in) {
2048 ASSERT(characters_filled_in < details->characters());
2049 int characters = details->characters();
2050 int char_mask;
2051 int char_shift;
2052 if (compiler->ascii()) {
2053 char_mask = String::kMaxAsciiCharCode;
2054 char_shift = 8;
2055 } else {
2056 char_mask = String::kMaxUC16CharCode;
2057 char_shift = 16;
2058 }
2059 for (int k = 0; k < elms_->length(); k++) {
2060 TextElement elm = elms_->at(k);
2061 if (elm.type == TextElement::ATOM) {
2062 Vector<const uc16> quarks = elm.data.u_atom->data();
2063 for (int i = 0; i < characters && i < quarks.length(); i++) {
2064 QuickCheckDetails::Position* pos =
2065 details->positions(characters_filled_in);
2066 if (compiler->ignore_case()) {
2067 unibrow::uchar chars[unibrow::Ecma262UnCanonicalize::kMaxWidth];
2068 uc16 c = quarks[i];
2069 int length = uncanonicalize.get(c, '\0', chars);
2070 if (length < 2) {
2071 // This letter has no case equivalents, so it's nice and simple
2072 // and the mask-compare will determine definitely whether we have
2073 // a match at this character position.
2074 pos->mask = char_mask;
2075 pos->value = c;
2076 pos->determines_perfectly = true;
2077 } else {
2078 uint32_t common_bits = char_mask;
2079 uint32_t bits = chars[0];
2080 for (int j = 1; j < length; j++) {
2081 uint32_t differing_bits = ((chars[j] & common_bits) ^ bits);
2082 common_bits ^= differing_bits;
2083 bits &= common_bits;
2084 }
2085 // If length is 2 and common bits has only one zero in it then
2086 // our mask and compare instruction will determine definitely
2087 // whether we have a match at this character position. Otherwise
2088 // it can only be an approximate check.
2089 uint32_t one_zero = (common_bits | ~char_mask);
2090 if (length == 2 && ((~one_zero) & ((~one_zero) - 1)) == 0) {
2091 pos->determines_perfectly = true;
2092 }
2093 pos->mask = common_bits;
2094 pos->value = bits;
2095 }
2096 } else {
2097 // Don't ignore case. Nice simple case where the mask-compare will
2098 // determine definitely whether we have a match at this character
2099 // position.
2100 pos->mask = char_mask;
2101 pos->value = quarks[i];
2102 pos->determines_perfectly = true;
2103 }
2104 characters_filled_in++;
2105 ASSERT(characters_filled_in <= details->characters());
2106 if (characters_filled_in == details->characters()) {
2107 return;
2108 }
2109 }
2110 } else {
2111 QuickCheckDetails::Position* pos =
2112 details->positions(characters_filled_in);
2113 RegExpCharacterClass* tree = elm.data.u_char_class;
2114 ZoneList<CharacterRange>* ranges = tree->ranges();
2115 CharacterRange range = ranges->at(0);
2116 if (tree->is_negated()) {
2117 // A quick check uses multi-character mask and compare. There is no
2118 // useful way to incorporate a negative char class into this scheme
2119 // so we just conservatively create a mask and value that will always
2120 // succeed.
2121 pos->mask = 0;
2122 pos->value = 0;
2123 } else {
2124 uint32_t differing_bits = (range.from() ^ range.to());
2125 // A mask and compare is only perfect if the differing bits form a
2126 // number like 00011111 with one single block of trailing 1s.
2127 if ((differing_bits & (differing_bits + 1)) == 0) {
2128 pos->determines_perfectly = true;
2129 }
2130 uint32_t common_bits = ~SmearBitsRight(differing_bits);
2131 uint32_t bits = (range.from() & common_bits);
2132 for (int i = 1; i < ranges->length(); i++) {
2133 // Here we are combining more ranges into the mask and compare
2134 // value. With each new range the mask becomes more sparse and
2135 // so the chances of a false positive rise. A character class
2136 // with multiple ranges is assumed never to be equivalent to a
2137 // mask and compare operation.
2138 pos->determines_perfectly = false;
2139 CharacterRange range = ranges->at(i);
2140 uint32_t new_common_bits = (range.from() ^ range.to());
2141 new_common_bits = ~SmearBitsRight(new_common_bits);
2142 common_bits &= new_common_bits;
2143 bits &= new_common_bits;
2144 uint32_t differing_bits = (range.from() & common_bits) ^ bits;
2145 common_bits ^= differing_bits;
2146 bits &= common_bits;
2147 }
2148 pos->mask = common_bits;
2149 pos->value = bits;
2150 }
2151 characters_filled_in++;
2152 ASSERT(characters_filled_in <= details->characters());
2153 if (characters_filled_in == details->characters()) {
2154 return;
2155 }
2156 }
2157 }
2158 ASSERT(characters_filled_in != details->characters());
2159 on_success()-> GetQuickCheckDetails(details, compiler, characters_filled_in);
2160 }
2161
2162
2163 void QuickCheckDetails::Clear() {
2164 for (int i = 0; i < characters_; i++) {
2165 positions_[i].mask = 0;
2166 positions_[i].value = 0;
2167 positions_[i].determines_perfectly = false;
2168 }
2169 characters_ = 0;
2170 }
2171
2172
2173 void QuickCheckDetails::Advance(int by, bool ascii) {
2174 ASSERT(by > 0);
2175 if (by >= characters_) {
2176 Clear();
2177 return;
2178 }
2179 for (int i = 0; i < characters_ - by; i++) {
2180 positions_[i] = positions_[by + i];
2181 }
2182 for (int i = characters_ - by; i < characters_; i++) {
2183 positions_[i].mask = 0;
2184 positions_[i].value = 0;
2185 positions_[i].determines_perfectly = false;
2186 }
2187 characters_ -= by;
2188 // We could change mask_ and value_ here but we would never advance unless
2189 // they had already been used in a check and they won't be used again because
2190 // it would gain us nothing. So there's no point.
2191 }
2192
2193
2194 void QuickCheckDetails::Merge(QuickCheckDetails* other, int from_index) {
2195 ASSERT(characters_ == other->characters_);
2196 for (int i = from_index; i < characters_; i++) {
2197 QuickCheckDetails::Position* pos = positions(i);
2198 QuickCheckDetails::Position* other_pos = other->positions(i);
2199 if (pos->mask != other_pos->mask ||
2200 pos->value != other_pos->value ||
2201 !other_pos->determines_perfectly) {
2202 // Our mask-compare operation will be approximate unless we have the
2203 // exact same operation on both sides of the alternation.
2204 pos->determines_perfectly = false;
2205 }
2206 pos->mask &= other_pos->mask;
2207 pos->value &= pos->mask;
2208 other_pos->value &= pos->mask;
2209 uc16 differing_bits = (pos->value ^ other_pos->value);
2210 pos->mask &= ~differing_bits;
2211 pos->value &= pos->mask;
2212 }
2213 }
2214
2215
2216 void LoopChoiceNode::GetQuickCheckDetails(QuickCheckDetails* details,
2217 RegExpCompiler* compiler,
2218 int characters_filled_in) {
2219 if (body_can_be_zero_length_) return;
2220 return ChoiceNode::GetQuickCheckDetails(details,
2221 compiler,
2222 characters_filled_in);
2223 }
2224
2225
2226 void ChoiceNode::GetQuickCheckDetails(QuickCheckDetails* details,
2227 RegExpCompiler* compiler,
2228 int characters_filled_in) {
2229 int choice_count = alternatives_->length();
2230 ASSERT(choice_count > 0);
2231 alternatives_->at(0).node()->GetQuickCheckDetails(details,
2232 compiler,
2233 characters_filled_in);
2234 for (int i = 1; i < choice_count; i++) {
2235 QuickCheckDetails new_details(details->characters());
2236 RegExpNode* node = alternatives_->at(i).node();
2237 node->GetQuickCheckDetails(&new_details, compiler, characters_filled_in);
2238 // Here we merge the quick match details of the two branches.
2239 details->Merge(&new_details, characters_filled_in);
2240 }
2241 }
2242
2243
2244 // We call this repeatedly to generate code for each pass over the text node.
2245 // The passes are in increasing order of difficulty because we hope one
2246 // of the first passes will fail in which case we are saved the work of the
2247 // later passes. for example for the case independent regexp /%[asdfghjkl]a/
2248 // we will check the '%' in the first pass, the case independent 'a' in the
2249 // second pass and the character class in the last pass.
2250 //
2251 // The passes are done from right to left, so for example to test for /bar/
2252 // we will first test for an 'r' with offset 2, then an 'a' with offset 1
2253 // and then a 'b' with offset 0. This means we can avoid the end-of-input
2254 // bounds check most of the time. In the example we only need to check for
2255 // end-of-input when loading the putative 'r'.
2256 //
2257 // A slight complication involves the fact that the first character may already
2258 // be fetched into a register by the previous node. In this case we want to
2259 // do the test for that character first. We do this in separate passes. The
2260 // 'preloaded' argument indicates that we are doing such a 'pass'. If such a
2261 // pass has been performed then subsequent passes will have true in
2262 // first_element_checked to indicate that that character does not need to be
2263 // checked again.
2264 //
2265 // In addition to all this we are passed a GenerationVariant, which can
2266 // contain an AlternativeGeneration object. In this AlternativeGeneration
2267 // object we can see details of any quick check that was already passed in
2268 // order to get to the code we are now generating. The quick check can involve
2269 // loading characters, which means we do not need to recheck the bounds
2270 // up to the limit the quick check already checked. In addition the quick
2271 // check can have involved a mask and compare operation which may simplify
2272 // or obviate the need for further checks at some character positions.
2273 void TextNode::TextEmitPass(RegExpCompiler* compiler,
2274 TextEmitPassType pass,
2275 bool preloaded,
2276 GenerationVariant* variant,
2277 bool first_element_checked,
2278 int* checked_up_to) {
2279 RegExpMacroAssembler* assembler = compiler->macro_assembler();
2280 bool ascii = compiler->ascii();
2281 Label* backtrack = variant->backtrack();
2282 QuickCheckDetails* quick_check = variant->quick_check_performed();
2283 int element_count = elms_->length();
2284 for (int i = preloaded ? 0 : element_count - 1; i >= 0; i--) {
2285 TextElement elm = elms_->at(i);
2286 int cp_offset = variant->cp_offset() + elm.cp_offset;
2287 if (elm.type == TextElement::ATOM) {
2288 if (pass == NON_ASCII_MATCH ||
2289 pass == CHARACTER_MATCH ||
2290 pass == CASE_CHARACTER_MATCH) {
2291 Vector<const uc16> quarks = elm.data.u_atom->data();
2292 for (int j = preloaded ? 0 : quarks.length() - 1; j >= 0; j--) {
2293 bool bound_checked = true; // Most ops will check their bounds.
2294 if (first_element_checked && i == 0 && j == 0) continue;
2295 if (quick_check != NULL &&
2296 elm.cp_offset + j < quick_check->characters() &&
2297 quick_check->positions(elm.cp_offset + j)->determines_perfectly) {
2298 continue;
2299 }
2300 if (pass == NON_ASCII_MATCH) {
2301 ASSERT(ascii);
2302 if (quarks[j] > String::kMaxAsciiCharCode) {
2303 assembler->GoTo(backtrack);
2304 return;
2305 }
2306 } else if (pass == CHARACTER_MATCH) {
2307 if (compiler->ignore_case()) {
2308 bound_checked = EmitAtomNonLetter(assembler,
2309 quarks[j],
2310 backtrack,
2311 cp_offset + j,
2312 *checked_up_to < cp_offset + j,
2313 preloaded);
2314 } else {
2315 if (!preloaded) {
2316 assembler->LoadCurrentCharacter(cp_offset + j,
2317 backtrack,
2318 *checked_up_to < cp_offset + j);
2319 }
2320 assembler->CheckNotCharacter(quarks[j], backtrack);
2321 }
2322 } else {
2323 ASSERT_EQ(pass, CASE_CHARACTER_MATCH);
2324 ASSERT(compiler->ignore_case());
2325 bound_checked = EmitAtomLetter(assembler,
2326 quarks[j],
2327 backtrack,
2328 cp_offset + j,
2329 *checked_up_to < cp_offset + j,
2330 preloaded);
2331 }
2332 if (pass != NON_ASCII_MATCH && bound_checked) {
2333 if (cp_offset + j > *checked_up_to) {
2334 *checked_up_to = cp_offset + j;
2335 }
2336 }
2337 }
2338 }
2339 } else {
2340 ASSERT_EQ(elm.type, TextElement::CHAR_CLASS);
2341 if (first_element_checked && i == 0) continue;
2342 if (quick_check != NULL &&
2343 elm.cp_offset < quick_check->characters() &&
2344 quick_check->positions(elm.cp_offset)->determines_perfectly) {
2345 continue;
2346 }
2347 if (pass == CHARACTER_CLASS_MATCH) {
2348 RegExpCharacterClass* cc = elm.data.u_char_class;
2349 EmitCharClass(assembler,
2350 cc,
2351 cp_offset,
2352 backtrack,
2353 *checked_up_to < cp_offset,
2354 ascii,
2355 preloaded);
2356 if (cp_offset > *checked_up_to) {
2357 *checked_up_to = cp_offset;
2358 }
2359 }
2360 }
2361 }
2362 }
2363
2364
2365 int TextNode::Length() {
2366 TextElement elm = elms_->last();
2367 ASSERT(elm.cp_offset >= 0);
2368 if (elm.type == TextElement::ATOM) {
2369 return elm.cp_offset + elm.data.u_atom->data().length();
2370 } else {
2371 return elm.cp_offset + 1;
2372 }
2373 }
2374
2375
1896 // This generates the code to match a text node. A text node can contain 2376 // This generates the code to match a text node. A text node can contain
1897 // straight character sequences (possibly to be matched in a case-independent 2377 // straight character sequences (possibly to be matched in a case-independent
1898 // way) and character classes. In order to be most efficient we test for the 2378 // way) and character classes. For efficiency we do not do this in a single
1899 // simple things first and then move on to the more complicated things. The 2379 // pass from left to right. Instead we pass over the text node several times,
1900 // simplest thing is a non-letter or a letter if we are matching case. The 2380 // emitting code for some character positions every time. See the comment on
1901 // next-most simple thing is a case-independent letter. The least simple is 2381 // TextEmitPass for details.
1902 // a character class. Another optimization is that we test the last one first.
1903 // If that succeeds we don't need to test for the end of the string when we
1904 // load other characters.
1905 bool TextNode::Emit(RegExpCompiler* compiler, GenerationVariant* variant) { 2382 bool TextNode::Emit(RegExpCompiler* compiler, GenerationVariant* variant) {
1906 RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
1907 Label *backtrack = variant->backtrack();
1908 LimitResult limit_result = LimitVersions(compiler, variant); 2383 LimitResult limit_result = LimitVersions(compiler, variant);
1909 if (limit_result == FAIL) return false; 2384 if (limit_result == FAIL) return false;
1910 if (limit_result == DONE) return true; 2385 if (limit_result == DONE) return true;
1911 ASSERT(limit_result == CONTINUE); 2386 ASSERT(limit_result == CONTINUE);
1912 2387
1913 int element_count = elms_->length(); 2388 if (info()->follows_word_interest ||
1914 ASSERT(element_count != 0); 2389 info()->follows_newline_interest ||
2390 info()->follows_start_interest) {
2391 return false;
2392 }
2393
1915 if (info()->at_end) { 2394 if (info()->at_end) {
1916 macro_assembler->GoTo(backtrack); 2395 compiler->macro_assembler()->GoTo(variant->backtrack());
1917 return true; 2396 return true;
1918 } 2397 }
1919 // First check for non-ASCII text. 2398
1920 // TODO(plesner): We should do this at node level.
1921 if (compiler->ascii()) { 2399 if (compiler->ascii()) {
1922 for (int i = element_count - 1; i >= 0; i--) { 2400 int dummy = 0;
1923 TextElement elm = elms_->at(i); 2401 TextEmitPass(compiler, NON_ASCII_MATCH, false, variant, false, &dummy);
1924 if (elm.type == TextElement::ATOM) { 2402 }
1925 Vector<const uc16> quarks = elm.data.u_atom->data(); 2403
1926 for (int j = quarks.length() - 1; j >= 0; j--) { 2404 bool first_elt_done = false;
1927 if (quarks[j] > String::kMaxAsciiCharCode) { 2405 int bound_checked_to = variant->cp_offset() - 1;
1928 macro_assembler->GoTo(backtrack); 2406 QuickCheckDetails* quick_check = variant->quick_check_performed();
1929 return true; 2407 bound_checked_to += Max(quick_check->characters(),
1930 } 2408 variant->characters_preloaded());
1931 } 2409
1932 } else { 2410 // If a character is preloaded into the current character register then
1933 ASSERT_EQ(elm.type, TextElement::CHAR_CLASS); 2411 // check that now.
1934 } 2412 if (variant->characters_preloaded() == 1) {
1935 } 2413 TextEmitPass(compiler,
1936 } 2414 CHARACTER_MATCH,
1937 // Second, handle straight character matches. 2415 true,
1938 int checked_up_to = -1; 2416 variant,
1939 for (int i = element_count - 1; i >= 0; i--) { 2417 false,
1940 TextElement elm = elms_->at(i); 2418 &bound_checked_to);
1941 ASSERT(elm.cp_offset >= 0); 2419 if (compiler->ignore_case()) {
1942 int cp_offset = variant->cp_offset() + elm.cp_offset; 2420 TextEmitPass(compiler,
1943 if (elm.type == TextElement::ATOM) { 2421 CASE_CHARACTER_MATCH,
1944 Vector<const uc16> quarks = elm.data.u_atom->data(); 2422 true,
1945 int last_cp_offset = cp_offset + quarks.length(); 2423 variant,
1946 if (compiler->ignore_case()) { 2424 false,
1947 EmitAtomNonLetters(macro_assembler, 2425 &bound_checked_to);
1948 elm, 2426 }
1949 quarks, 2427 TextEmitPass(compiler,
1950 backtrack, 2428 CHARACTER_CLASS_MATCH,
1951 cp_offset, 2429 true,
1952 checked_up_to < last_cp_offset); 2430 variant,
1953 } else { 2431 false,
1954 macro_assembler->CheckCharacters(quarks, 2432 &bound_checked_to);
1955 cp_offset, 2433 first_elt_done = true;
1956 backtrack, 2434 }
1957 checked_up_to < last_cp_offset); 2435
1958 } 2436 TextEmitPass(compiler,
1959 if (last_cp_offset > checked_up_to) checked_up_to = last_cp_offset - 1; 2437 CHARACTER_MATCH,
1960 } else { 2438 false,
1961 ASSERT_EQ(elm.type, TextElement::CHAR_CLASS); 2439 variant,
1962 } 2440 first_elt_done,
1963 } 2441 &bound_checked_to);
1964 // Third, handle case independent letter matches if any.
1965 if (compiler->ignore_case()) { 2442 if (compiler->ignore_case()) {
1966 for (int i = element_count - 1; i >= 0; i--) { 2443 TextEmitPass(compiler,
1967 TextElement elm = elms_->at(i); 2444 CASE_CHARACTER_MATCH,
1968 int cp_offset = variant->cp_offset() + elm.cp_offset; 2445 false,
1969 if (elm.type == TextElement::ATOM) { 2446 variant,
1970 Vector<const uc16> quarks = elm.data.u_atom->data(); 2447 first_elt_done,
1971 int last_cp_offset = cp_offset + quarks.length(); 2448 &bound_checked_to);
1972 EmitAtomLetters(macro_assembler, 2449 }
1973 elm, 2450 TextEmitPass(compiler,
1974 quarks, 2451 CHARACTER_CLASS_MATCH,
1975 backtrack, 2452 false,
1976 cp_offset, 2453 variant,
1977 checked_up_to < last_cp_offset); 2454 first_elt_done,
1978 if (last_cp_offset > checked_up_to) checked_up_to = last_cp_offset - 1; 2455 &bound_checked_to);
1979 } 2456
1980 } 2457 GenerationVariant successor_variant(*variant);
1981 } 2458 successor_variant.AdvanceVariant(Length(), compiler->ascii());
1982 // If the fast character matches passed then do the character classes.
1983 for (int i = element_count - 1; i >= 0; i--) {
1984 TextElement elm = elms_->at(i);
1985 int cp_offset = variant->cp_offset() + elm.cp_offset;
1986 if (elm.type == TextElement::CHAR_CLASS) {
1987 RegExpCharacterClass* cc = elm.data.u_char_class;
1988 EmitCharClass(macro_assembler,
1989 cc,
1990 cp_offset,
1991 backtrack,
1992 checked_up_to < cp_offset,
1993 compiler->ascii());
1994 if (cp_offset > checked_up_to) checked_up_to = cp_offset;
1995 }
1996 }
1997
1998 GenerationVariant new_variant(*variant);
1999 new_variant.set_cp_offset(checked_up_to + 1);
2000 RecursionCheck rc(compiler); 2459 RecursionCheck rc(compiler);
2001 return on_success()->Emit(compiler, &new_variant); 2460 return on_success()->Emit(compiler, &successor_variant);
2461 }
2462
2463
2464 void GenerationVariant::AdvanceVariant(int by, bool ascii) {
2465 ASSERT(by > 0);
2466 // We don't have an instruction for shifting the current character register
2467 // down or for using a shifted value for anything so lets just forget that
2468 // we preloaded any characters into it.
2469 characters_preloaded_ = 0;
2470 // Adjust the offsets of the quick check performed information. This
2471 // information is used to find out what we already determined about the
2472 // characters by means of mask and compare.
2473 quick_check_performed_.Advance(by, ascii);
2474 cp_offset_ += by;
2002 } 2475 }
2003 2476
2004 2477
2005 void TextNode::MakeCaseIndependent() { 2478 void TextNode::MakeCaseIndependent() {
2006 int element_count = elms_->length(); 2479 int element_count = elms_->length();
2007 for (int i = 0; i < element_count; i++) { 2480 for (int i = 0; i < element_count; i++) {
2008 TextElement elm = elms_->at(i); 2481 TextElement elm = elms_->at(i);
2009 if (elm.type == TextElement::CHAR_CLASS) { 2482 if (elm.type == TextElement::CHAR_CLASS) {
2010 RegExpCharacterClass* cc = elm.data.u_char_class; 2483 RegExpCharacterClass* cc = elm.data.u_char_class;
2011 ZoneList<CharacterRange>* ranges = cc->ranges(); 2484 ZoneList<CharacterRange>* ranges = cc->ranges();
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
2053 return kNodeIsTooComplexForGreedyLoops; 2526 return kNodeIsTooComplexForGreedyLoops;
2054 } 2527 }
2055 length += node_length; 2528 length += node_length;
2056 SeqRegExpNode* seq_node = static_cast<SeqRegExpNode*>(node); 2529 SeqRegExpNode* seq_node = static_cast<SeqRegExpNode*>(node);
2057 node = seq_node->on_success(); 2530 node = seq_node->on_success();
2058 } 2531 }
2059 return length; 2532 return length;
2060 } 2533 }
2061 2534
2062 2535
2536 void LoopChoiceNode::AddLoopAlternative(GuardedAlternative alt) {
2537 ASSERT_EQ(loop_node_, NULL);
2538 AddAlternative(alt);
2539 loop_node_ = alt.node();
2540 }
2541
2542
2543 void LoopChoiceNode::AddContinueAlternative(GuardedAlternative alt) {
2544 ASSERT_EQ(continue_node_, NULL);
2545 AddAlternative(alt);
2546 continue_node_ = alt.node();
2547 }
2548
2549
2063 bool LoopChoiceNode::Emit(RegExpCompiler* compiler, 2550 bool LoopChoiceNode::Emit(RegExpCompiler* compiler,
2064 GenerationVariant* variant) { 2551 GenerationVariant* variant) {
2065 RegExpMacroAssembler* macro_assembler = compiler->macro_assembler(); 2552 RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
2066 if (variant->stop_node() == this) { 2553 if (variant->stop_node() == this) {
2067 int text_length = GreedyLoopTextLength(&(alternatives_->at(0))); 2554 int text_length = GreedyLoopTextLength(&(alternatives_->at(0)));
2068 ASSERT(text_length != kNodeIsTooComplexForGreedyLoops); 2555 ASSERT(text_length != kNodeIsTooComplexForGreedyLoops);
2069 // Update the counter-based backtracking info on the stack. This is an 2556 // Update the counter-based backtracking info on the stack. This is an
2070 // optimization for greedy loops (see below). 2557 // optimization for greedy loops (see below).
2071 ASSERT(variant->cp_offset() == text_length); 2558 ASSERT(variant->cp_offset() == text_length);
2072 macro_assembler->AdvanceCurrentPosition(text_length); 2559 macro_assembler->AdvanceCurrentPosition(text_length);
2073 macro_assembler->GoTo(variant->loop_label()); 2560 macro_assembler->GoTo(variant->loop_label());
2074 return true; 2561 return true;
2075 } 2562 }
2076 ASSERT(variant->stop_node() == NULL); 2563 ASSERT(variant->stop_node() == NULL);
2077 if (!variant->is_trivial()) { 2564 if (!variant->is_trivial()) {
2078 return variant->Flush(compiler, this); 2565 return variant->Flush(compiler, this);
2079 } 2566 }
2080 return ChoiceNode::Emit(compiler, variant); 2567 return ChoiceNode::Emit(compiler, variant);
2081 } 2568 }
2082 2569
2083 2570
2571 int ChoiceNode::CalculatePreloadCharacters(RegExpCompiler* compiler) {
2572 int preload_characters = EatsAtLeast(0);
2573 #ifdef CAN_READ_UNALIGNED
2574 bool ascii = compiler->ascii();
2575 if (ascii) {
2576 if (preload_characters > 4) preload_characters = 4;
2577 // We can't preload 3 characters because there is no machine instruction
2578 // to do that. We can't just load 4 because we could be reading
2579 // beyond the end of the string, which could cause a memory fault.
2580 if (preload_characters == 3) preload_characters = 2;
2581 } else {
2582 if (preload_characters > 2) preload_characters = 2;
2583 }
2584 #else
2585 if (preload_characters > 1) preload_characters = 1;
2586 #endif
2587 return preload_characters;
2588 }
2589
2590
2591 // This class is used when generating the alternatives in a choice node. It
2592 // records the way the alternative is being code generated.
2593 class AlternativeGeneration: public Malloced {
2594 public:
2595 AlternativeGeneration()
2596 : possible_success(),
2597 expects_preload(false),
2598 after(),
2599 quick_check_details() { }
2600 Label possible_success;
2601 bool expects_preload;
2602 Label after;
2603 QuickCheckDetails quick_check_details;
2604 };
2605
2606
2607 // Creates a list of AlternativeGenerations. If the list has a reasonable
2608 // size then it is on the stack, otherwise the excess is on the heap.
2609 class AlternativeGenerationList {
2610 public:
2611 explicit AlternativeGenerationList(int count)
2612 : alt_gens_(count) {
2613 for (int i = 0; i < count && i < kAFew; i++) {
2614 alt_gens_.Add(a_few_alt_gens_ + i);
2615 }
2616 for (int i = kAFew; i < count; i++) {
2617 alt_gens_.Add(new AlternativeGeneration());
2618 }
2619 }
2620 ~AlternativeGenerationList() {
2621 for (int i = 0; i < alt_gens_.length(); i++) {
2622 alt_gens_[i]->possible_success.Unuse();
2623 alt_gens_[i]->after.Unuse();
2624 }
2625 for (int i = kAFew; i < alt_gens_.length(); i++) {
2626 delete alt_gens_[i];
2627 alt_gens_[i] = NULL;
2628 }
2629 }
2630
2631 AlternativeGeneration* at(int i) {
2632 return alt_gens_[i];
2633 }
2634 private:
2635 static const int kAFew = 10;
2636 ZoneList<AlternativeGeneration*> alt_gens_;
2637 AlternativeGeneration a_few_alt_gens_[kAFew];
2638 };
2639
2640
2641 /* Code generation for choice nodes.
2642 *
2643 * We generate quick checks that do a mask and compare to eliminate a
2644 * choice. If the quick check succeeds then it jumps to the continuation to
2645 * do slow checks and check subsequent nodes. If it fails (the common case)
2646 * it falls through to the next choice.
2647 *
2648 * Here is the desired flow graph. Nodes directly below each other imply
2649 * fallthrough. Alternatives 1 and 2 have quick checks. Alternative
2650 * 3 doesn't have a quick check so we have to call the slow check.
2651 * Nodes are marked Qn for quick checks and Sn for slow checks. The entire
2652 * regexp continuation is generated directly after the Sn node, up to the
2653 * next GoTo if we decide to reuse some already generated code. Some
2654 * nodes expect preload_characters to be preloaded into the current
2655 * character register. R nodes do this preloading. Vertices are marked
2656 * F for failures and S for success (possible success in the case of quick
2657 * nodes). L, V, < and > are used as arrow heads.
2658 *
2659 * ----------> R
2660 * |
2661 * V
2662 * Q1 -----> S1
2663 * | S /
2664 * F| /
2665 * | F/
2666 * | /
2667 * | R
2668 * | /
2669 * V L
2670 * Q2 -----> S2
2671 * | S /
2672 * F| /
2673 * | F/
2674 * | /
2675 * | R
2676 * | /
2677 * V L
2678 * S3
2679 * |
2680 * F|
2681 * |
2682 * R
2683 * |
2684 * backtrack V
2685 * <----------Q4
2686 * \ F |
2687 * \ |S
2688 * \ F V
2689 * \-----S4
2690 *
2691 * For greedy loops we reverse our expectation and expect to match rather
2692 * than fail. Therefore we want the loop code to look like this (U is the
2693 * unwind code that steps back in the greedy loop). The following alternatives
2694 * look the same as above.
2695 * _____
2696 * / \
2697 * V |
2698 * ----------> S1 |
2699 * /| |
2700 * / |S |
2701 * F/ \_____/
2702 * /
2703 * |<-----------
2704 * | \
2705 * V \
2706 * Q2 ---> S2 \
2707 * | S / |
2708 * F| / |
2709 * | F/ |
2710 * | / |
2711 * | R |
2712 * | / |
2713 * F VL |
2714 * <------U |
2715 * back |S |
2716 * \______________/
2717 */
2718
2719
2084 bool ChoiceNode::Emit(RegExpCompiler* compiler, GenerationVariant* variant) { 2720 bool ChoiceNode::Emit(RegExpCompiler* compiler, GenerationVariant* variant) {
2085 RegExpMacroAssembler* macro_assembler = compiler->macro_assembler(); 2721 RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
2086 int choice_count = alternatives_->length(); 2722 int choice_count = alternatives_->length();
2087 #ifdef DEBUG 2723 #ifdef DEBUG
2088 for (int i = 0; i < choice_count - 1; i++) { 2724 for (int i = 0; i < choice_count - 1; i++) {
2089 GuardedAlternative alternative = alternatives_->at(i); 2725 GuardedAlternative alternative = alternatives_->at(i);
2090 ZoneList<Guard*>* guards = alternative.guards(); 2726 ZoneList<Guard*>* guards = alternative.guards();
2091 int guard_count = (guards == NULL) ? 0 : guards->length(); 2727 int guard_count = (guards == NULL) ? 0 : guards->length();
2092 for (int j = 0; j < guard_count; j++) { 2728 for (int j = 0; j < guard_count; j++) {
2093 ASSERT(!variant->mentions_reg(guards->at(j)->reg())); 2729 ASSERT(!variant->mentions_reg(guards->at(j)->reg()));
2094 } 2730 }
2095 } 2731 }
2096 #endif 2732 #endif
2097 2733
2098 LimitResult limit_result = LimitVersions(compiler, variant); 2734 LimitResult limit_result = LimitVersions(compiler, variant);
2099 if (limit_result == DONE) return true; 2735 if (limit_result == DONE) return true;
2100 if (limit_result == FAIL) return false; 2736 if (limit_result == FAIL) return false;
2101 ASSERT(limit_result == CONTINUE); 2737 ASSERT(limit_result == CONTINUE);
2102 2738
2103 RecursionCheck rc(compiler); 2739 RecursionCheck rc(compiler);
2104 2740
2105 GenerationVariant* current_variant = variant; 2741 GenerationVariant* current_variant = variant;
2106 2742
2107 int text_length = GreedyLoopTextLength(&(alternatives_->at(0))); 2743 int text_length = GreedyLoopTextLength(&(alternatives_->at(0)));
2108 bool greedy_loop = false; 2744 bool greedy_loop = false;
2109 Label greedy_loop_label; 2745 Label greedy_loop_label;
2110 GenerationVariant counter_backtrack_variant(&greedy_loop_label); 2746 GenerationVariant counter_backtrack_variant;
2747 counter_backtrack_variant.set_backtrack(&greedy_loop_label);
2111 if (choice_count > 1 && text_length != kNodeIsTooComplexForGreedyLoops) { 2748 if (choice_count > 1 && text_length != kNodeIsTooComplexForGreedyLoops) {
2112 // Here we have special handling for greedy loops containing only text nodes 2749 // Here we have special handling for greedy loops containing only text nodes
2113 // and other simple nodes. These are handled by pushing the current 2750 // and other simple nodes. These are handled by pushing the current
2114 // position on the stack and then incrementing the current position each 2751 // position on the stack and then incrementing the current position each
2115 // time around the switch. On backtrack we decrement the current position 2752 // time around the switch. On backtrack we decrement the current position
2116 // and check it against the pushed value. This avoids pushing backtrack 2753 // and check it against the pushed value. This avoids pushing backtrack
2117 // information for each iteration of the loop, which could take up a lot of 2754 // information for each iteration of the loop, which could take up a lot of
2118 // space. 2755 // space.
2119 greedy_loop = true; 2756 greedy_loop = true;
2120 ASSERT(variant->stop_node() == NULL); 2757 ASSERT(variant->stop_node() == NULL);
2121 macro_assembler->PushCurrentPosition(); 2758 macro_assembler->PushCurrentPosition();
2122 current_variant = &counter_backtrack_variant; 2759 current_variant = &counter_backtrack_variant;
2123 Label greedy_match_failed; 2760 Label greedy_match_failed;
2124 GenerationVariant greedy_match_variant(&greedy_match_failed); 2761 GenerationVariant greedy_match_variant;
2762 greedy_match_variant.set_backtrack(&greedy_match_failed);
2125 Label loop_label; 2763 Label loop_label;
2126 macro_assembler->Bind(&loop_label); 2764 macro_assembler->Bind(&loop_label);
2127 greedy_match_variant.set_stop_node(this); 2765 greedy_match_variant.set_stop_node(this);
2128 greedy_match_variant.set_loop_label(&loop_label); 2766 greedy_match_variant.set_loop_label(&loop_label);
2129 bool ok = alternatives_->at(0).node()->Emit(compiler, 2767 bool ok = alternatives_->at(0).node()->Emit(compiler,
2130 &greedy_match_variant); 2768 &greedy_match_variant);
2131 macro_assembler->Bind(&greedy_match_failed); 2769 macro_assembler->Bind(&greedy_match_failed);
2132 if (!ok) { 2770 if (!ok) {
2133 greedy_loop_label.Unuse(); 2771 greedy_loop_label.Unuse();
2134 return false; 2772 return false;
2135 } 2773 }
2136 } 2774 }
2137 2775
2138 Label second_choice; // For use in greedy matches. 2776 Label second_choice; // For use in greedy matches.
2139 macro_assembler->Bind(&second_choice); 2777 macro_assembler->Bind(&second_choice);
2140 2778
2779 int first_normal_choice = greedy_loop ? 1 : 0;
2780
2781 int preload_characters = CalculatePreloadCharacters(compiler);
2782 bool preload_is_current = false;
2783 bool preload_has_checked_bounds = false;
2784
2785 AlternativeGenerationList alt_gens(choice_count);
2786
2141 // For now we just call all choices one after the other. The idea ultimately 2787 // For now we just call all choices one after the other. The idea ultimately
2142 // is to use the Dispatch table to try only the relevant ones. 2788 // is to use the Dispatch table to try only the relevant ones.
2143 for (int i = greedy_loop ? 1 : 0; i < choice_count - 1; i++) { 2789 for (int i = first_normal_choice; i < choice_count; i++) {
2144 GuardedAlternative alternative = alternatives_->at(i); 2790 GuardedAlternative alternative = alternatives_->at(i);
2145 Label after; 2791 AlternativeGeneration* alt_gen(alt_gens.at(i));
2792 alt_gen->quick_check_details.set_characters(preload_characters);
2146 ZoneList<Guard*>* guards = alternative.guards(); 2793 ZoneList<Guard*>* guards = alternative.guards();
2147 int guard_count = (guards == NULL) ? 0 : guards->length(); 2794 int guard_count = (guards == NULL) ? 0 : guards->length();
2795
2148 GenerationVariant new_variant(*current_variant); 2796 GenerationVariant new_variant(*current_variant);
2149 new_variant.set_backtrack(&after); 2797 new_variant.set_characters_preloaded(preload_is_current ?
2150 for (int j = 0; j < guard_count; j++) { 2798 preload_characters :
2151 GenerateGuard(macro_assembler, guards->at(j), &new_variant); 2799 0);
2800 new_variant.quick_check_performed()->Clear();
2801 alt_gen->expects_preload = preload_is_current;
2802 bool generate_full_check_inline = false;
2803 if (alternative.node()->EmitQuickCheck(compiler,
2804 &new_variant,
2805 preload_has_checked_bounds,
2806 &alt_gen->possible_success,
2807 &alt_gen->quick_check_details,
2808 i < choice_count - 1)) {
2809 // Quick check was generated for this choice.
2810 preload_is_current = true;
2811 preload_has_checked_bounds = true;
2812 // On the last choice in the ChoiceNode we generated the quick
2813 // check to fall through on possible success. So now we need to
2814 // generate the full check inline.
2815 if (i == choice_count - 1) {
2816 macro_assembler->Bind(&alt_gen->possible_success);
2817 new_variant.set_quick_check_performed(&alt_gen->quick_check_details);
2818 new_variant.set_characters_preloaded(preload_characters);
2819 generate_full_check_inline = true;
2820 }
2821 } else {
2822 // No quick check was generated. Put the full code here.
2823 if (i < choice_count - 1) {
2824 new_variant.set_backtrack(&alt_gen->after);
2825 }
2826 generate_full_check_inline = true;
2152 } 2827 }
2153 if (!alternative.node()->Emit(compiler, &new_variant)) { 2828 if (generate_full_check_inline) {
2154 after.Unuse(); 2829 if (preload_is_current) {
2155 return false; 2830 new_variant.set_characters_preloaded(preload_characters);
2831 }
2832 for (int j = 0; j < guard_count; j++) {
2833 GenerateGuard(macro_assembler, guards->at(j), &new_variant);
2834 }
2835 if (!alternative.node()->Emit(compiler, &new_variant)) {
2836 greedy_loop_label.Unuse();
2837 return false;
2838 }
2839 preload_is_current = false;
2156 } 2840 }
2157 macro_assembler->Bind(&after); 2841 macro_assembler->Bind(&alt_gen->after);
2158 } 2842 }
2159 GuardedAlternative alternative = alternatives_->at(choice_count - 1);
2160 ZoneList<Guard*>* guards = alternative.guards();
2161 int guard_count = (guards == NULL) ? 0 : guards->length();
2162 for (int j = 0; j < guard_count; j++) {
2163 GenerateGuard(macro_assembler, guards->at(j), current_variant);
2164 }
2165 bool ok = alternative.node()->Emit(compiler, current_variant);
2166 if (!ok) return false;
2167 if (greedy_loop) { 2843 if (greedy_loop) {
2168 macro_assembler->Bind(&greedy_loop_label); 2844 macro_assembler->Bind(&greedy_loop_label);
2169 // If we have unwound to the bottom then backtrack. 2845 // If we have unwound to the bottom then backtrack.
2170 macro_assembler->CheckGreedyLoop(variant->backtrack()); 2846 macro_assembler->CheckGreedyLoop(variant->backtrack());
2171 // Otherwise try the second priority at an earlier position. 2847 // Otherwise try the second priority at an earlier position.
2172 macro_assembler->AdvanceCurrentPosition(-text_length); 2848 macro_assembler->AdvanceCurrentPosition(-text_length);
2173 macro_assembler->GoTo(&second_choice); 2849 macro_assembler->GoTo(&second_choice);
2174 } 2850 }
2851 // At this point we need to generate slow checks for the alternatives where
2852 // the quick check was inlined. We can recognize these because the associated
2853 // label was bound.
2854 for (int i = first_normal_choice; i < choice_count - 1; i++) {
2855 AlternativeGeneration* alt_gen = alt_gens.at(i);
2856 if (!EmitOutOfLineContinuation(compiler,
2857 current_variant,
2858 alternatives_->at(i),
2859 alt_gen,
2860 preload_characters,
2861 alt_gens.at(i + 1)->expects_preload)) {
2862 return false;
2863 }
2864 }
2175 return true; 2865 return true;
2176 } 2866 }
2177 2867
2178 2868
2869 bool ChoiceNode::EmitOutOfLineContinuation(RegExpCompiler* compiler,
2870 GenerationVariant* variant,
2871 GuardedAlternative alternative,
2872 AlternativeGeneration* alt_gen,
2873 int preload_characters,
2874 bool next_expects_preload) {
2875 if (!alt_gen->possible_success.is_linked()) return true;
2876
2877 RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
2878 macro_assembler->Bind(&alt_gen->possible_success);
2879 GenerationVariant out_of_line_variant(*variant);
2880 out_of_line_variant.set_characters_preloaded(preload_characters);
2881 out_of_line_variant.set_quick_check_performed(&alt_gen->quick_check_details);
2882 ZoneList<Guard*>* guards = alternative.guards();
2883 int guard_count = (guards == NULL) ? 0 : guards->length();
2884 if (next_expects_preload) {
2885 Label reload_current_char;
2886 out_of_line_variant.set_backtrack(&reload_current_char);
2887 for (int j = 0; j < guard_count; j++) {
2888 GenerateGuard(macro_assembler, guards->at(j), &out_of_line_variant);
2889 }
2890 bool ok = alternative.node()->Emit(compiler, &out_of_line_variant);
2891 macro_assembler->Bind(&reload_current_char);
2892 // Reload the current character, since the next quick check expects that.
2893 // We don't need to check bounds here because we only get into this
2894 // code through a quick check which already did the checked load.
2895 macro_assembler->LoadCurrentCharacter(variant->cp_offset(),
2896 NULL,
2897 false,
2898 preload_characters);
2899 macro_assembler->GoTo(&(alt_gen->after));
2900 return ok;
2901 } else {
2902 out_of_line_variant.set_backtrack(&(alt_gen->after));
2903 for (int j = 0; j < guard_count; j++) {
2904 GenerateGuard(macro_assembler, guards->at(j), &out_of_line_variant);
2905 }
2906 return alternative.node()->Emit(compiler, &out_of_line_variant);
2907 }
2908 }
2909
2910
2179 bool ActionNode::Emit(RegExpCompiler* compiler, GenerationVariant* variant) { 2911 bool ActionNode::Emit(RegExpCompiler* compiler, GenerationVariant* variant) {
2180 RegExpMacroAssembler* macro = compiler->macro_assembler(); 2912 RegExpMacroAssembler* assembler = compiler->macro_assembler();
2181 LimitResult limit_result = LimitVersions(compiler, variant); 2913 LimitResult limit_result = LimitVersions(compiler, variant);
2182 if (limit_result == DONE) return true; 2914 if (limit_result == DONE) return true;
2183 if (limit_result == FAIL) return false; 2915 if (limit_result == FAIL) return false;
2184 ASSERT(limit_result == CONTINUE); 2916 ASSERT(limit_result == CONTINUE);
2185 2917
2186 RecursionCheck rc(compiler); 2918 RecursionCheck rc(compiler);
2187 2919
2188 switch (type_) { 2920 switch (type_) {
2189 case STORE_POSITION: { 2921 case STORE_POSITION: {
2190 GenerationVariant::DeferredCapture 2922 GenerationVariant::DeferredCapture
(...skipping 11 matching lines...) Expand all
2202 } 2934 }
2203 case SET_REGISTER: { 2935 case SET_REGISTER: {
2204 GenerationVariant::DeferredSetRegister 2936 GenerationVariant::DeferredSetRegister
2205 new_set(data_.u_store_register.reg, data_.u_store_register.value); 2937 new_set(data_.u_store_register.reg, data_.u_store_register.value);
2206 GenerationVariant new_variant = *variant; 2938 GenerationVariant new_variant = *variant;
2207 new_variant.add_action(&new_set); 2939 new_variant.add_action(&new_set);
2208 return on_success()->Emit(compiler, &new_variant); 2940 return on_success()->Emit(compiler, &new_variant);
2209 } 2941 }
2210 case BEGIN_SUBMATCH: 2942 case BEGIN_SUBMATCH:
2211 if (!variant->is_trivial()) return variant->Flush(compiler, this); 2943 if (!variant->is_trivial()) return variant->Flush(compiler, this);
2212 macro->WriteCurrentPositionToRegister( 2944 assembler->WriteCurrentPositionToRegister(
2213 data_.u_submatch.current_position_register, 0); 2945 data_.u_submatch.current_position_register, 0);
2214 macro->WriteStackPointerToRegister( 2946 assembler->WriteStackPointerToRegister(
2215 data_.u_submatch.stack_pointer_register); 2947 data_.u_submatch.stack_pointer_register);
2216 return on_success()->Emit(compiler, variant); 2948 return on_success()->Emit(compiler, variant);
2217 case POSITIVE_SUBMATCH_SUCCESS: 2949 case POSITIVE_SUBMATCH_SUCCESS:
2218 if (!variant->is_trivial()) return variant->Flush(compiler, this); 2950 if (!variant->is_trivial()) return variant->Flush(compiler, this);
2219 // TODO(erikcorry): Implement support. 2951 // TODO(erikcorry): Implement support.
2220 if (info()->follows_word_interest || 2952 if (info()->follows_word_interest ||
2221 info()->follows_newline_interest || 2953 info()->follows_newline_interest ||
2222 info()->follows_start_interest) { 2954 info()->follows_start_interest) {
2223 return false; 2955 return false;
2224 } 2956 }
2225 if (info()->at_end) { 2957 if (info()->at_end) {
2226 Label at_end; 2958 Label at_end;
2227 // Load current character jumps to the label if we are beyond the string 2959 // Load current character jumps to the label if we are beyond the string
2228 // end. 2960 // end.
2229 macro->LoadCurrentCharacter(0, &at_end); 2961 assembler->LoadCurrentCharacter(0, &at_end);
2230 macro->GoTo(variant->backtrack()); 2962 assembler->GoTo(variant->backtrack());
2231 macro->Bind(&at_end); 2963 assembler->Bind(&at_end);
2232 } 2964 }
2233 macro->ReadCurrentPositionFromRegister( 2965 assembler->ReadCurrentPositionFromRegister(
2234 data_.u_submatch.current_position_register); 2966 data_.u_submatch.current_position_register);
2235 macro->ReadStackPointerFromRegister( 2967 assembler->ReadStackPointerFromRegister(
2236 data_.u_submatch.stack_pointer_register); 2968 data_.u_submatch.stack_pointer_register);
2237 return on_success()->Emit(compiler, variant); 2969 return on_success()->Emit(compiler, variant);
2238 default: 2970 default:
2239 UNREACHABLE(); 2971 UNREACHABLE();
2240 return false; 2972 return false;
2241 } 2973 }
2242 } 2974 }
2243 2975
2244 2976
2245 bool BackReferenceNode::Emit(RegExpCompiler* compiler, 2977 bool BackReferenceNode::Emit(RegExpCompiler* compiler,
2246 GenerationVariant* variant) { 2978 GenerationVariant* variant) {
2247 RegExpMacroAssembler* macro = compiler->macro_assembler(); 2979 RegExpMacroAssembler* assembler = compiler->macro_assembler();
2248 if (!variant->is_trivial()) { 2980 if (!variant->is_trivial()) {
2249 return variant->Flush(compiler, this); 2981 return variant->Flush(compiler, this);
2250 } 2982 }
2251 2983
2252 LimitResult limit_result = LimitVersions(compiler, variant); 2984 LimitResult limit_result = LimitVersions(compiler, variant);
2253 if (limit_result == DONE) return true; 2985 if (limit_result == DONE) return true;
2254 if (limit_result == FAIL) return false; 2986 if (limit_result == FAIL) return false;
2255 ASSERT(limit_result == CONTINUE); 2987 ASSERT(limit_result == CONTINUE);
2256 2988
2257 RecursionCheck rc(compiler); 2989 RecursionCheck rc(compiler);
2258 2990
2259 ASSERT_EQ(start_reg_ + 1, end_reg_); 2991 ASSERT_EQ(start_reg_ + 1, end_reg_);
2260 if (info()->at_end) { 2992 if (info()->at_end) {
2261 // If we are constrained to match at the end of the input then succeed 2993 // If we are constrained to match at the end of the input then succeed
2262 // iff the back reference is empty. 2994 // iff the back reference is empty.
2263 macro->CheckNotRegistersEqual(start_reg_, end_reg_, variant->backtrack()); 2995 assembler->CheckNotRegistersEqual(start_reg_,
2996 end_reg_,
2997 variant->backtrack());
2264 } else { 2998 } else {
2265 if (compiler->ignore_case()) { 2999 if (compiler->ignore_case()) {
2266 macro->CheckNotBackReferenceIgnoreCase(start_reg_, variant->backtrack()); 3000 assembler->CheckNotBackReferenceIgnoreCase(start_reg_,
3001 variant->backtrack());
2267 } else { 3002 } else {
2268 macro->CheckNotBackReference(start_reg_, variant->backtrack()); 3003 assembler->CheckNotBackReference(start_reg_, variant->backtrack());
2269 } 3004 }
2270 } 3005 }
2271 return on_success()->Emit(compiler, variant); 3006 return on_success()->Emit(compiler, variant);
2272 } 3007 }
2273 3008
2274 3009
2275 // ------------------------------------------------------------------- 3010 // -------------------------------------------------------------------
2276 // Dot/dotty output 3011 // Dot/dotty output
2277 3012
2278 3013
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
2417 3152
2418 void DotPrinter::PrintAttributes(RegExpNode* that) { 3153 void DotPrinter::PrintAttributes(RegExpNode* that) {
2419 stream()->Add(" a%p [shape=Mrecord, color=grey, fontcolor=grey, " 3154 stream()->Add(" a%p [shape=Mrecord, color=grey, fontcolor=grey, "
2420 "margin=0.1, fontsize=10, label=\"{", 3155 "margin=0.1, fontsize=10, label=\"{",
2421 that); 3156 that);
2422 AttributePrinter printer(this); 3157 AttributePrinter printer(this);
2423 NodeInfo* info = that->info(); 3158 NodeInfo* info = that->info();
2424 printer.PrintBit("NI", info->follows_newline_interest); 3159 printer.PrintBit("NI", info->follows_newline_interest);
2425 printer.PrintBit("WI", info->follows_word_interest); 3160 printer.PrintBit("WI", info->follows_word_interest);
2426 printer.PrintBit("SI", info->follows_start_interest); 3161 printer.PrintBit("SI", info->follows_start_interest);
2427 printer.PrintBit("DN", info->determine_newline);
2428 printer.PrintBit("DW", info->determine_word);
2429 printer.PrintBit("DS", info->determine_start);
2430 printer.PrintBit("DDN", info->does_determine_newline);
2431 printer.PrintBit("DDW", info->does_determine_word);
2432 printer.PrintBit("DDS", info->does_determine_start);
2433 printer.PrintPositive("IW", info->is_word);
2434 printer.PrintPositive("IN", info->is_newline);
2435 printer.PrintPositive("FN", info->follows_newline);
2436 printer.PrintPositive("FW", info->follows_word);
2437 printer.PrintPositive("FS", info->follows_start);
2438 Label* label = that->label(); 3162 Label* label = that->label();
2439 if (label->is_bound()) 3163 if (label->is_bound())
2440 printer.PrintPositive("@", label->pos()); 3164 printer.PrintPositive("@", label->pos());
2441 stream()->Add("}\"];\n"); 3165 stream()->Add("}\"];\n");
2442 stream()->Add(" a%p -> n%p [style=dashed, color=grey, " 3166 stream()->Add(" a%p -> n%p [style=dashed, color=grey, "
2443 "arrowhead=none];\n", that, that); 3167 "arrowhead=none];\n", that, that);
2444 } 3168 }
2445 3169
2446 3170
2447 static const bool kPrintDispatchTable = false; 3171 static const bool kPrintDispatchTable = false;
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after
2659 // | ` 3383 // | `
2660 // | (x) 3384 // | (x)
2661 // v ^ 3385 // v ^
2662 // (r=0)-->(?)---/ [if r < t] 3386 // (r=0)-->(?)---/ [if r < t]
2663 // | 3387 // |
2664 // [if r >= f] \----> ... 3388 // [if r >= f] \----> ...
2665 // 3389 //
2666 // 3390 //
2667 // TODO(someone): clear captures on repetition and handle empty 3391 // TODO(someone): clear captures on repetition and handle empty
2668 // matches. 3392 // matches.
3393
3394 // 15.10.2.5 RepeatMatcher algorithm.
3395 // The parser has already eliminated the case where max is 0. In the case
3396 // where max_match is zero the parser has removed the quantifier if min was
3397 // > 0 and removed the atom if min was 0. See AddQuantifierToAtom.
3398
3399 // If we know that we cannot match zero length then things are a little
3400 // simpler since we don't need to make the special zero length match check
3401 // from step 2.1. If the min and max are small we can unroll a little in
3402 // this case.
3403 static const int kMaxUnrolledMinMatches = 3; // Unroll (foo)+ and (foo){3,}
3404 static const int kMaxUnrolledMaxMatches = 3; // Unroll (foo)? and (foo){x,3}
3405 if (max == 0) return on_success; // This can happen due to recursion.
3406 if (body->min_match() > 0) {
3407 if (min > 0 && min <= kMaxUnrolledMinMatches) {
3408 int new_max = (max == kInfinity) ? max : max - min;
3409 // Recurse once to get the loop or optional matches after the fixed ones.
3410 RegExpNode* answer =
3411 ToNode(0, new_max, is_greedy, body, compiler, on_success);
3412 // Unroll the forced matches from 0 to min. This can cause chains of
3413 // TextNodes (which the parser does not generate). These should be
3414 // combined if it turns out they hinder good code generation.
3415 for (int i = 0; i < min; i++) {
3416 answer = body->ToNode(compiler, answer);
3417 }
3418 return answer;
3419 }
3420 if (max <= kMaxUnrolledMaxMatches) {
3421 ASSERT(min == 0);
3422 // Unroll the optional matches up to max.
3423 RegExpNode* answer = on_success;
3424 for (int i = 0; i < max; i++) {
3425 ChoiceNode* alternation = new ChoiceNode(2);
3426 if (is_greedy) {
3427 alternation->AddAlternative(GuardedAlternative(body->ToNode(compiler,
3428 answer)));
3429 alternation->AddAlternative(GuardedAlternative(on_success));
3430 } else {
3431 alternation->AddAlternative(GuardedAlternative(on_success));
3432 alternation->AddAlternative(GuardedAlternative(body->ToNode(compiler,
3433 answer)));
3434 }
3435 answer = alternation;
3436 }
3437 return answer;
3438 }
3439 }
2669 bool has_min = min > 0; 3440 bool has_min = min > 0;
2670 bool has_max = max < RegExpQuantifier::kInfinity; 3441 bool has_max = max < RegExpTree::kInfinity;
2671 bool needs_counter = has_min || has_max; 3442 bool needs_counter = has_min || has_max;
2672 int reg_ctr = needs_counter ? compiler->AllocateRegister() : -1; 3443 int reg_ctr = needs_counter ? compiler->AllocateRegister() : -1;
2673 ChoiceNode* center = new LoopChoiceNode(2); 3444 LoopChoiceNode* center = new LoopChoiceNode(body->min_match() == 0);
2674 RegExpNode* loop_return = needs_counter 3445 RegExpNode* loop_return = needs_counter
2675 ? static_cast<RegExpNode*>(ActionNode::IncrementRegister(reg_ctr, center)) 3446 ? static_cast<RegExpNode*>(ActionNode::IncrementRegister(reg_ctr, center))
2676 : static_cast<RegExpNode*>(center); 3447 : static_cast<RegExpNode*>(center);
2677 RegExpNode* body_node = body->ToNode(compiler, loop_return); 3448 RegExpNode* body_node = body->ToNode(compiler, loop_return);
2678 GuardedAlternative body_alt(body_node); 3449 GuardedAlternative body_alt(body_node);
2679 if (has_max) { 3450 if (has_max) {
2680 Guard* body_guard = new Guard(reg_ctr, Guard::LT, max); 3451 Guard* body_guard = new Guard(reg_ctr, Guard::LT, max);
2681 body_alt.AddGuard(body_guard); 3452 body_alt.AddGuard(body_guard);
2682 } 3453 }
2683 GuardedAlternative rest_alt(on_success); 3454 GuardedAlternative rest_alt(on_success);
2684 if (has_min) { 3455 if (has_min) {
2685 Guard* rest_guard = new Guard(reg_ctr, Guard::GEQ, min); 3456 Guard* rest_guard = new Guard(reg_ctr, Guard::GEQ, min);
2686 rest_alt.AddGuard(rest_guard); 3457 rest_alt.AddGuard(rest_guard);
2687 } 3458 }
2688 if (is_greedy) { 3459 if (is_greedy) {
2689 center->AddAlternative(body_alt); 3460 center->AddLoopAlternative(body_alt);
2690 center->AddAlternative(rest_alt); 3461 center->AddContinueAlternative(rest_alt);
2691 } else { 3462 } else {
2692 center->AddAlternative(rest_alt); 3463 center->AddContinueAlternative(rest_alt);
2693 center->AddAlternative(body_alt); 3464 center->AddLoopAlternative(body_alt);
2694 } 3465 }
2695 if (needs_counter) { 3466 if (needs_counter) {
2696 return ActionNode::SetRegister(reg_ctr, 0, center); 3467 return ActionNode::SetRegister(reg_ctr, 0, center);
2697 } else { 3468 } else {
2698 return center; 3469 return center;
2699 } 3470 }
2700 } 3471 }
2701 3472
2702 3473
2703 RegExpNode* RegExpAssertion::ToNode(RegExpCompiler* compiler, 3474 RegExpNode* RegExpAssertion::ToNode(RegExpCompiler* compiler,
(...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after
3039 RegExpNode* sibling = siblings_.Get(i); 3810 RegExpNode* sibling = siblings_.Get(i);
3040 if (sibling->info()->Matches(info)) 3811 if (sibling->info()->Matches(info))
3041 return sibling; 3812 return sibling;
3042 } 3813 }
3043 return NULL; 3814 return NULL;
3044 } 3815 }
3045 3816
3046 3817
3047 RegExpNode* RegExpNode::EnsureSibling(NodeInfo* info, bool* cloned) { 3818 RegExpNode* RegExpNode::EnsureSibling(NodeInfo* info, bool* cloned) {
3048 ASSERT_EQ(false, *cloned); 3819 ASSERT_EQ(false, *cloned);
3049 ASSERT(!info->HasAssertions());
3050 siblings_.Ensure(this); 3820 siblings_.Ensure(this);
3051 RegExpNode* result = TryGetSibling(info); 3821 RegExpNode* result = TryGetSibling(info);
3052 if (result != NULL) return result; 3822 if (result != NULL) return result;
3053 result = this->Clone(); 3823 result = this->Clone();
3054 NodeInfo* new_info = result->info(); 3824 NodeInfo* new_info = result->info();
3055 new_info->ResetCompilationState(); 3825 new_info->ResetCompilationState();
3056 new_info->AddFromPreceding(info); 3826 new_info->AddFromPreceding(info);
3057 AddSibling(result); 3827 AddSibling(result);
3058 *cloned = true; 3828 *cloned = true;
3059 return result; 3829 return result;
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after
3271 return entry->out_set(); 4041 return entry->out_set();
3272 else 4042 else
3273 return empty(); 4043 return empty();
3274 } 4044 }
3275 4045
3276 4046
3277 // ------------------------------------------------------------------- 4047 // -------------------------------------------------------------------
3278 // Analysis 4048 // Analysis
3279 4049
3280 4050
3281 void AssertionPropagation::EnsureAnalyzed(RegExpNode* that) { 4051 void Analysis::EnsureAnalyzed(RegExpNode* that) {
3282 if (that->info()->been_analyzed || that->info()->being_analyzed) 4052 if (that->info()->been_analyzed || that->info()->being_analyzed)
3283 return; 4053 return;
3284 that->info()->being_analyzed = true; 4054 that->info()->being_analyzed = true;
3285 that->Accept(this); 4055 that->Accept(this);
3286 that->info()->being_analyzed = false; 4056 that->info()->being_analyzed = false;
3287 that->info()->been_analyzed = true; 4057 that->info()->been_analyzed = true;
3288 } 4058 }
3289 4059
3290 4060
3291 void AssertionPropagation::VisitEnd(EndNode* that) { 4061 void Analysis::VisitEnd(EndNode* that) {
3292 // nothing to do 4062 // nothing to do
3293 } 4063 }
3294 4064
3295 4065
3296 void TextNode::CalculateOffsets() { 4066 void TextNode::CalculateOffsets() {
3297 int element_count = elements()->length(); 4067 int element_count = elements()->length();
3298 // Set up the offsets of the elements relative to the start. This is a fixed 4068 // Set up the offsets of the elements relative to the start. This is a fixed
3299 // quantity since a TextNode can only contain fixed-width things. 4069 // quantity since a TextNode can only contain fixed-width things.
3300 int cp_offset = 0; 4070 int cp_offset = 0;
3301 for (int i = 0; i < element_count; i++) { 4071 for (int i = 0; i < element_count; i++) {
3302 TextElement& elm = elements()->at(i); 4072 TextElement& elm = elements()->at(i);
3303 elm.cp_offset = cp_offset; 4073 elm.cp_offset = cp_offset;
3304 if (elm.type == TextElement::ATOM) { 4074 if (elm.type == TextElement::ATOM) {
3305 cp_offset += elm.data.u_atom->data().length(); 4075 cp_offset += elm.data.u_atom->data().length();
3306 } else { 4076 } else {
3307 cp_offset++; 4077 cp_offset++;
3308 Vector<const uc16> quarks = elm.data.u_atom->data(); 4078 Vector<const uc16> quarks = elm.data.u_atom->data();
3309 } 4079 }
3310 } 4080 }
3311 } 4081 }
3312 4082
3313 4083
3314 void AssertionPropagation::VisitText(TextNode* that) { 4084 void Analysis::VisitText(TextNode* that) {
3315 if (ignore_case_) { 4085 if (ignore_case_) {
3316 that->MakeCaseIndependent(); 4086 that->MakeCaseIndependent();
3317 } 4087 }
3318 EnsureAnalyzed(that->on_success()); 4088 EnsureAnalyzed(that->on_success());
3319 NodeInfo* info = that->info();
3320 NodeInfo* next_info = that->on_success()->info();
3321 // If the following node is interested in what it follows then this
3322 // node must determine it.
3323 info->determine_newline = next_info->follows_newline_interest;
3324 info->determine_word = next_info->follows_word_interest;
3325 info->determine_start = next_info->follows_start_interest;
3326 that->CalculateOffsets(); 4089 that->CalculateOffsets();
3327 } 4090 }
3328 4091
3329 4092
3330 void AssertionPropagation::VisitAction(ActionNode* that) { 4093 void Analysis::VisitAction(ActionNode* that) {
3331 RegExpNode* target = that->on_success(); 4094 RegExpNode* target = that->on_success();
3332 EnsureAnalyzed(target); 4095 EnsureAnalyzed(target);
3333 // If the next node is interested in what it follows then this node 4096 // If the next node is interested in what it follows then this node
3334 // has to be interested too so it can pass the information on. 4097 // has to be interested too so it can pass the information on.
3335 that->info()->AddFromFollowing(target->info()); 4098 that->info()->AddFromFollowing(target->info());
3336 } 4099 }
3337 4100
3338 4101
3339 void AssertionPropagation::VisitChoice(ChoiceNode* that) { 4102 void Analysis::VisitChoice(ChoiceNode* that) {
3340 NodeInfo* info = that->info(); 4103 NodeInfo* info = that->info();
3341 for (int i = 0; i < that->alternatives()->length(); i++) { 4104 for (int i = 0; i < that->alternatives()->length(); i++) {
3342 RegExpNode* node = that->alternatives()->at(i).node(); 4105 RegExpNode* node = that->alternatives()->at(i).node();
3343 EnsureAnalyzed(node); 4106 EnsureAnalyzed(node);
3344 // Anything the following nodes need to know has to be known by 4107 // Anything the following nodes need to know has to be known by
3345 // this node also, so it can pass it on. 4108 // this node also, so it can pass it on.
3346 info->AddFromFollowing(node->info()); 4109 info->AddFromFollowing(node->info());
3347 } 4110 }
3348 } 4111 }
3349 4112
3350 4113
3351 void AssertionPropagation::VisitBackReference(BackReferenceNode* that) { 4114 void Analysis::VisitLoopChoice(LoopChoiceNode* that) {
3352 EnsureAnalyzed(that->on_success()); 4115 NodeInfo* info = that->info();
4116 for (int i = 0; i < that->alternatives()->length(); i++) {
4117 RegExpNode* node = that->alternatives()->at(i).node();
4118 if (node != that->loop_node()) {
4119 EnsureAnalyzed(node);
4120 info->AddFromFollowing(node->info());
4121 }
4122 }
4123 // Check the loop last since it may need the value of this node
4124 // to get a correct result.
4125 EnsureAnalyzed(that->loop_node());
4126 info->AddFromFollowing(that->loop_node()->info());
3353 } 4127 }
3354 4128
3355 4129
3356 // ------------------------------------------------------------------- 4130 void Analysis::VisitBackReference(BackReferenceNode* that) {
3357 // Assumption expansion 4131 EnsureAnalyzed(that->on_success());
3358
3359
3360 RegExpNode* RegExpNode::EnsureExpanded(NodeInfo* info) {
3361 siblings_.Ensure(this);
3362 NodeInfo new_info = *this->info();
3363 if (new_info.follows_word_interest)
3364 new_info.follows_word = info->follows_word;
3365 if (new_info.follows_newline_interest)
3366 new_info.follows_newline = info->follows_newline;
3367 // If the following node should determine something we need to get
3368 // a sibling that determines it.
3369 new_info.does_determine_newline = new_info.determine_newline;
3370 new_info.does_determine_word = new_info.determine_word;
3371 new_info.does_determine_start = new_info.determine_start;
3372 RegExpNode* sibling = TryGetSibling(&new_info);
3373 if (sibling == NULL) {
3374 sibling = ExpandLocal(&new_info);
3375 siblings_.Add(sibling);
3376 sibling->info()->being_expanded = true;
3377 sibling->ExpandChildren();
3378 sibling->info()->being_expanded = false;
3379 sibling->info()->been_expanded = true;
3380 } else {
3381 NodeInfo* sib_info = sibling->info();
3382 if (!sib_info->been_expanded && !sib_info->being_expanded) {
3383 sibling->info()->being_expanded = true;
3384 sibling->ExpandChildren();
3385 sibling->info()->being_expanded = false;
3386 sibling->info()->been_expanded = true;
3387 }
3388 }
3389 return sibling;
3390 }
3391
3392
3393 RegExpNode* ChoiceNode::ExpandLocal(NodeInfo* info) {
3394 ChoiceNode* clone = this->Clone();
3395 clone->info()->ResetCompilationState();
3396 clone->info()->AddAssumptions(info);
3397 return clone;
3398 }
3399
3400
3401 void ChoiceNode::ExpandChildren() {
3402 ZoneList<GuardedAlternative>* alts = alternatives();
3403 ZoneList<GuardedAlternative>* new_alts
3404 = new ZoneList<GuardedAlternative>(alts->length());
3405 for (int i = 0; i < alts->length(); i++) {
3406 GuardedAlternative next = alts->at(i);
3407 next.set_node(next.node()->EnsureExpanded(info()));
3408 new_alts->Add(next);
3409 }
3410 alternatives_ = new_alts;
3411 }
3412
3413
3414 RegExpNode* TextNode::ExpandLocal(NodeInfo* info) {
3415 TextElement last = elements()->last();
3416 if (last.type == TextElement::CHAR_CLASS) {
3417 RegExpCharacterClass* char_class = last.data.u_char_class;
3418 if (info->does_determine_word) {
3419 ZoneList<CharacterRange>* word = NULL;
3420 ZoneList<CharacterRange>* non_word = NULL;
3421 CharacterRange::Split(char_class->ranges(),
3422 CharacterRange::GetWordBounds(),
3423 &word,
3424 &non_word);
3425 if (non_word == NULL) {
3426 // This node contains no non-word characters so it must be
3427 // all word.
3428 this->info()->is_word = NodeInfo::TRUE;
3429 } else if (word == NULL) {
3430 // Vice versa.
3431 this->info()->is_word = NodeInfo::FALSE;
3432 } else {
3433 // If this character class contains both word and non-word
3434 // characters we need to split it into two.
3435 ChoiceNode* result = new ChoiceNode(2);
3436 // Welcome to the family, son!
3437 result->set_siblings(this->siblings());
3438 *result->info() = *this->info();
3439 result->info()->ResetCompilationState();
3440 result->info()->AddAssumptions(info);
3441 RegExpNode* word_node
3442 = new TextNode(new RegExpCharacterClass(word, false),
3443 on_success());
3444 word_node->info()->determine_word = true;
3445 word_node->info()->does_determine_word = true;
3446 word_node->info()->is_word = NodeInfo::TRUE;
3447 result->alternatives()->Add(GuardedAlternative(word_node));
3448 RegExpNode* non_word_node
3449 = new TextNode(new RegExpCharacterClass(non_word, false),
3450 on_success());
3451 non_word_node->info()->determine_word = true;
3452 non_word_node->info()->does_determine_word = true;
3453 non_word_node->info()->is_word = NodeInfo::FALSE;
3454 result->alternatives()->Add(GuardedAlternative(non_word_node));
3455 return result;
3456 }
3457 }
3458 }
3459 TextNode* clone = this->Clone();
3460 clone->info()->ResetCompilationState();
3461 clone->info()->AddAssumptions(info);
3462 return clone;
3463 }
3464
3465
3466 void TextNode::ExpandAtomChildren(RegExpAtom* that) {
3467 NodeInfo new_info = *info();
3468 uc16 last = that->data()[that->data().length() - 1];
3469 if (info()->determine_word) {
3470 new_info.follows_word = IsRegExpWord(last)
3471 ? NodeInfo::TRUE : NodeInfo::FALSE;
3472 } else {
3473 new_info.follows_word = NodeInfo::UNKNOWN;
3474 }
3475 if (info()->determine_newline) {
3476 new_info.follows_newline = IsRegExpNewline(last)
3477 ? NodeInfo::TRUE : NodeInfo::FALSE;
3478 } else {
3479 new_info.follows_newline = NodeInfo::UNKNOWN;
3480 }
3481 if (info()->determine_start) {
3482 new_info.follows_start = NodeInfo::FALSE;
3483 } else {
3484 new_info.follows_start = NodeInfo::UNKNOWN;
3485 }
3486 set_on_success(on_success()->EnsureExpanded(&new_info));
3487 }
3488
3489
3490 void TextNode::ExpandCharClassChildren(RegExpCharacterClass* that) {
3491 if (info()->does_determine_word) {
3492 // ASSERT(info()->is_word != NodeInfo::UNKNOWN);
3493 NodeInfo next_info = *on_success()->info();
3494 next_info.follows_word = info()->is_word;
3495 set_on_success(on_success()->EnsureExpanded(&next_info));
3496 } else {
3497 set_on_success(on_success()->EnsureExpanded(info()));
3498 }
3499 }
3500
3501
3502 void TextNode::ExpandChildren() {
3503 TextElement last = elements()->last();
3504 switch (last.type) {
3505 case TextElement::ATOM:
3506 ExpandAtomChildren(last.data.u_atom);
3507 break;
3508 case TextElement::CHAR_CLASS:
3509 ExpandCharClassChildren(last.data.u_char_class);
3510 break;
3511 default:
3512 UNREACHABLE();
3513 }
3514 }
3515
3516
3517 RegExpNode* ActionNode::ExpandLocal(NodeInfo* info) {
3518 ActionNode* clone = this->Clone();
3519 clone->info()->ResetCompilationState();
3520 clone->info()->AddAssumptions(info);
3521 return clone;
3522 }
3523
3524
3525 void ActionNode::ExpandChildren() {
3526 set_on_success(on_success()->EnsureExpanded(info()));
3527 }
3528
3529
3530 RegExpNode* BackReferenceNode::ExpandLocal(NodeInfo* info) {
3531 BackReferenceNode* clone = this->Clone();
3532 clone->info()->ResetCompilationState();
3533 clone->info()->AddAssumptions(info);
3534 return clone;
3535 }
3536
3537
3538 void BackReferenceNode::ExpandChildren() {
3539 set_on_success(on_success()->EnsureExpanded(info()));
3540 }
3541
3542
3543 RegExpNode* EndNode::ExpandLocal(NodeInfo* info) {
3544 EndNode* clone = this->Clone();
3545 clone->info()->ResetCompilationState();
3546 clone->info()->AddAssumptions(info);
3547 return clone;
3548 }
3549
3550
3551 void EndNode::ExpandChildren() {
3552 // nothing to do
3553 } 4132 }
3554 4133
3555 4134
3556 // ------------------------------------------------------------------- 4135 // -------------------------------------------------------------------
3557 // Dispatch table construction 4136 // Dispatch table construction
3558 4137
3559 4138
3560 void DispatchTableConstructor::VisitEnd(EndNode* that) { 4139 void DispatchTableConstructor::VisitEnd(EndNode* that) {
3561 AddRange(CharacterRange::Everything()); 4140 AddRange(CharacterRange::Everything());
3562 } 4141 }
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
3656 } 4235 }
3657 } 4236 }
3658 4237
3659 4238
3660 void DispatchTableConstructor::VisitAction(ActionNode* that) { 4239 void DispatchTableConstructor::VisitAction(ActionNode* that) {
3661 RegExpNode* target = that->on_success(); 4240 RegExpNode* target = that->on_success();
3662 target->Accept(this); 4241 target->Accept(this);
3663 } 4242 }
3664 4243
3665 4244
3666 #ifdef DEBUG
3667
3668
3669 class VisitNodeScope {
3670 public:
3671 explicit VisitNodeScope(RegExpNode* node) : node_(node) {
3672 ASSERT(!node->info()->visited);
3673 node->info()->visited = true;
3674 }
3675 ~VisitNodeScope() {
3676 node_->info()->visited = false;
3677 }
3678 private:
3679 RegExpNode* node_;
3680 };
3681
3682
3683 class NodeValidator : public NodeVisitor {
3684 public:
3685 virtual void ValidateInfo(NodeInfo* info) = 0;
3686 #define DECLARE_VISIT(Type) \
3687 virtual void Visit##Type(Type##Node* that);
3688 FOR_EACH_NODE_TYPE(DECLARE_VISIT)
3689 #undef DECLARE_VISIT
3690 };
3691
3692
3693 class PostAnalysisNodeValidator : public NodeValidator {
3694 public:
3695 virtual void ValidateInfo(NodeInfo* info);
3696 };
3697
3698
3699 class PostExpansionNodeValidator : public NodeValidator {
3700 public:
3701 virtual void ValidateInfo(NodeInfo* info);
3702 };
3703
3704
3705 void PostAnalysisNodeValidator::ValidateInfo(NodeInfo* info) {
3706 ASSERT(info->been_analyzed);
3707 }
3708
3709
3710 void PostExpansionNodeValidator::ValidateInfo(NodeInfo* info) {
3711 ASSERT_EQ(info->determine_newline, info->does_determine_newline);
3712 ASSERT_EQ(info->determine_start, info->does_determine_start);
3713 ASSERT_EQ(info->determine_word, info->does_determine_word);
3714 ASSERT_EQ(info->follows_word_interest,
3715 (info->follows_word != NodeInfo::UNKNOWN));
3716 if (false) {
3717 // These are still unimplemented.
3718 ASSERT_EQ(info->follows_start_interest,
3719 (info->follows_start != NodeInfo::UNKNOWN));
3720 ASSERT_EQ(info->follows_newline_interest,
3721 (info->follows_newline != NodeInfo::UNKNOWN));
3722 }
3723 }
3724
3725
3726 void NodeValidator::VisitAction(ActionNode* that) {
3727 if (that->info()->visited) return;
3728 VisitNodeScope scope(that);
3729 ValidateInfo(that->info());
3730 that->on_success()->Accept(this);
3731 }
3732
3733
3734 void NodeValidator::VisitBackReference(BackReferenceNode* that) {
3735 if (that->info()->visited) return;
3736 VisitNodeScope scope(that);
3737 ValidateInfo(that->info());
3738 that->on_success()->Accept(this);
3739 }
3740
3741
3742 void NodeValidator::VisitChoice(ChoiceNode* that) {
3743 if (that->info()->visited) return;
3744 VisitNodeScope scope(that);
3745 ValidateInfo(that->info());
3746 ZoneList<GuardedAlternative>* alts = that->alternatives();
3747 for (int i = 0; i < alts->length(); i++)
3748 alts->at(i).node()->Accept(this);
3749 }
3750
3751
3752 void NodeValidator::VisitEnd(EndNode* that) {
3753 if (that->info()->visited) return;
3754 VisitNodeScope scope(that);
3755 ValidateInfo(that->info());
3756 }
3757
3758
3759 void NodeValidator::VisitText(TextNode* that) {
3760 if (that->info()->visited) return;
3761 VisitNodeScope scope(that);
3762 ValidateInfo(that->info());
3763 that->on_success()->Accept(this);
3764 }
3765
3766
3767 #endif
3768
3769
3770 Handle<FixedArray> RegExpEngine::Compile(RegExpCompileData* data, 4245 Handle<FixedArray> RegExpEngine::Compile(RegExpCompileData* data,
3771 bool ignore_case, 4246 bool ignore_case,
3772 bool is_multiline, 4247 bool is_multiline,
3773 Handle<String> pattern, 4248 Handle<String> pattern,
3774 bool is_ascii) { 4249 bool is_ascii) {
3775 RegExpCompiler compiler(data->capture_count, ignore_case, is_ascii); 4250 RegExpCompiler compiler(data->capture_count, ignore_case, is_ascii);
3776 // Wrap the body of the regexp in capture #0. 4251 // Wrap the body of the regexp in capture #0.
3777 RegExpNode* captured_body = RegExpCapture::ToNode(data->tree, 4252 RegExpNode* captured_body = RegExpCapture::ToNode(data->tree,
3778 0, 4253 0,
3779 &compiler, 4254 &compiler,
3780 compiler.accept()); 4255 compiler.accept());
3781 // Add a .*? at the beginning, outside the body capture. 4256 // Add a .*? at the beginning, outside the body capture.
3782 // Note: We could choose to not add this if the regexp is anchored at 4257 // Note: We could choose to not add this if the regexp is anchored at
3783 // the start of the input but I'm not sure how best to do that and 4258 // the start of the input but I'm not sure how best to do that and
3784 // since we don't even handle ^ yet I'm saving that optimization for 4259 // since we don't even handle ^ yet I'm saving that optimization for
3785 // later. 4260 // later.
3786 RegExpNode* node = RegExpQuantifier::ToNode(0, 4261 RegExpNode* node = RegExpQuantifier::ToNode(0,
3787 RegExpQuantifier::kInfinity, 4262 RegExpTree::kInfinity,
3788 false, 4263 false,
3789 new RegExpCharacterClass('*'), 4264 new RegExpCharacterClass('*'),
3790 &compiler, 4265 &compiler,
3791 captured_body); 4266 captured_body);
3792 AssertionPropagation analysis(ignore_case); 4267 data->node = node;
4268 Analysis analysis(ignore_case);
3793 analysis.EnsureAnalyzed(node); 4269 analysis.EnsureAnalyzed(node);
3794 4270
3795 NodeInfo info = *node->info(); 4271 NodeInfo info = *node->info();
3796 data->has_lookbehind = info.HasLookbehind();
3797 if (data->has_lookbehind) {
3798 // If this node needs information about the preceding text we let
3799 // it start with a character class that consumes a single character
3800 // and proceeds to wherever is appropriate. This means that if
3801 // has_lookbehind is set the code generator must start one character
3802 // before the start position.
3803 node = new TextNode(new RegExpCharacterClass('*'), node);
3804 analysis.EnsureAnalyzed(node);
3805 }
3806
3807 #ifdef DEBUG
3808 PostAnalysisNodeValidator post_analysis_validator;
3809 node->Accept(&post_analysis_validator);
3810 #endif
3811
3812 node = node->EnsureExpanded(&info);
3813
3814 #ifdef DEBUG
3815 PostExpansionNodeValidator post_expansion_validator;
3816 node->Accept(&post_expansion_validator);
3817 #endif
3818
3819 data->node = node;
3820 4272
3821 if (is_multiline && !FLAG_attempt_multiline_irregexp) { 4273 if (is_multiline && !FLAG_attempt_multiline_irregexp) {
3822 return Handle<FixedArray>::null(); 4274 return Handle<FixedArray>::null();
3823 } 4275 }
3824 4276
3825 if (data->has_lookbehind) {
3826 return Handle<FixedArray>::null();
3827 }
3828
3829 if (FLAG_irregexp_native) { 4277 if (FLAG_irregexp_native) {
3830 #ifdef ARM 4278 #ifdef ARM
3831 // Unimplemented, fall-through to bytecode implementation. 4279 // Unimplemented, fall-through to bytecode implementation.
3832 #else // IA32 4280 #else // IA32
3833 RegExpMacroAssemblerIA32::Mode mode; 4281 RegExpMacroAssemblerIA32::Mode mode;
3834 if (is_ascii) { 4282 if (is_ascii) {
3835 mode = RegExpMacroAssemblerIA32::ASCII; 4283 mode = RegExpMacroAssemblerIA32::ASCII;
3836 } else { 4284 } else {
3837 mode = RegExpMacroAssemblerIA32::UC16; 4285 mode = RegExpMacroAssemblerIA32::UC16;
3838 } 4286 }
3839 RegExpMacroAssemblerIA32 macro_assembler(mode, 4287 RegExpMacroAssemblerIA32 macro_assembler(mode,
3840 (data->capture_count + 1) * 2); 4288 (data->capture_count + 1) * 2);
3841 return compiler.Assemble(&macro_assembler, 4289 return compiler.Assemble(&macro_assembler,
3842 node, 4290 node,
3843 data->capture_count, 4291 data->capture_count,
3844 pattern); 4292 pattern);
3845 #endif 4293 #endif
3846 } 4294 }
3847 EmbeddedVector<byte, 1024> codes; 4295 EmbeddedVector<byte, 1024> codes;
3848 RegExpMacroAssemblerIrregexp macro_assembler(codes); 4296 RegExpMacroAssemblerIrregexp macro_assembler(codes);
3849 return compiler.Assemble(&macro_assembler, 4297 return compiler.Assemble(&macro_assembler,
3850 node, 4298 node,
3851 data->capture_count, 4299 data->capture_count,
3852 pattern); 4300 pattern);
3853 } 4301 }
3854 4302
3855 4303
3856 }} // namespace v8::internal 4304 }} // namespace v8::internal
OLDNEW
« no previous file with comments | « src/jsregexp.h ('k') | src/log.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698