| OLD | NEW |
| 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 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 159 void set_to(uc16 value) { to_ = value; } | 159 void set_to(uc16 value) { to_ = value; } |
| 160 bool is_valid() { return from_ <= to_; } | 160 bool is_valid() { return from_ <= to_; } |
| 161 bool IsSingleton() { return (from_ == to_); } | 161 bool IsSingleton() { return (from_ == to_); } |
| 162 private: | 162 private: |
| 163 uc16 from_; | 163 uc16 from_; |
| 164 uc16 to_; | 164 uc16 to_; |
| 165 }; | 165 }; |
| 166 | 166 |
| 167 | 167 |
| 168 template <typename Node, class Callback> | 168 template <typename Node, class Callback> |
| 169 static void DoForEach(Node* node, Callback callback); | 169 static void DoForEach(Node* node, Callback* callback); |
| 170 | 170 |
| 171 | 171 |
| 172 // A zone splay tree. The config type parameter encapsulates the | 172 // A zone splay tree. The config type parameter encapsulates the |
| 173 // different configurations of a concrete splay tree: | 173 // different configurations of a concrete splay tree: |
| 174 // | 174 // |
| 175 // typedef Key: the key type | 175 // typedef Key: the key type |
| 176 // typedef Value: the value type | 176 // typedef Value: the value type |
| 177 // static const kNoKey: the dummy key used when no key is set | 177 // static const kNoKey: the dummy key used when no key is set |
| 178 // static const kNoValue: the dummy value used to initialize nodes | 178 // static const kNoValue: the dummy value used to initialize nodes |
| 179 // int (Compare)(Key& a, Key& b) -> {-1, 0, 1}: comparison function | 179 // int (Compare)(Key& a, Key& b) -> {-1, 0, 1}: comparison function |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 251 Locator() : node_(NULL) { } | 251 Locator() : node_(NULL) { } |
| 252 const Key& key() { return node_->key_; } | 252 const Key& key() { return node_->key_; } |
| 253 Value& value() { return node_->value_; } | 253 Value& value() { return node_->value_; } |
| 254 void set_value(const Value& value) { node_->value_ = value; } | 254 void set_value(const Value& value) { node_->value_ = value; } |
| 255 inline void bind(Node* node) { node_ = node; } | 255 inline void bind(Node* node) { node_ = node; } |
| 256 private: | 256 private: |
| 257 Node* node_; | 257 Node* node_; |
| 258 }; | 258 }; |
| 259 | 259 |
| 260 template <class Callback> | 260 template <class Callback> |
| 261 void ForEach(Callback c) { | 261 void ForEach(Callback* c) { |
| 262 DoForEach<typename ZoneSplayTree<Config>::Node, Callback>(root_, c); | 262 DoForEach<typename ZoneSplayTree<Config>::Node, Callback>(root_, c); |
| 263 } | 263 } |
| 264 | 264 |
| 265 private: | 265 private: |
| 266 Node* root_; | 266 Node* root_; |
| 267 }; | 267 }; |
| 268 | 268 |
| 269 | 269 |
| 270 // A set of unsigned integers that behaves especially well on small | 270 // A set of unsigned integers that behaves especially well on small |
| 271 // integers (< 32). May do zone-allocation. | 271 // integers (< 32). May do zone-allocation. |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 330 else | 330 else |
| 331 return 1; | 331 return 1; |
| 332 } | 332 } |
| 333 }; | 333 }; |
| 334 | 334 |
| 335 void AddRange(CharacterRange range, int value); | 335 void AddRange(CharacterRange range, int value); |
| 336 OutSet* Get(uc16 value); | 336 OutSet* Get(uc16 value); |
| 337 void Dump(); | 337 void Dump(); |
| 338 | 338 |
| 339 template <typename Callback> | 339 template <typename Callback> |
| 340 void ForEach(Callback callback) { return tree()->ForEach(callback); } | 340 void ForEach(Callback* callback) { return tree()->ForEach(callback); } |
| 341 private: | 341 private: |
| 342 // There can't be a static empty set since it allocates its | 342 // There can't be a static empty set since it allocates its |
| 343 // successors in a zone and caches them. | 343 // successors in a zone and caches them. |
| 344 OutSet* empty() { return &empty_; } | 344 OutSet* empty() { return &empty_; } |
| 345 OutSet empty_; | 345 OutSet empty_; |
| 346 ZoneSplayTree<Config>* tree() { return &tree_; } | 346 ZoneSplayTree<Config>* tree() { return &tree_; } |
| 347 ZoneSplayTree<Config> tree_; | 347 ZoneSplayTree<Config> tree_; |
| 348 }; | 348 }; |
| 349 | 349 |
| 350 | 350 |
| 351 #define FOR_EACH_NODE_TYPE(VISIT) \ | 351 #define FOR_EACH_NODE_TYPE(VISIT) \ |
| 352 VISIT(End) \ | 352 VISIT(End) \ |
| 353 VISIT(Atom) \ | 353 VISIT(Atom) \ |
| 354 VISIT(Action) \ | 354 VISIT(Action) \ |
| 355 VISIT(Choice) \ | 355 VISIT(Choice) \ |
| 356 VISIT(Backreference) \ | 356 VISIT(Backreference) \ |
| 357 VISIT(CharacterClass) | 357 VISIT(CharacterClass) |
| 358 | 358 |
| 359 | 359 |
| 360 class NodeInfo { |
| 361 public: |
| 362 NodeInfo() |
| 363 : being_analyzed(false), |
| 364 been_analyzed(false), |
| 365 propagate_word(false), |
| 366 propagate_line(false) { } |
| 367 bool being_analyzed: 1; |
| 368 bool been_analyzed: 1; |
| 369 bool propagate_word: 1; |
| 370 bool propagate_line: 1; |
| 371 }; |
| 372 |
| 373 |
| 374 STATIC_CHECK(sizeof(NodeInfo) <= sizeof(int)); // NOLINT |
| 375 |
| 376 |
| 360 class RegExpNode: public ZoneObject { | 377 class RegExpNode: public ZoneObject { |
| 361 public: | 378 public: |
| 362 virtual ~RegExpNode() { } | 379 virtual ~RegExpNode() { } |
| 363 virtual void Accept(NodeVisitor* visitor) = 0; | 380 virtual void Accept(NodeVisitor* visitor) = 0; |
| 364 // Generates a goto to this node or actually generates the code at this point. | 381 // Generates a goto to this node or actually generates the code at this point. |
| 365 void GoTo(RegExpCompiler* compiler); | 382 void GoTo(RegExpCompiler* compiler); |
| 366 void EmitAddress(RegExpCompiler* compiler); | 383 void EmitAddress(RegExpCompiler* compiler); |
| 367 virtual void Emit(RegExpCompiler* compiler) = 0; | 384 virtual void Emit(RegExpCompiler* compiler) = 0; |
| 385 NodeInfo* info() { return &info_; } |
| 386 virtual bool IsBacktrack() { return false; } |
| 368 private: | 387 private: |
| 369 Label label; | 388 Label label; |
| 389 NodeInfo info_; |
| 370 }; | 390 }; |
| 371 | 391 |
| 372 | 392 |
| 373 class SeqRegExpNode: public RegExpNode { | 393 class SeqRegExpNode: public RegExpNode { |
| 374 public: | 394 public: |
| 375 explicit SeqRegExpNode(RegExpNode* on_success) | 395 explicit SeqRegExpNode(RegExpNode* on_success) |
| 376 : on_success_(on_success) { } | 396 : on_success_(on_success) { } |
| 377 RegExpNode* on_success() { return on_success_; } | 397 RegExpNode* on_success() { return on_success_; } |
| 378 virtual void Emit(RegExpCompiler* compiler) { UNREACHABLE(); } | 398 virtual void Emit(RegExpCompiler* compiler) { UNREACHABLE(); } |
| 379 private: | 399 private: |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 483 private: | 503 private: |
| 484 RegExpNode* on_failure_; | 504 RegExpNode* on_failure_; |
| 485 ZoneList<CharacterRange>* ranges_; | 505 ZoneList<CharacterRange>* ranges_; |
| 486 bool is_negated_; | 506 bool is_negated_; |
| 487 }; | 507 }; |
| 488 | 508 |
| 489 | 509 |
| 490 class EndNode: public RegExpNode { | 510 class EndNode: public RegExpNode { |
| 491 public: | 511 public: |
| 492 enum Action { ACCEPT, BACKTRACK }; | 512 enum Action { ACCEPT, BACKTRACK }; |
| 513 explicit EndNode(Action action) : action_(action) { } |
| 493 virtual void Accept(NodeVisitor* visitor); | 514 virtual void Accept(NodeVisitor* visitor); |
| 494 static EndNode* GetAccept() { return &kAccept; } | |
| 495 static EndNode* GetBacktrack() { return &kBacktrack; } | |
| 496 virtual void Emit(RegExpCompiler* compiler) { UNREACHABLE(); } | 515 virtual void Emit(RegExpCompiler* compiler) { UNREACHABLE(); } |
| 516 virtual bool IsBacktrack() { return action_ == BACKTRACK; } |
| 497 private: | 517 private: |
| 498 explicit EndNode(Action action) : action_(action) { } | |
| 499 Action action_; | 518 Action action_; |
| 500 static EndNode kAccept; | |
| 501 static EndNode kBacktrack; | |
| 502 }; | 519 }; |
| 503 | 520 |
| 504 | 521 |
| 505 class Guard: public ZoneObject { | 522 class Guard: public ZoneObject { |
| 506 public: | 523 public: |
| 507 enum Relation { LT, GEQ }; | 524 enum Relation { LT, GEQ }; |
| 508 Guard(int reg, Relation op, int value) | 525 Guard(int reg, Relation op, int value) |
| 509 : reg_(reg), | 526 : reg_(reg), |
| 510 op_(op), | 527 op_(op), |
| 511 value_(value) { } | 528 value_(value) { } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 528 private: | 545 private: |
| 529 RegExpNode* node_; | 546 RegExpNode* node_; |
| 530 ZoneList<Guard*>* guards_; | 547 ZoneList<Guard*>* guards_; |
| 531 }; | 548 }; |
| 532 | 549 |
| 533 | 550 |
| 534 class ChoiceNode: public RegExpNode { | 551 class ChoiceNode: public RegExpNode { |
| 535 public: | 552 public: |
| 536 explicit ChoiceNode(int expected_size, RegExpNode* on_failure) | 553 explicit ChoiceNode(int expected_size, RegExpNode* on_failure) |
| 537 : on_failure_(on_failure), | 554 : on_failure_(on_failure), |
| 538 choices_(new ZoneList<GuardedAlternative>(expected_size)), | 555 alternatives_(new ZoneList<GuardedAlternative>(expected_size)), |
| 539 visited_(false) { } | 556 table_calculated_(false), |
| 557 being_calculated_(false) { } |
| 540 virtual void Accept(NodeVisitor* visitor); | 558 virtual void Accept(NodeVisitor* visitor); |
| 541 void AddChild(GuardedAlternative node) { choices()->Add(node); } | 559 void AddAlternative(GuardedAlternative node) { alternatives()->Add(node); } |
| 542 ZoneList<GuardedAlternative>* choices() { return choices_; } | 560 ZoneList<GuardedAlternative>* alternatives() { return alternatives_; } |
| 543 DispatchTable* table() { return &table_; } | 561 DispatchTable* table() { return &table_; } |
| 544 RegExpNode* on_failure() { return on_failure_; } | 562 RegExpNode* on_failure() { return on_failure_; } |
| 545 virtual void Emit(RegExpCompiler* compiler); | 563 virtual void Emit(RegExpCompiler* compiler); |
| 546 bool visited() { return visited_; } | 564 bool table_calculated() { return table_calculated_; } |
| 547 void set_visited(bool value) { visited_ = value; } | 565 void set_table_calculated(bool b) { table_calculated_ = b; } |
| 566 bool being_calculated() { return being_calculated_; } |
| 567 void set_being_calculated(bool b) { being_calculated_ = b; } |
| 548 private: | 568 private: |
| 549 RegExpNode* on_failure_; | 569 RegExpNode* on_failure_; |
| 550 ZoneList<GuardedAlternative>* choices_; | 570 ZoneList<GuardedAlternative>* alternatives_; |
| 551 DispatchTable table_; | 571 DispatchTable table_; |
| 552 bool visited_; | 572 bool table_calculated_; |
| 573 bool being_calculated_; |
| 553 }; | 574 }; |
| 554 | 575 |
| 555 | 576 |
| 577 class NodeVisitor { |
| 578 public: |
| 579 virtual ~NodeVisitor() { } |
| 580 #define DECLARE_VISIT(Type) \ |
| 581 virtual void Visit##Type(Type##Node* that) = 0; |
| 582 FOR_EACH_NODE_TYPE(DECLARE_VISIT) |
| 583 #undef DECLARE_VISIT |
| 584 }; |
| 585 |
| 586 |
| 587 // Node visitor used to add the start set of the alternatives to the |
| 588 // dispatch table of a choice node. |
| 589 class DispatchTableConstructor: public NodeVisitor { |
| 590 public: |
| 591 explicit DispatchTableConstructor(DispatchTable* table) |
| 592 : table_(table), |
| 593 choice_index_(-1) { } |
| 594 |
| 595 void BuildTable(ChoiceNode* node); |
| 596 |
| 597 void AddRange(CharacterRange range) { |
| 598 table()->AddRange(range, choice_index_); |
| 599 } |
| 600 |
| 601 void AddInverse(ZoneList<CharacterRange>* ranges); |
| 602 |
| 603 #define DECLARE_VISIT(Type) \ |
| 604 virtual void Visit##Type(Type##Node* that); |
| 605 FOR_EACH_NODE_TYPE(DECLARE_VISIT) |
| 606 #undef DECLARE_VISIT |
| 607 |
| 608 DispatchTable* table() { return table_; } |
| 609 void set_choice_index(int value) { choice_index_ = value; } |
| 610 |
| 611 protected: |
| 612 DispatchTable *table_; |
| 613 int choice_index_; |
| 614 }; |
| 615 |
| 616 |
| 617 class Analysis: public NodeVisitor { |
| 618 public: |
| 619 void EnsureAnalyzed(RegExpNode* node); |
| 620 |
| 621 #define DECLARE_VISIT(Type) \ |
| 622 virtual void Visit##Type(Type##Node* that); |
| 623 FOR_EACH_NODE_TYPE(DECLARE_VISIT) |
| 624 #undef DECLARE_VISIT |
| 625 }; |
| 626 |
| 627 |
| 556 struct RegExpParseResult { | 628 struct RegExpParseResult { |
| 557 RegExpTree* tree; | 629 RegExpTree* tree; |
| 558 bool has_character_escapes; | 630 bool has_character_escapes; |
| 559 Handle<String> error; | 631 Handle<String> error; |
| 560 int capture_count; | 632 int capture_count; |
| 561 }; | 633 }; |
| 562 | 634 |
| 563 | 635 |
| 564 class RegExpEngine: public AllStatic { | 636 class RegExpEngine: public AllStatic { |
| 565 public: | 637 public: |
| 566 static RegExpNode* Compile(RegExpParseResult* input); | 638 static RegExpNode* Compile(RegExpParseResult* input); |
| 567 static void DotPrint(const char* label, RegExpNode* node); | 639 static void DotPrint(const char* label, RegExpNode* node); |
| 568 }; | 640 }; |
| 569 | 641 |
| 570 | 642 |
| 571 class RegExpCompiler; | |
| 572 | |
| 573 | |
| 574 } } // namespace v8::internal | 643 } } // namespace v8::internal |
| 575 | 644 |
| 576 #endif // V8_JSREGEXP_H_ | 645 #endif // V8_JSREGEXP_H_ |
| OLD | NEW |