| Index: runtime/vm/regexp.cc
|
| diff --git a/runtime/vm/regexp.cc b/runtime/vm/regexp.cc
|
| index 70af0315a4daf6a9de4a06b8c0e3334c1ddacc9e..fbbc1b7ccbd6f969773124084530f083dd8e7f0e 100644
|
| --- a/runtime/vm/regexp.cc
|
| +++ b/runtime/vm/regexp.cc
|
| @@ -9,10 +9,10 @@
|
| #include "vm/regexp_assembler_bytecode.h"
|
| #include "vm/regexp_assembler_ir.h"
|
| #include "vm/regexp_ast.h"
|
| -#include "vm/unibrow-inl.h"
|
| -#include "vm/unicode.h"
|
| #include "vm/symbols.h"
|
| #include "vm/thread.h"
|
| +#include "vm/unibrow-inl.h"
|
| +#include "vm/unicode.h"
|
|
|
| #define Z (zone())
|
|
|
| @@ -196,38 +196,31 @@ ContainedInLattice AddRange(ContainedInLattice containment,
|
| // trace is not recorded in the node and so it cannot currently be reused in
|
| // the event that code generation is requested for an identical trace.
|
|
|
| -
|
| void RegExpTree::AppendToText(RegExpText* text) {
|
| UNREACHABLE();
|
| }
|
|
|
| -
|
| void RegExpAtom::AppendToText(RegExpText* text) {
|
| text->AddElement(TextElement::Atom(this));
|
| }
|
|
|
| -
|
| void RegExpCharacterClass::AppendToText(RegExpText* text) {
|
| text->AddElement(TextElement::CharClass(this));
|
| }
|
|
|
| -
|
| void RegExpText::AppendToText(RegExpText* text) {
|
| for (intptr_t i = 0; i < elements()->length(); i++)
|
| text->AddElement((*elements())[i]);
|
| }
|
|
|
| -
|
| TextElement TextElement::Atom(RegExpAtom* atom) {
|
| return TextElement(ATOM, atom);
|
| }
|
|
|
| -
|
| TextElement TextElement::CharClass(RegExpCharacterClass* char_class) {
|
| return TextElement(CHAR_CLASS, char_class);
|
| }
|
|
|
| -
|
| intptr_t TextElement::length() const {
|
| switch (text_type()) {
|
| case ATOM:
|
| @@ -240,7 +233,6 @@ intptr_t TextElement::length() const {
|
| return 0;
|
| }
|
|
|
| -
|
| class FrequencyCollator : public ValueObject {
|
| public:
|
| FrequencyCollator() : total_samples_(0) {
|
| @@ -283,13 +275,11 @@ class FrequencyCollator : public ValueObject {
|
| DISALLOW_ALLOCATION();
|
| };
|
|
|
| -
|
| private:
|
| CharacterFrequency frequencies_[RegExpMacroAssembler::kTableSize];
|
| intptr_t total_samples_;
|
| };
|
|
|
| -
|
| class RegExpCompiler : public ValueObject {
|
| public:
|
| RegExpCompiler(intptr_t capture_count, bool ignore_case, bool is_one_byte);
|
| @@ -352,7 +342,6 @@ class RegExpCompiler : public ValueObject {
|
| Zone* zone_;
|
| };
|
|
|
| -
|
| class RecursionCheck : public ValueObject {
|
| public:
|
| explicit RecursionCheck(RegExpCompiler* compiler) : compiler_(compiler) {
|
| @@ -364,12 +353,10 @@ class RecursionCheck : public ValueObject {
|
| RegExpCompiler* compiler_;
|
| };
|
|
|
| -
|
| static RegExpEngine::CompilationResult IrregexpRegExpTooBig() {
|
| return RegExpEngine::CompilationResult("RegExp too big");
|
| }
|
|
|
| -
|
| // Attempts to compile the regexp using an Irregexp code generator. Returns
|
| // a fixed array or a null handle depending on whether it succeeded.
|
| RegExpCompiler::RegExpCompiler(intptr_t capture_count,
|
| @@ -386,7 +373,6 @@ RegExpCompiler::RegExpCompiler(intptr_t capture_count,
|
| accept_ = new (Z) EndNode(EndNode::ACCEPT, Z);
|
| }
|
|
|
| -
|
| #if !defined(DART_PRECOMPILED_RUNTIME)
|
| RegExpEngine::CompilationResult RegExpCompiler::Assemble(
|
| IRRegExpMacroAssembler* macro_assembler,
|
| @@ -419,7 +405,6 @@ RegExpEngine::CompilationResult RegExpCompiler::Assemble(
|
| }
|
| #endif
|
|
|
| -
|
| RegExpEngine::CompilationResult RegExpCompiler::Assemble(
|
| BytecodeRegExpMacroAssembler* macro_assembler,
|
| RegExpNode* start,
|
| @@ -445,7 +430,6 @@ RegExpEngine::CompilationResult RegExpCompiler::Assemble(
|
| return RegExpEngine::CompilationResult(&bytecode, next_register_);
|
| }
|
|
|
| -
|
| bool Trace::DeferredAction::Mentions(intptr_t that) {
|
| if (action_type() == ActionNode::CLEAR_CAPTURES) {
|
| Interval range = static_cast<DeferredClearCaptures*>(this)->range();
|
| @@ -455,7 +439,6 @@ bool Trace::DeferredAction::Mentions(intptr_t that) {
|
| }
|
| }
|
|
|
| -
|
| bool Trace::mentions_reg(intptr_t reg) {
|
| for (DeferredAction* action = actions_; action != NULL;
|
| action = action->next()) {
|
| @@ -464,7 +447,6 @@ bool Trace::mentions_reg(intptr_t reg) {
|
| return false;
|
| }
|
|
|
| -
|
| bool Trace::GetStoredPosition(intptr_t reg, intptr_t* cp_offset) {
|
| ASSERT(*cp_offset == 0);
|
| for (DeferredAction* action = actions_; action != NULL;
|
| @@ -481,7 +463,6 @@ bool Trace::GetStoredPosition(intptr_t reg, intptr_t* cp_offset) {
|
| return false;
|
| }
|
|
|
| -
|
| // This is called as we come into a loop choice node and some other tricky
|
| // nodes. It normalizes the state of the code generator to ensure we can
|
| // generate generic code.
|
| @@ -502,7 +483,6 @@ intptr_t Trace::FindAffectedRegisters(OutSet* affected_registers, Zone* zone) {
|
| return max_register;
|
| }
|
|
|
| -
|
| void Trace::RestoreAffectedRegisters(RegExpMacroAssembler* assembler,
|
| intptr_t max_register,
|
| const OutSet& registers_to_pop,
|
| @@ -520,7 +500,6 @@ void Trace::RestoreAffectedRegisters(RegExpMacroAssembler* assembler,
|
| }
|
| }
|
|
|
| -
|
| void Trace::PerformDeferredActions(RegExpMacroAssembler* assembler,
|
| intptr_t max_register,
|
| const OutSet& affected_registers,
|
| @@ -635,7 +614,6 @@ void Trace::PerformDeferredActions(RegExpMacroAssembler* assembler,
|
| }
|
| }
|
|
|
| -
|
| // This is called as we come into a loop choice node and some other tricky
|
| // nodes. It normalizes the state of the code generator to ensure we can
|
| // generate generic code.
|
| @@ -692,7 +670,6 @@ void Trace::Flush(RegExpCompiler* compiler, RegExpNode* successor) {
|
| }
|
| }
|
|
|
| -
|
| void NegativeSubmatchSuccess::Emit(RegExpCompiler* compiler, Trace* trace) {
|
| RegExpMacroAssembler* assembler = compiler->macro_assembler();
|
|
|
| @@ -719,7 +696,6 @@ void NegativeSubmatchSuccess::Emit(RegExpCompiler* compiler, Trace* trace) {
|
| assembler->Backtrack();
|
| }
|
|
|
| -
|
| void EndNode::Emit(RegExpCompiler* compiler, Trace* trace) {
|
| if (!trace->is_trivial()) {
|
| trace->Flush(compiler, this);
|
| @@ -743,13 +719,11 @@ void EndNode::Emit(RegExpCompiler* compiler, Trace* trace) {
|
| UNIMPLEMENTED();
|
| }
|
|
|
| -
|
| void GuardedAlternative::AddGuard(Guard* guard, Zone* zone) {
|
| if (guards_ == NULL) guards_ = new (zone) ZoneGrowableArray<Guard*>(1);
|
| guards_->Add(guard);
|
| }
|
|
|
| -
|
| ActionNode* ActionNode::SetRegister(intptr_t reg,
|
| intptr_t val,
|
| RegExpNode* on_success) {
|
| @@ -760,7 +734,6 @@ ActionNode* ActionNode::SetRegister(intptr_t reg,
|
| return result;
|
| }
|
|
|
| -
|
| ActionNode* ActionNode::IncrementRegister(intptr_t reg,
|
| RegExpNode* on_success) {
|
| ActionNode* result =
|
| @@ -769,7 +742,6 @@ ActionNode* ActionNode::IncrementRegister(intptr_t reg,
|
| return result;
|
| }
|
|
|
| -
|
| ActionNode* ActionNode::StorePosition(intptr_t reg,
|
| bool is_capture,
|
| RegExpNode* on_success) {
|
| @@ -780,7 +752,6 @@ ActionNode* ActionNode::StorePosition(intptr_t reg,
|
| return result;
|
| }
|
|
|
| -
|
| ActionNode* ActionNode::ClearCaptures(Interval range, RegExpNode* on_success) {
|
| ActionNode* result =
|
| new (on_success->zone()) ActionNode(CLEAR_CAPTURES, on_success);
|
| @@ -789,7 +760,6 @@ ActionNode* ActionNode::ClearCaptures(Interval range, RegExpNode* on_success) {
|
| return result;
|
| }
|
|
|
| -
|
| ActionNode* ActionNode::BeginSubmatch(intptr_t stack_reg,
|
| intptr_t position_reg,
|
| RegExpNode* on_success) {
|
| @@ -800,7 +770,6 @@ ActionNode* ActionNode::BeginSubmatch(intptr_t stack_reg,
|
| return result;
|
| }
|
|
|
| -
|
| ActionNode* ActionNode::PositiveSubmatchSuccess(intptr_t stack_reg,
|
| intptr_t position_reg,
|
| intptr_t clear_register_count,
|
| @@ -815,7 +784,6 @@ ActionNode* ActionNode::PositiveSubmatchSuccess(intptr_t stack_reg,
|
| return result;
|
| }
|
|
|
| -
|
| ActionNode* ActionNode::EmptyMatchCheck(intptr_t start_register,
|
| intptr_t repetition_register,
|
| intptr_t repetition_limit,
|
| @@ -828,22 +796,18 @@ ActionNode* ActionNode::EmptyMatchCheck(intptr_t start_register,
|
| return result;
|
| }
|
|
|
| -
|
| #define DEFINE_ACCEPT(Type) \
|
| void Type##Node::Accept(NodeVisitor* visitor) { visitor->Visit##Type(this); }
|
| FOR_EACH_NODE_TYPE(DEFINE_ACCEPT)
|
| #undef DEFINE_ACCEPT
|
|
|
| -
|
| void LoopChoiceNode::Accept(NodeVisitor* visitor) {
|
| visitor->VisitLoopChoice(this);
|
| }
|
|
|
| -
|
| // -------------------------------------------------------------------
|
| // Emit code.
|
|
|
| -
|
| void ChoiceNode::GenerateGuard(RegExpMacroAssembler* macro_assembler,
|
| Guard* guard,
|
| Trace* trace) {
|
| @@ -861,7 +825,6 @@ void ChoiceNode::GenerateGuard(RegExpMacroAssembler* macro_assembler,
|
| }
|
| }
|
|
|
| -
|
| // Returns the number of characters in the equivalence class, omitting those
|
| // that cannot occur in the source string because it is ASCII.
|
| static intptr_t GetCaseIndependentLetters(uint16_t character,
|
| @@ -886,7 +849,6 @@ static intptr_t GetCaseIndependentLetters(uint16_t character,
|
| return 0;
|
| }
|
|
|
| -
|
| static inline bool EmitSimpleCharacter(Zone* zone,
|
| RegExpCompiler* compiler,
|
| uint16_t c,
|
| @@ -904,7 +866,6 @@ static inline bool EmitSimpleCharacter(Zone* zone,
|
| return bound_checked;
|
| }
|
|
|
| -
|
| // Only emits non-letters (things that don't have case). Only used for case
|
| // independent matches.
|
| static inline bool EmitAtomNonLetter(Zone* zone,
|
| @@ -940,7 +901,6 @@ static inline bool EmitAtomNonLetter(Zone* zone,
|
| return checked;
|
| }
|
|
|
| -
|
| static bool ShortCutEmitCharacterPair(RegExpMacroAssembler* macro_assembler,
|
| bool one_byte,
|
| uint16_t c1,
|
| @@ -977,7 +937,6 @@ static bool ShortCutEmitCharacterPair(RegExpMacroAssembler* macro_assembler,
|
| return false;
|
| }
|
|
|
| -
|
| typedef bool EmitCharacterFunction(Zone* zone,
|
| RegExpCompiler* compiler,
|
| uint16_t c,
|
| @@ -1034,7 +993,6 @@ static inline bool EmitAtomLetter(Zone* zone,
|
| return true;
|
| }
|
|
|
| -
|
| static void EmitBoundaryTest(RegExpMacroAssembler* masm,
|
| intptr_t border,
|
| BlockLabel* fall_through,
|
| @@ -1048,7 +1006,6 @@ static void EmitBoundaryTest(RegExpMacroAssembler* masm,
|
| }
|
| }
|
|
|
| -
|
| static void EmitDoubleBoundaryTest(RegExpMacroAssembler* masm,
|
| intptr_t first,
|
| intptr_t last,
|
| @@ -1071,7 +1028,6 @@ static void EmitDoubleBoundaryTest(RegExpMacroAssembler* masm,
|
| }
|
| }
|
|
|
| -
|
| // even_label is for ranges[i] to ranges[i + 1] where i - start_index is even.
|
| // odd_label is for ranges[i] to ranges[i + 1] where i - start_index is odd.
|
| static void EmitUseLookupTable(RegExpMacroAssembler* masm,
|
| @@ -1131,7 +1087,6 @@ static void EmitUseLookupTable(RegExpMacroAssembler* masm,
|
| if (on_bit_clear != fall_through) masm->GoTo(on_bit_clear);
|
| }
|
|
|
| -
|
| static void CutOutRange(RegExpMacroAssembler* masm,
|
| ZoneGrowableArray<int>* ranges,
|
| intptr_t start_index,
|
| @@ -1157,7 +1112,6 @@ static void CutOutRange(RegExpMacroAssembler* masm,
|
| }
|
| }
|
|
|
| -
|
| // Unicode case. Split the search space into kSize spaces that are handled
|
| // with recursion.
|
| static void SplitSearchSpace(ZoneGrowableArray<int>* ranges,
|
| @@ -1223,7 +1177,6 @@ static void SplitSearchSpace(ZoneGrowableArray<int>* ranges,
|
| }
|
| }
|
|
|
| -
|
| // Gets a series of segment boundaries representing a character class. If the
|
| // character is in the range between an even and an odd boundary (counting from
|
| // start_index) then go to even_label, otherwise go to odd_label. We already
|
| @@ -1344,7 +1297,6 @@ static void GenerateBranches(RegExpMacroAssembler* masm,
|
| }
|
| }
|
|
|
| -
|
| static void EmitCharClass(RegExpMacroAssembler* macro_assembler,
|
| RegExpCharacterClass* cc,
|
| bool one_byte,
|
| @@ -1410,13 +1362,11 @@ static void EmitCharClass(RegExpMacroAssembler* macro_assembler,
|
| macro_assembler->LoadCurrentCharacter(cp_offset, on_failure, check_offset);
|
| }
|
|
|
| - if (cc->is_standard() &&
|
| - macro_assembler->CheckSpecialCharacterClass(cc->standard_type(),
|
| - on_failure)) {
|
| + if (cc->is_standard() && macro_assembler->CheckSpecialCharacterClass(
|
| + cc->standard_type(), on_failure)) {
|
| return;
|
| }
|
|
|
| -
|
| // A new list with ascending entries. Each entry is a code unit
|
| // where there is a boundary between code units that are part of
|
| // the class and code units that are not. Normally we insert an
|
| @@ -1454,10 +1404,8 @@ static void EmitCharClass(RegExpMacroAssembler* macro_assembler,
|
| macro_assembler->BindBlock(&fall_through);
|
| }
|
|
|
| -
|
| RegExpNode::~RegExpNode() {}
|
|
|
| -
|
| RegExpNode::LimitResult RegExpNode::LimitVersions(RegExpCompiler* compiler,
|
| Trace* trace) {
|
| // If we are generating a greedy loop then don't stop and don't reuse code.
|
| @@ -1500,7 +1448,6 @@ RegExpNode::LimitResult RegExpNode::LimitVersions(RegExpCompiler* compiler,
|
| return DONE;
|
| }
|
|
|
| -
|
| intptr_t ActionNode::EatsAtLeast(intptr_t still_to_find,
|
| intptr_t budget,
|
| bool not_at_start) {
|
| @@ -1509,7 +1456,6 @@ intptr_t ActionNode::EatsAtLeast(intptr_t still_to_find,
|
| return on_success()->EatsAtLeast(still_to_find, budget - 1, not_at_start);
|
| }
|
|
|
| -
|
| void ActionNode::FillInBMInfo(intptr_t offset,
|
| intptr_t budget,
|
| BoyerMooreLookahead* bm,
|
| @@ -1522,7 +1468,6 @@ void ActionNode::FillInBMInfo(intptr_t offset,
|
| SaveBMInfo(bm, not_at_start, offset);
|
| }
|
|
|
| -
|
| intptr_t AssertionNode::EatsAtLeast(intptr_t still_to_find,
|
| intptr_t budget,
|
| bool not_at_start) {
|
| @@ -1536,7 +1481,6 @@ intptr_t AssertionNode::EatsAtLeast(intptr_t still_to_find,
|
| return on_success()->EatsAtLeast(still_to_find, budget - 1, not_at_start);
|
| }
|
|
|
| -
|
| void AssertionNode::FillInBMInfo(intptr_t offset,
|
| intptr_t budget,
|
| BoyerMooreLookahead* bm,
|
| @@ -1547,7 +1491,6 @@ void AssertionNode::FillInBMInfo(intptr_t offset,
|
| SaveBMInfo(bm, not_at_start, offset);
|
| }
|
|
|
| -
|
| intptr_t BackReferenceNode::EatsAtLeast(intptr_t still_to_find,
|
| intptr_t budget,
|
| bool not_at_start) {
|
| @@ -1555,7 +1498,6 @@ intptr_t BackReferenceNode::EatsAtLeast(intptr_t still_to_find,
|
| return on_success()->EatsAtLeast(still_to_find, budget - 1, not_at_start);
|
| }
|
|
|
| -
|
| intptr_t TextNode::EatsAtLeast(intptr_t still_to_find,
|
| intptr_t budget,
|
| bool not_at_start) {
|
| @@ -1567,7 +1509,6 @@ intptr_t TextNode::EatsAtLeast(intptr_t still_to_find,
|
| on_success()->EatsAtLeast(still_to_find - answer, budget - 1, true);
|
| }
|
|
|
| -
|
| intptr_t NegativeLookaheadChoiceNode::EatsAtLeast(intptr_t still_to_find,
|
| intptr_t budget,
|
| bool not_at_start) {
|
| @@ -1578,7 +1519,6 @@ intptr_t NegativeLookaheadChoiceNode::EatsAtLeast(intptr_t still_to_find,
|
| return node->EatsAtLeast(still_to_find, budget - 1, not_at_start);
|
| }
|
|
|
| -
|
| void NegativeLookaheadChoiceNode::GetQuickCheckDetails(
|
| QuickCheckDetails* details,
|
| RegExpCompiler* compiler,
|
| @@ -1590,7 +1530,6 @@ void NegativeLookaheadChoiceNode::GetQuickCheckDetails(
|
| return node->GetQuickCheckDetails(details, compiler, filled_in, not_at_start);
|
| }
|
|
|
| -
|
| intptr_t ChoiceNode::EatsAtLeastHelper(intptr_t still_to_find,
|
| intptr_t budget,
|
| RegExpNode* ignore_this_node,
|
| @@ -1610,21 +1549,18 @@ intptr_t ChoiceNode::EatsAtLeastHelper(intptr_t still_to_find,
|
| return min;
|
| }
|
|
|
| -
|
| intptr_t LoopChoiceNode::EatsAtLeast(intptr_t still_to_find,
|
| intptr_t budget,
|
| bool not_at_start) {
|
| return EatsAtLeastHelper(still_to_find, budget - 1, loop_node_, not_at_start);
|
| }
|
|
|
| -
|
| intptr_t ChoiceNode::EatsAtLeast(intptr_t still_to_find,
|
| intptr_t budget,
|
| bool not_at_start) {
|
| return EatsAtLeastHelper(still_to_find, budget, NULL, not_at_start);
|
| }
|
|
|
| -
|
| // Takes the left-most 1-bit and smears it out, setting all bits to its right.
|
| static inline uint32_t SmearBitsRight(uint32_t v) {
|
| v |= v >> 1;
|
| @@ -1635,7 +1571,6 @@ static inline uint32_t SmearBitsRight(uint32_t v) {
|
| return v;
|
| }
|
|
|
| -
|
| bool QuickCheckDetails::Rationalize(bool asc) {
|
| bool found_useful_op = false;
|
| uint32_t char_mask;
|
| @@ -1659,7 +1594,6 @@ bool QuickCheckDetails::Rationalize(bool asc) {
|
| return found_useful_op;
|
| }
|
|
|
| -
|
| bool RegExpNode::EmitQuickCheck(RegExpCompiler* compiler,
|
| Trace* bounds_check_trace,
|
| Trace* trace,
|
| @@ -1690,7 +1624,6 @@ bool RegExpNode::EmitQuickCheck(RegExpCompiler* compiler,
|
| !preload_has_checked_bounds, details->characters());
|
| }
|
|
|
| -
|
| bool need_mask = true;
|
|
|
| if (details->characters() == 1) {
|
| @@ -1732,7 +1665,6 @@ bool RegExpNode::EmitQuickCheck(RegExpCompiler* compiler,
|
| return true;
|
| }
|
|
|
| -
|
| // Here is the meat of GetQuickCheckDetails (see also the comment on the
|
| // super-class in the .h file).
|
| //
|
| @@ -1896,7 +1828,6 @@ void TextNode::GetQuickCheckDetails(QuickCheckDetails* details,
|
| }
|
| }
|
|
|
| -
|
| void QuickCheckDetails::Clear() {
|
| for (int i = 0; i < characters_; i++) {
|
| positions_[i].mask = 0;
|
| @@ -1906,7 +1837,6 @@ void QuickCheckDetails::Clear() {
|
| characters_ = 0;
|
| }
|
|
|
| -
|
| void QuickCheckDetails::Advance(intptr_t by, bool one_byte) {
|
| ASSERT(by >= 0);
|
| if (by >= characters_) {
|
| @@ -1927,7 +1857,6 @@ void QuickCheckDetails::Advance(intptr_t by, bool one_byte) {
|
| // it would gain us nothing. So there's no point.
|
| }
|
|
|
| -
|
| void QuickCheckDetails::Merge(QuickCheckDetails* other, intptr_t from_index) {
|
| ASSERT(characters_ == other->characters_);
|
| if (other->cannot_match_) {
|
| @@ -1955,7 +1884,6 @@ void QuickCheckDetails::Merge(QuickCheckDetails* other, intptr_t from_index) {
|
| }
|
| }
|
|
|
| -
|
| class VisitMarker : public ValueObject {
|
| public:
|
| explicit VisitMarker(NodeInfo* info) : info_(info) {
|
| @@ -1968,7 +1896,6 @@ class VisitMarker : public ValueObject {
|
| NodeInfo* info_;
|
| };
|
|
|
| -
|
| RegExpNode* SeqRegExpNode::FilterOneByte(intptr_t depth, bool ignore_case) {
|
| if (info()->replacement_calculated) return replacement();
|
| if (depth < 0) return this;
|
| @@ -1977,7 +1904,6 @@ RegExpNode* SeqRegExpNode::FilterOneByte(intptr_t depth, bool ignore_case) {
|
| return FilterSuccessor(depth - 1, ignore_case);
|
| }
|
|
|
| -
|
| RegExpNode* SeqRegExpNode::FilterSuccessor(intptr_t depth, bool ignore_case) {
|
| RegExpNode* next = on_success_->FilterOneByte(depth - 1, ignore_case);
|
| if (next == NULL) return set_replacement(NULL);
|
| @@ -1985,7 +1911,6 @@ RegExpNode* SeqRegExpNode::FilterSuccessor(intptr_t depth, bool ignore_case) {
|
| return set_replacement(this);
|
| }
|
|
|
| -
|
| // We need to check for the following characters: 0x39c 0x3bc 0x178.
|
| static inline bool RangeContainsLatin1Equivalents(CharacterRange range) {
|
| // TODO(dcarney): this could be a lot more efficient.
|
| @@ -1993,7 +1918,6 @@ static inline bool RangeContainsLatin1Equivalents(CharacterRange range) {
|
| range.Contains(0x178);
|
| }
|
|
|
| -
|
| static bool RangesContainLatin1Equivalents(
|
| ZoneGrowableArray<CharacterRange>* ranges) {
|
| for (intptr_t i = 0; i < ranges->length(); i++) {
|
| @@ -2003,7 +1927,6 @@ static bool RangesContainLatin1Equivalents(
|
| return false;
|
| }
|
|
|
| -
|
| static uint16_t ConvertNonLatin1ToLatin1(uint16_t c) {
|
| ASSERT(c > Symbols::kMaxOneCharCodeSymbol);
|
| switch (c) {
|
| @@ -2019,7 +1942,6 @@ static uint16_t ConvertNonLatin1ToLatin1(uint16_t c) {
|
| return 0;
|
| }
|
|
|
| -
|
| RegExpNode* TextNode::FilterOneByte(intptr_t depth, bool ignore_case) {
|
| if (info()->replacement_calculated) return replacement();
|
| if (depth < 0) return this;
|
| @@ -2071,7 +1993,6 @@ RegExpNode* TextNode::FilterOneByte(intptr_t depth, bool ignore_case) {
|
| return FilterSuccessor(depth - 1, ignore_case);
|
| }
|
|
|
| -
|
| RegExpNode* LoopChoiceNode::FilterOneByte(intptr_t depth, bool ignore_case) {
|
| if (info()->replacement_calculated) return replacement();
|
| if (depth < 0) return this;
|
| @@ -2089,7 +2010,6 @@ RegExpNode* LoopChoiceNode::FilterOneByte(intptr_t depth, bool ignore_case) {
|
| return ChoiceNode::FilterOneByte(depth - 1, ignore_case);
|
| }
|
|
|
| -
|
| RegExpNode* ChoiceNode::FilterOneByte(intptr_t depth, bool ignore_case) {
|
| if (info()->replacement_calculated) return replacement();
|
| if (depth < 0) return this;
|
| @@ -2140,7 +2060,6 @@ RegExpNode* ChoiceNode::FilterOneByte(intptr_t depth, bool ignore_case) {
|
| return this;
|
| }
|
|
|
| -
|
| RegExpNode* NegativeLookaheadChoiceNode::FilterOneByte(intptr_t depth,
|
| bool ignore_case) {
|
| if (info()->replacement_calculated) return replacement();
|
| @@ -2163,7 +2082,6 @@ RegExpNode* NegativeLookaheadChoiceNode::FilterOneByte(intptr_t depth,
|
| return set_replacement(this);
|
| }
|
|
|
| -
|
| void LoopChoiceNode::GetQuickCheckDetails(QuickCheckDetails* details,
|
| RegExpCompiler* compiler,
|
| intptr_t characters_filled_in,
|
| @@ -2174,7 +2092,6 @@ void LoopChoiceNode::GetQuickCheckDetails(QuickCheckDetails* details,
|
| characters_filled_in, not_at_start);
|
| }
|
|
|
| -
|
| void LoopChoiceNode::FillInBMInfo(intptr_t offset,
|
| intptr_t budget,
|
| BoyerMooreLookahead* bm,
|
| @@ -2188,7 +2105,6 @@ void LoopChoiceNode::FillInBMInfo(intptr_t offset,
|
| SaveBMInfo(bm, not_at_start, offset);
|
| }
|
|
|
| -
|
| void ChoiceNode::GetQuickCheckDetails(QuickCheckDetails* details,
|
| RegExpCompiler* compiler,
|
| intptr_t characters_filled_in,
|
| @@ -2208,7 +2124,6 @@ void ChoiceNode::GetQuickCheckDetails(QuickCheckDetails* details,
|
| }
|
| }
|
|
|
| -
|
| // Check for [0-9A-Z_a-z].
|
| static void EmitWordCheck(RegExpMacroAssembler* assembler,
|
| BlockLabel* word,
|
| @@ -2233,7 +2148,6 @@ static void EmitWordCheck(RegExpMacroAssembler* assembler,
|
| }
|
| }
|
|
|
| -
|
| // Emit the code to check for a ^ in multiline mode (1-character lookbehind
|
| // that matches newline or the start of input).
|
| static void EmitHat(RegExpCompiler* compiler,
|
| @@ -2267,7 +2181,6 @@ static void EmitHat(RegExpCompiler* compiler,
|
| on_success->Emit(compiler, &new_trace);
|
| }
|
|
|
| -
|
| // Emit the code to handle \b and \B (word-boundary or non-word-boundary).
|
| void AssertionNode::EmitBoundaryCheck(RegExpCompiler* compiler, Trace* trace) {
|
| RegExpMacroAssembler* assembler = compiler->macro_assembler();
|
| @@ -2322,7 +2235,6 @@ void AssertionNode::EmitBoundaryCheck(RegExpCompiler* compiler, Trace* trace) {
|
| }
|
| }
|
|
|
| -
|
| void AssertionNode::BacktrackIfPrevious(
|
| RegExpCompiler* compiler,
|
| Trace* trace,
|
| @@ -2354,7 +2266,6 @@ void AssertionNode::BacktrackIfPrevious(
|
| on_success()->Emit(compiler, &new_trace);
|
| }
|
|
|
| -
|
| void AssertionNode::GetQuickCheckDetails(QuickCheckDetails* details,
|
| RegExpCompiler* compiler,
|
| intptr_t filled_in,
|
| @@ -2367,7 +2278,6 @@ void AssertionNode::GetQuickCheckDetails(QuickCheckDetails* details,
|
| not_at_start);
|
| }
|
|
|
| -
|
| void AssertionNode::Emit(RegExpCompiler* compiler, Trace* trace) {
|
| RegExpMacroAssembler* assembler = compiler->macro_assembler();
|
| switch (assertion_type_) {
|
| @@ -2403,21 +2313,18 @@ void AssertionNode::Emit(RegExpCompiler* compiler, Trace* trace) {
|
| on_success()->Emit(compiler, trace);
|
| }
|
|
|
| -
|
| static bool DeterminedAlready(QuickCheckDetails* quick_check, intptr_t offset) {
|
| if (quick_check == NULL) return false;
|
| if (offset >= quick_check->characters()) return false;
|
| return quick_check->positions(offset)->determines_perfectly;
|
| }
|
|
|
| -
|
| static void UpdateBoundsCheck(intptr_t index, intptr_t* checked_up_to) {
|
| if (index > *checked_up_to) {
|
| *checked_up_to = index;
|
| }
|
| }
|
|
|
| -
|
| // We call this repeatedly to generate code for each pass over the text node.
|
| // The passes are in increasing order of difficulty because we hope one
|
| // of the first passes will fail in which case we are saved the work of the
|
| @@ -2508,14 +2415,12 @@ void TextNode::TextEmitPass(RegExpCompiler* compiler,
|
| }
|
| }
|
|
|
| -
|
| intptr_t TextNode::Length() {
|
| TextElement elm = elms_->Last();
|
| ASSERT(elm.cp_offset() >= 0);
|
| return elm.cp_offset() + elm.length();
|
| }
|
|
|
| -
|
| bool TextNode::SkipPass(intptr_t intptr_t_pass, bool ignore_case) {
|
| TextEmitPassType pass = static_cast<TextEmitPassType>(intptr_t_pass);
|
| if (ignore_case) {
|
| @@ -2525,7 +2430,6 @@ bool TextNode::SkipPass(intptr_t intptr_t_pass, bool ignore_case) {
|
| }
|
| }
|
|
|
| -
|
| // This generates the code to match a text node. A text node can contain
|
| // straight character sequences (possibly to be matched in a case-independent
|
| // way) and character classes. For efficiency we do not do this in a single
|
| @@ -2577,12 +2481,10 @@ void TextNode::Emit(RegExpCompiler* compiler, Trace* trace) {
|
| on_success()->Emit(compiler, &successor_trace);
|
| }
|
|
|
| -
|
| void Trace::InvalidateCurrentCharacter() {
|
| characters_preloaded_ = 0;
|
| }
|
|
|
| -
|
| void Trace::AdvanceCurrentPositionInTrace(intptr_t by,
|
| RegExpCompiler* compiler) {
|
| ASSERT(by > 0);
|
| @@ -2603,7 +2505,6 @@ void Trace::AdvanceCurrentPositionInTrace(intptr_t by,
|
| Utils::Maximum(static_cast<intptr_t>(0), bound_checked_up_to_ - by);
|
| }
|
|
|
| -
|
| void TextNode::MakeCaseIndependent(bool is_one_byte) {
|
| intptr_t element_count = elms_->length();
|
| for (intptr_t i = 0; i < element_count; i++) {
|
| @@ -2622,13 +2523,11 @@ void TextNode::MakeCaseIndependent(bool is_one_byte) {
|
| }
|
| }
|
|
|
| -
|
| intptr_t TextNode::GreedyLoopTextLength() {
|
| TextElement elm = elms_->At(elms_->length() - 1);
|
| return elm.cp_offset() + elm.length();
|
| }
|
|
|
| -
|
| RegExpNode* TextNode::GetSuccessorOfOmnivorousTextNode(
|
| RegExpCompiler* compiler) {
|
| if (elms_->length() != 1) return NULL;
|
| @@ -2652,7 +2551,6 @@ RegExpNode* TextNode::GetSuccessorOfOmnivorousTextNode(
|
| return ranges->At(0).IsEverything(max_char) ? on_success() : NULL;
|
| }
|
|
|
| -
|
| // Finds the fixed match length of a sequence of nodes that goes from
|
| // this alternative and back to this choice node. If there are variable
|
| // length nodes or other complications in the way then return a sentinel
|
| @@ -2679,21 +2577,18 @@ intptr_t ChoiceNode::GreedyLoopTextLengthForAlternative(
|
| return length;
|
| }
|
|
|
| -
|
| void LoopChoiceNode::AddLoopAlternative(GuardedAlternative alt) {
|
| ASSERT(loop_node_ == NULL);
|
| AddAlternative(alt);
|
| loop_node_ = alt.node();
|
| }
|
|
|
| -
|
| void LoopChoiceNode::AddContinueAlternative(GuardedAlternative alt) {
|
| ASSERT(continue_node_ == NULL);
|
| AddAlternative(alt);
|
| continue_node_ = alt.node();
|
| }
|
|
|
| -
|
| void LoopChoiceNode::Emit(RegExpCompiler* compiler, Trace* trace) {
|
| RegExpMacroAssembler* macro_assembler = compiler->macro_assembler();
|
| if (trace->stop_node() == this) {
|
| @@ -2716,7 +2611,6 @@ void LoopChoiceNode::Emit(RegExpCompiler* compiler, Trace* trace) {
|
| ChoiceNode::Emit(compiler, trace);
|
| }
|
|
|
| -
|
| intptr_t ChoiceNode::CalculatePreloadCharacters(RegExpCompiler* compiler,
|
| intptr_t eats_at_least) {
|
| intptr_t preload_characters =
|
| @@ -2738,7 +2632,6 @@ intptr_t ChoiceNode::CalculatePreloadCharacters(RegExpCompiler* compiler,
|
| return preload_characters;
|
| }
|
|
|
| -
|
| // This structure is used when generating the alternatives in a choice node. It
|
| // records the way the alternative is being code generated.
|
| struct AlternativeGeneration {
|
| @@ -2753,7 +2646,6 @@ struct AlternativeGeneration {
|
| QuickCheckDetails quick_check_details;
|
| };
|
|
|
| -
|
| // Creates a list of AlternativeGenerations. If the list has a reasonable
|
| // size then it is on the stack, otherwise the excess is on the heap.
|
| class AlternativeGenerationList {
|
| @@ -2783,7 +2675,6 @@ class AlternativeGenerationList {
|
| DISALLOW_ALLOCATION();
|
| };
|
|
|
| -
|
| // The '2' variant is inclusive from and exclusive to.
|
| // This covers \s as defined in ECMA-262 5.1, 15.10.2.12,
|
| // which include WhiteSpace (7.2) or LineTerminator (7.3) values.
|
| @@ -2804,12 +2695,10 @@ static const intptr_t kLineTerminatorRanges[] = {0x000A, 0x000B, 0x000D, 0x000E,
|
| static const intptr_t kLineTerminatorRangeCount =
|
| ARRAY_SIZE(kLineTerminatorRanges);
|
|
|
| -
|
| void BoyerMoorePositionInfo::Set(intptr_t character) {
|
| SetInterval(Interval(character, character));
|
| }
|
|
|
| -
|
| void BoyerMoorePositionInfo::SetInterval(const Interval& interval) {
|
| s_ = AddRange(s_, kSpaceRanges, kSpaceRangeCount, interval);
|
| w_ = AddRange(w_, kWordRanges, kWordRangeCount, interval);
|
| @@ -2834,7 +2723,6 @@ void BoyerMoorePositionInfo::SetInterval(const Interval& interval) {
|
| }
|
| }
|
|
|
| -
|
| void BoyerMoorePositionInfo::SetAll() {
|
| s_ = w_ = d_ = kLatticeUnknown;
|
| if (map_count_ != kMapSize) {
|
| @@ -2844,7 +2732,6 @@ void BoyerMoorePositionInfo::SetAll() {
|
| }
|
| }
|
|
|
| -
|
| BoyerMooreLookahead::BoyerMooreLookahead(intptr_t length,
|
| RegExpCompiler* compiler,
|
| Zone* zone)
|
| @@ -2860,7 +2747,6 @@ BoyerMooreLookahead::BoyerMooreLookahead(intptr_t length,
|
| }
|
| }
|
|
|
| -
|
| // Find the longest range of lookahead that has the fewest number of different
|
| // characters that can occur at a given position. Since we are optimizing two
|
| // different parameters at once this is a tradeoff.
|
| @@ -2878,7 +2764,6 @@ bool BoyerMooreLookahead::FindWorthwhileInterval(intptr_t* from, intptr_t* to) {
|
| return true;
|
| }
|
|
|
| -
|
| // Find the highest-points range between 0 and length_ where the character
|
| // information is not too vague. 'Too vague' means that there are more than
|
| // max_number_of_chars that can occur at this position. Calculates the number
|
| @@ -2938,7 +2823,6 @@ intptr_t BoyerMooreLookahead::FindBestInterval(intptr_t max_number_of_chars,
|
| return biggest_points;
|
| }
|
|
|
| -
|
| // Take all the characters that will not prevent a successful match if they
|
| // occur in the subject string in the range between min_lookahead and
|
| // max_lookahead (inclusive) measured from the current position. If the
|
| @@ -2970,7 +2854,6 @@ intptr_t BoyerMooreLookahead::GetSkipTable(
|
| return skip;
|
| }
|
|
|
| -
|
| // See comment above on the implementation of GetSkipTable.
|
| void BoyerMooreLookahead::EmitSkipInstructions(RegExpMacroAssembler* masm) {
|
| const intptr_t kSize = RegExpMacroAssembler::kTableSize;
|
| @@ -3041,7 +2924,6 @@ void BoyerMooreLookahead::EmitSkipInstructions(RegExpMacroAssembler* masm) {
|
| return;
|
| }
|
|
|
| -
|
| /* Code generation for choice nodes.
|
| *
|
| * We generate quick checks that do a mask and compare to eliminate a
|
| @@ -3121,7 +3003,6 @@ GreedyLoopState::GreedyLoopState(bool not_at_start) {
|
| if (not_at_start) counter_backtrack_trace_.set_at_start(false);
|
| }
|
|
|
| -
|
| void ChoiceNode::AssertGuardsMentionRegisters(Trace* trace) {
|
| #ifdef DEBUG
|
| intptr_t choice_count = alternatives_->length();
|
| @@ -3136,7 +3017,6 @@ void ChoiceNode::AssertGuardsMentionRegisters(Trace* trace) {
|
| #endif
|
| }
|
|
|
| -
|
| void ChoiceNode::SetUpPreLoad(RegExpCompiler* compiler,
|
| Trace* current_trace,
|
| PreloadState* state) {
|
| @@ -3154,7 +3034,6 @@ void ChoiceNode::SetUpPreLoad(RegExpCompiler* compiler,
|
| state->preload_has_checked_bounds_ = state->preload_is_current_;
|
| }
|
|
|
| -
|
| void ChoiceNode::Emit(RegExpCompiler* compiler, Trace* trace) {
|
| intptr_t choice_count = alternatives_->length();
|
|
|
| @@ -3260,7 +3139,6 @@ Trace* ChoiceNode::EmitGreedyLoop(RegExpCompiler* compiler,
|
| return new_trace;
|
| }
|
|
|
| -
|
| intptr_t ChoiceNode::EmitOptimizedUnanchoredSearch(RegExpCompiler* compiler,
|
| Trace* trace) {
|
| intptr_t eats_at_least = PreloadState::kEatsAtLeastNotYetInitialized;
|
| @@ -3308,7 +3186,6 @@ intptr_t ChoiceNode::EmitOptimizedUnanchoredSearch(RegExpCompiler* compiler,
|
| return eats_at_least;
|
| }
|
|
|
| -
|
| void ChoiceNode::EmitChoices(RegExpCompiler* compiler,
|
| AlternativeGenerationList* alt_gens,
|
| intptr_t first_choice,
|
| @@ -3393,7 +3270,6 @@ void ChoiceNode::EmitChoices(RegExpCompiler* compiler,
|
| }
|
| }
|
|
|
| -
|
| void ChoiceNode::EmitOutOfLineContinuation(RegExpCompiler* compiler,
|
| Trace* trace,
|
| GuardedAlternative alternative,
|
| @@ -3433,7 +3309,6 @@ void ChoiceNode::EmitOutOfLineContinuation(RegExpCompiler* compiler,
|
| }
|
| }
|
|
|
| -
|
| void ActionNode::Emit(RegExpCompiler* compiler, Trace* trace) {
|
| RegExpMacroAssembler* assembler = compiler->macro_assembler();
|
| LimitResult limit_result = LimitVersions(compiler, trace);
|
| @@ -3554,7 +3429,6 @@ void ActionNode::Emit(RegExpCompiler* compiler, Trace* trace) {
|
| }
|
| }
|
|
|
| -
|
| void BackReferenceNode::Emit(RegExpCompiler* compiler, Trace* trace) {
|
| RegExpMacroAssembler* assembler = compiler->macro_assembler();
|
| if (!trace->is_trivial()) {
|
| @@ -3577,14 +3451,11 @@ void BackReferenceNode::Emit(RegExpCompiler* compiler, Trace* trace) {
|
| on_success()->Emit(compiler, trace);
|
| }
|
|
|
| -
|
| // -------------------------------------------------------------------
|
| // Dot/dotty output
|
|
|
| -
|
| #ifdef DEBUG
|
|
|
| -
|
| class DotPrinter : public NodeVisitor {
|
| public:
|
| explicit DotPrinter(bool ignore_case) {}
|
| @@ -3597,7 +3468,6 @@ class DotPrinter : public NodeVisitor {
|
| #undef DECLARE_VISIT
|
| };
|
|
|
| -
|
| void DotPrinter::PrintNode(const char* label, RegExpNode* node) {
|
| OS::Print("digraph G {\n graph [label=\"");
|
| for (intptr_t i = 0; label[i]; i++) {
|
| @@ -3618,20 +3488,17 @@ void DotPrinter::PrintNode(const char* label, RegExpNode* node) {
|
| OS::Print("}\n");
|
| }
|
|
|
| -
|
| void DotPrinter::Visit(RegExpNode* node) {
|
| if (node->info()->visited) return;
|
| node->info()->visited = true;
|
| node->Accept(this);
|
| }
|
|
|
| -
|
| void DotPrinter::PrintOnFailure(RegExpNode* from, RegExpNode* on_failure) {
|
| OS::Print(" n%p -> n%p [style=dotted];\n", from, on_failure);
|
| Visit(on_failure);
|
| }
|
|
|
| -
|
| class AttributePrinter : public ValueObject {
|
| public:
|
| AttributePrinter() : first_(true) {}
|
| @@ -3657,7 +3524,6 @@ class AttributePrinter : public ValueObject {
|
| bool first_;
|
| };
|
|
|
| -
|
| void DotPrinter::PrintAttributes(RegExpNode* that) {
|
| OS::Print(
|
| " a%p [shape=Mrecord, color=grey, fontcolor=grey, "
|
| @@ -3676,7 +3542,6 @@ void DotPrinter::PrintAttributes(RegExpNode* that) {
|
| that, that);
|
| }
|
|
|
| -
|
| void DotPrinter::VisitChoice(ChoiceNode* that) {
|
| OS::Print(" n%p [shape=Mrecord, label=\"?\"];\n", that);
|
| for (intptr_t i = 0; i < that->alternatives()->length(); i++) {
|
| @@ -3689,7 +3554,6 @@ void DotPrinter::VisitChoice(ChoiceNode* that) {
|
| }
|
| }
|
|
|
| -
|
| void DotPrinter::VisitText(TextNode* that) {
|
| OS::Print(" n%p [label=\"", that);
|
| for (intptr_t i = 0; i < that->elements()->length(); i++) {
|
| @@ -3726,7 +3590,6 @@ void DotPrinter::VisitText(TextNode* that) {
|
| Visit(that->on_success());
|
| }
|
|
|
| -
|
| void DotPrinter::VisitBackReference(BackReferenceNode* that) {
|
| OS::Print(" n%p [label=\"$%" Pd "..$%" Pd "\", shape=doubleoctagon];\n",
|
| that, that->start_register(), that->end_register());
|
| @@ -3735,13 +3598,11 @@ void DotPrinter::VisitBackReference(BackReferenceNode* that) {
|
| Visit(that->on_success());
|
| }
|
|
|
| -
|
| void DotPrinter::VisitEnd(EndNode* that) {
|
| OS::Print(" n%p [style=bold, shape=point];\n", that);
|
| PrintAttributes(that);
|
| }
|
|
|
| -
|
| void DotPrinter::VisitAssertion(AssertionNode* that) {
|
| OS::Print(" n%p [", that);
|
| switch (that->assertion_type()) {
|
| @@ -3768,7 +3629,6 @@ void DotPrinter::VisitAssertion(AssertionNode* that) {
|
| Visit(successor);
|
| }
|
|
|
| -
|
| void DotPrinter::VisitAction(ActionNode* that) {
|
| OS::Print(" n%p [", that);
|
| switch (that->action_type_) {
|
| @@ -3812,7 +3672,6 @@ void DotPrinter::VisitAction(ActionNode* that) {
|
| Visit(successor);
|
| }
|
|
|
| -
|
| void RegExpEngine::DotPrint(const char* label,
|
| RegExpNode* node,
|
| bool ignore_case) {
|
| @@ -3820,10 +3679,8 @@ void RegExpEngine::DotPrint(const char* label,
|
| printer.PrintNode(label, node);
|
| }
|
|
|
| -
|
| #endif // DEBUG
|
|
|
| -
|
| // -------------------------------------------------------------------
|
| // Tree to graph conversion
|
|
|
| @@ -3838,7 +3695,6 @@ RegExpNode* RegExpAtom::ToNode(RegExpCompiler* compiler,
|
| return new (OZ) TextNode(elms, on_success);
|
| }
|
|
|
| -
|
| RegExpNode* RegExpText::ToNode(RegExpCompiler* compiler,
|
| RegExpNode* on_success) {
|
| ZoneGrowableArray<TextElement>* elms =
|
| @@ -3849,7 +3705,6 @@ RegExpNode* RegExpText::ToNode(RegExpCompiler* compiler,
|
| return new (OZ) TextNode(elms, on_success);
|
| }
|
|
|
| -
|
| static bool CompareInverseRanges(ZoneGrowableArray<CharacterRange>* ranges,
|
| const intptr_t* special_class,
|
| intptr_t length) {
|
| @@ -3880,7 +3735,6 @@ static bool CompareInverseRanges(ZoneGrowableArray<CharacterRange>* ranges,
|
| return true;
|
| }
|
|
|
| -
|
| static bool CompareRanges(ZoneGrowableArray<CharacterRange>* ranges,
|
| const intptr_t* special_class,
|
| intptr_t length) {
|
| @@ -3899,7 +3753,6 @@ static bool CompareRanges(ZoneGrowableArray<CharacterRange>* ranges,
|
| return true;
|
| }
|
|
|
| -
|
| bool RegExpCharacterClass::is_standard() {
|
| // TODO(lrn): Remove need for this function, by not throwing away information
|
| // along the way.
|
| @@ -3938,13 +3791,11 @@ bool RegExpCharacterClass::is_standard() {
|
| return false;
|
| }
|
|
|
| -
|
| RegExpNode* RegExpCharacterClass::ToNode(RegExpCompiler* compiler,
|
| RegExpNode* on_success) {
|
| return new (OZ) TextNode(this, on_success);
|
| }
|
|
|
| -
|
| RegExpNode* RegExpDisjunction::ToNode(RegExpCompiler* compiler,
|
| RegExpNode* on_success) {
|
| ZoneGrowableArray<RegExpTree*>* alternatives = this->alternatives();
|
| @@ -3958,13 +3809,11 @@ RegExpNode* RegExpDisjunction::ToNode(RegExpCompiler* compiler,
|
| return result;
|
| }
|
|
|
| -
|
| RegExpNode* RegExpQuantifier::ToNode(RegExpCompiler* compiler,
|
| RegExpNode* on_success) {
|
| return ToNode(min(), max(), is_greedy(), body(), compiler, on_success);
|
| }
|
|
|
| -
|
| // Scoped object to keep track of how much we unroll quantifier loops in the
|
| // regexp graph generator.
|
| class RegExpExpansionLimiter : public ValueObject {
|
| @@ -4002,7 +3851,6 @@ class RegExpExpansionLimiter : public ValueObject {
|
| DISALLOW_IMPLICIT_CONSTRUCTORS(RegExpExpansionLimiter);
|
| };
|
|
|
| -
|
| RegExpNode* RegExpQuantifier::ToNode(intptr_t min,
|
| intptr_t max,
|
| bool is_greedy,
|
| @@ -4139,7 +3987,6 @@ RegExpNode* RegExpQuantifier::ToNode(intptr_t min,
|
| }
|
| }
|
|
|
| -
|
| RegExpNode* RegExpAssertion::ToNode(RegExpCompiler* compiler,
|
| RegExpNode* on_success) {
|
| switch (assertion_type()) {
|
| @@ -4188,7 +4035,6 @@ RegExpNode* RegExpAssertion::ToNode(RegExpCompiler* compiler,
|
| return on_success;
|
| }
|
|
|
| -
|
| RegExpNode* RegExpBackReference::ToNode(RegExpCompiler* compiler,
|
| RegExpNode* on_success) {
|
| return new (OZ)
|
| @@ -4196,13 +4042,11 @@ RegExpNode* RegExpBackReference::ToNode(RegExpCompiler* compiler,
|
| RegExpCapture::EndRegister(index()), on_success);
|
| }
|
|
|
| -
|
| RegExpNode* RegExpEmpty::ToNode(RegExpCompiler* compiler,
|
| RegExpNode* on_success) {
|
| return on_success;
|
| }
|
|
|
| -
|
| RegExpNode* RegExpLookahead::ToNode(RegExpCompiler* compiler,
|
| RegExpNode* on_success) {
|
| intptr_t stack_pointer_register = compiler->AllocateRegister();
|
| @@ -4246,13 +4090,11 @@ RegExpNode* RegExpLookahead::ToNode(RegExpCompiler* compiler,
|
| }
|
| }
|
|
|
| -
|
| RegExpNode* RegExpCapture::ToNode(RegExpCompiler* compiler,
|
| RegExpNode* on_success) {
|
| return ToNode(body(), index(), compiler, on_success);
|
| }
|
|
|
| -
|
| RegExpNode* RegExpCapture::ToNode(RegExpTree* body,
|
| intptr_t index,
|
| RegExpCompiler* compiler,
|
| @@ -4264,7 +4106,6 @@ RegExpNode* RegExpCapture::ToNode(RegExpTree* body,
|
| return ActionNode::StorePosition(start_reg, true, body_node);
|
| }
|
|
|
| -
|
| RegExpNode* RegExpAlternative::ToNode(RegExpCompiler* compiler,
|
| RegExpNode* on_success) {
|
| ZoneGrowableArray<RegExpTree*>* children = nodes();
|
| @@ -4275,7 +4116,6 @@ RegExpNode* RegExpAlternative::ToNode(RegExpCompiler* compiler,
|
| return current;
|
| }
|
|
|
| -
|
| static void AddClass(const intptr_t* elmv,
|
| intptr_t elmc,
|
| ZoneGrowableArray<CharacterRange>* ranges) {
|
| @@ -4287,7 +4127,6 @@ static void AddClass(const intptr_t* elmv,
|
| }
|
| }
|
|
|
| -
|
| static void AddClassNegated(const intptr_t* elmv,
|
| intptr_t elmc,
|
| ZoneGrowableArray<CharacterRange>* ranges) {
|
| @@ -4305,7 +4144,6 @@ static void AddClassNegated(const intptr_t* elmv,
|
| ranges->Add(CharacterRange(last, Utf16::kMaxCodeUnit));
|
| }
|
|
|
| -
|
| void CharacterRange::AddClassEscape(uint16_t type,
|
| ZoneGrowableArray<CharacterRange>* ranges) {
|
| switch (type) {
|
| @@ -4346,7 +4184,6 @@ void CharacterRange::AddClassEscape(uint16_t type,
|
| }
|
| }
|
|
|
| -
|
| void CharacterRange::AddCaseEquivalents(
|
| ZoneGrowableArray<CharacterRange>* ranges,
|
| bool is_one_byte,
|
| @@ -4418,7 +4255,6 @@ void CharacterRange::AddCaseEquivalents(
|
| }
|
| }
|
|
|
| -
|
| bool CharacterRange::IsCanonical(ZoneGrowableArray<CharacterRange>* ranges) {
|
| ASSERT(ranges != NULL);
|
| intptr_t n = ranges->length();
|
| @@ -4432,7 +4268,6 @@ bool CharacterRange::IsCanonical(ZoneGrowableArray<CharacterRange>* ranges) {
|
| return true;
|
| }
|
|
|
| -
|
| ZoneGrowableArray<CharacterRange>* CharacterSet::ranges() {
|
| if (ranges_ == NULL) {
|
| ranges_ = new ZoneGrowableArray<CharacterRange>(2);
|
| @@ -4441,7 +4276,6 @@ ZoneGrowableArray<CharacterRange>* CharacterSet::ranges() {
|
| return ranges_;
|
| }
|
|
|
| -
|
| // Move a number of elements in a zone array to another position
|
| // in the same array. Handles overlapping source and target areas.
|
| static void MoveRanges(ZoneGrowableArray<CharacterRange>* list,
|
| @@ -4460,7 +4294,6 @@ static void MoveRanges(ZoneGrowableArray<CharacterRange>* list,
|
| }
|
| }
|
|
|
| -
|
| static intptr_t InsertRangeInCanonicalList(
|
| ZoneGrowableArray<CharacterRange>* list,
|
| intptr_t count,
|
| @@ -4519,7 +4352,6 @@ static intptr_t InsertRangeInCanonicalList(
|
| return count - (end_pos - start_pos) + 1;
|
| }
|
|
|
| -
|
| void CharacterSet::Canonicalize() {
|
| // Special/default classes are always considered canonical. The result
|
| // of calling ranges() will be sorted.
|
| @@ -4527,7 +4359,6 @@ void CharacterSet::Canonicalize() {
|
| CharacterRange::Canonicalize(ranges_);
|
| }
|
|
|
| -
|
| void CharacterRange::Canonicalize(
|
| ZoneGrowableArray<CharacterRange>* character_ranges) {
|
| if (character_ranges->length() <= 1) return;
|
| @@ -4564,7 +4395,6 @@ void CharacterRange::Canonicalize(
|
| ASSERT(CharacterRange::IsCanonical(character_ranges));
|
| }
|
|
|
| -
|
| void CharacterRange::Negate(ZoneGrowableArray<CharacterRange>* ranges,
|
| ZoneGrowableArray<CharacterRange>* negated_ranges) {
|
| ASSERT(CharacterRange::IsCanonical(ranges));
|
| @@ -4587,11 +4417,9 @@ void CharacterRange::Negate(ZoneGrowableArray<CharacterRange>* ranges,
|
| }
|
| }
|
|
|
| -
|
| // -------------------------------------------------------------------
|
| // Splay tree
|
|
|
| -
|
| // Workaround for the fact that ZoneGrowableArray does not have contains().
|
| static bool ArrayContains(ZoneGrowableArray<unsigned>* array, unsigned value) {
|
| for (intptr_t i = 0; i < array->length(); i++) {
|
| @@ -4602,7 +4430,6 @@ static bool ArrayContains(ZoneGrowableArray<unsigned>* array, unsigned value) {
|
| return false;
|
| }
|
|
|
| -
|
| void OutSet::Set(unsigned value, Zone* zone) {
|
| if (value < kFirstLimit) {
|
| first_ |= (1 << value);
|
| @@ -4617,7 +4444,6 @@ void OutSet::Set(unsigned value, Zone* zone) {
|
| }
|
| }
|
|
|
| -
|
| bool OutSet::Get(unsigned value) const {
|
| if (value < kFirstLimit) {
|
| return (first_ & (1 << value)) != 0;
|
| @@ -4628,11 +4454,9 @@ bool OutSet::Get(unsigned value) const {
|
| }
|
| }
|
|
|
| -
|
| // -------------------------------------------------------------------
|
| // Analysis
|
|
|
| -
|
| void Analysis::EnsureAnalyzed(RegExpNode* that) {
|
| if (that->info()->been_analyzed || that->info()->being_analyzed) return;
|
| that->info()->being_analyzed = true;
|
| @@ -4641,12 +4465,10 @@ void Analysis::EnsureAnalyzed(RegExpNode* that) {
|
| that->info()->been_analyzed = true;
|
| }
|
|
|
| -
|
| void Analysis::VisitEnd(EndNode* that) {
|
| // nothing to do
|
| }
|
|
|
| -
|
| void TextNode::CalculateOffsets() {
|
| intptr_t element_count = elements()->length();
|
| // Set up the offsets of the elements relative to the start. This is a fixed
|
| @@ -4659,7 +4481,6 @@ void TextNode::CalculateOffsets() {
|
| }
|
| }
|
|
|
| -
|
| void Analysis::VisitText(TextNode* that) {
|
| if (ignore_case_) {
|
| that->MakeCaseIndependent(is_one_byte_);
|
| @@ -4670,7 +4491,6 @@ void Analysis::VisitText(TextNode* that) {
|
| }
|
| }
|
|
|
| -
|
| void Analysis::VisitAction(ActionNode* that) {
|
| RegExpNode* target = that->on_success();
|
| EnsureAnalyzed(target);
|
| @@ -4681,7 +4501,6 @@ void Analysis::VisitAction(ActionNode* that) {
|
| }
|
| }
|
|
|
| -
|
| void Analysis::VisitChoice(ChoiceNode* that) {
|
| NodeInfo* info = that->info();
|
| for (intptr_t i = 0; i < that->alternatives()->length(); i++) {
|
| @@ -4694,7 +4513,6 @@ void Analysis::VisitChoice(ChoiceNode* that) {
|
| }
|
| }
|
|
|
| -
|
| void Analysis::VisitLoopChoice(LoopChoiceNode* that) {
|
| NodeInfo* info = that->info();
|
| for (intptr_t i = 0; i < that->alternatives()->length(); i++) {
|
| @@ -4713,17 +4531,14 @@ void Analysis::VisitLoopChoice(LoopChoiceNode* that) {
|
| }
|
| }
|
|
|
| -
|
| void Analysis::VisitBackReference(BackReferenceNode* that) {
|
| EnsureAnalyzed(that->on_success());
|
| }
|
|
|
| -
|
| void Analysis::VisitAssertion(AssertionNode* that) {
|
| EnsureAnalyzed(that->on_success());
|
| }
|
|
|
| -
|
| void BackReferenceNode::FillInBMInfo(intptr_t offset,
|
| intptr_t budget,
|
| BoyerMooreLookahead* bm,
|
| @@ -4734,11 +4549,9 @@ void BackReferenceNode::FillInBMInfo(intptr_t offset,
|
| SaveBMInfo(bm, not_at_start, offset);
|
| }
|
|
|
| -
|
| COMPILE_ASSERT(BoyerMoorePositionInfo::kMapSize ==
|
| RegExpMacroAssembler::kTableSize);
|
|
|
| -
|
| void ChoiceNode::FillInBMInfo(intptr_t offset,
|
| intptr_t budget,
|
| BoyerMooreLookahead* bm,
|
| @@ -4757,7 +4570,6 @@ void ChoiceNode::FillInBMInfo(intptr_t offset,
|
| SaveBMInfo(bm, not_at_start, offset);
|
| }
|
|
|
| -
|
| void TextNode::FillInBMInfo(intptr_t initial_offset,
|
| intptr_t budget,
|
| BoyerMooreLookahead* bm,
|
| @@ -4818,7 +4630,6 @@ void TextNode::FillInBMInfo(intptr_t initial_offset,
|
| if (initial_offset == 0) set_bm_info(not_at_start, bm);
|
| }
|
|
|
| -
|
| #if !defined(DART_PRECOMPILED_RUNTIME)
|
| RegExpEngine::CompilationResult RegExpEngine::CompileIR(
|
| RegExpCompileData* data,
|
| @@ -4930,7 +4741,6 @@ RegExpEngine::CompilationResult RegExpEngine::CompileIR(
|
| }
|
| #endif // !defined(DART_PRECOMPILED_RUNTIME)
|
|
|
| -
|
| RegExpEngine::CompilationResult RegExpEngine::CompileBytecode(
|
| RegExpCompileData* data,
|
| const RegExp& regexp,
|
| @@ -5033,7 +4843,6 @@ RegExpEngine::CompilationResult RegExpEngine::CompileBytecode(
|
| return result;
|
| }
|
|
|
| -
|
| static void CreateSpecializedFunction(Thread* thread,
|
| Zone* zone,
|
| const RegExp& regexp,
|
| @@ -5081,7 +4890,6 @@ static void CreateSpecializedFunction(Thread* thread,
|
| // The function is compiled lazily during the first call.
|
| }
|
|
|
| -
|
| RawRegExp* RegExpEngine::CreateRegExp(Thread* thread,
|
| const String& pattern,
|
| bool multi_line,
|
| @@ -5120,5 +4928,4 @@ RawRegExp* RegExpEngine::CreateRegExp(Thread* thread,
|
| return regexp.raw();
|
| }
|
|
|
| -
|
| } // namespace dart
|
|
|