2014-11-03 10:00:31 +00:00
|
|
|
// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
|
|
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
|
2016-10-26 07:26:03 +00:00
|
|
|
#ifndef RUNTIME_VM_REGEXP_ASSEMBLER_H_
|
|
|
|
#define RUNTIME_VM_REGEXP_ASSEMBLER_H_
|
2014-11-03 10:00:31 +00:00
|
|
|
|
2020-04-16 22:59:03 +00:00
|
|
|
#include "vm/object.h"
|
|
|
|
|
|
|
|
#if !defined(DART_PRECOMPILED_RUNTIME)
|
2017-09-04 14:18:37 +00:00
|
|
|
#include "vm/compiler/assembler/assembler.h"
|
|
|
|
#include "vm/compiler/backend/il.h"
|
2020-04-16 22:59:03 +00:00
|
|
|
#endif // !defined(DART_PRECOMPILED_RUNTIME)
|
2014-11-03 10:00:31 +00:00
|
|
|
|
|
|
|
namespace dart {
|
|
|
|
|
2014-11-26 09:32:43 +00:00
|
|
|
// Utility function for the DotPrinter
|
|
|
|
void PrintUtf16(uint16_t c);
|
2020-04-25 05:21:27 +00:00
|
|
|
|
|
|
|
extern "C" {
|
2019-04-29 09:11:48 +00:00
|
|
|
// Compares two-byte strings case insensitively as UCS2.
|
|
|
|
// Called from generated RegExp code.
|
2020-04-25 05:21:27 +00:00
|
|
|
uword /*BoolPtr*/ CaseInsensitiveCompareUCS2(uword /*StringPtr*/ str_raw,
|
|
|
|
uword /*SmiPtr*/ lhs_index_raw,
|
|
|
|
uword /*SmiPtr*/ rhs_index_raw,
|
|
|
|
uword /*SmiPtr*/ length_raw);
|
2019-04-29 09:11:48 +00:00
|
|
|
|
|
|
|
// Compares two-byte strings case insensitively as UTF16.
|
|
|
|
// Called from generated RegExp code.
|
2020-04-25 05:21:27 +00:00
|
|
|
uword /*BoolPtr*/ CaseInsensitiveCompareUTF16(uword /*StringPtr*/ str_raw,
|
|
|
|
uword /*SmiPtr*/ lhs_index_raw,
|
|
|
|
uword /*SmiPtr*/ rhs_index_raw,
|
|
|
|
uword /*SmiPtr*/ length_raw);
|
|
|
|
}
|
2014-11-03 10:00:31 +00:00
|
|
|
|
2014-11-26 09:32:43 +00:00
|
|
|
/// Convenience wrapper around a BlockEntryInstr pointer.
|
|
|
|
class BlockLabel : public ValueObject {
|
2015-07-07 21:43:32 +00:00
|
|
|
// Used by the IR assembler.
|
2014-11-26 09:32:43 +00:00
|
|
|
public:
|
2016-02-26 14:59:36 +00:00
|
|
|
BlockLabel();
|
2016-11-08 21:54:47 +00:00
|
|
|
~BlockLabel() { ASSERT(!is_linked()); }
|
2015-07-07 21:43:32 +00:00
|
|
|
|
2016-11-08 21:54:47 +00:00
|
|
|
intptr_t pos() const { return pos_; }
|
2020-04-16 22:59:03 +00:00
|
|
|
bool is_bound() const { return is_bound_; }
|
|
|
|
bool is_linked() const { return !is_bound_ && is_linked_; }
|
|
|
|
#if !defined(DART_PRECOMPILED_RUNTIME)
|
|
|
|
JoinEntryInstr* block() const { return block_; }
|
|
|
|
#endif // !defined(DART_PRECOMPILED_RUNTIME)
|
2015-07-07 21:43:32 +00:00
|
|
|
|
|
|
|
void Unuse() {
|
2020-04-16 22:59:03 +00:00
|
|
|
pos_ = -1;
|
2015-07-07 21:43:32 +00:00
|
|
|
is_bound_ = false;
|
|
|
|
is_linked_ = false;
|
|
|
|
}
|
|
|
|
|
2020-04-16 22:59:03 +00:00
|
|
|
void BindTo(intptr_t pos) {
|
2015-07-07 21:43:32 +00:00
|
|
|
pos_ = pos;
|
2020-04-16 22:59:03 +00:00
|
|
|
#if !defined(DART_PRECOMPILED_RUNTIME)
|
|
|
|
if (block_ != nullptr) block_->set_block_id(pos);
|
|
|
|
#endif // !defined(DART_PRECOMPILED_RUNTIME)
|
2015-07-07 21:43:32 +00:00
|
|
|
is_bound_ = true;
|
|
|
|
is_linked_ = false;
|
|
|
|
ASSERT(is_bound());
|
|
|
|
}
|
|
|
|
|
2020-04-16 22:59:03 +00:00
|
|
|
// Used by bytecode assembler to form a linked list out of
|
|
|
|
// forward jumps to an unbound label.
|
|
|
|
void LinkTo(intptr_t pos) {
|
|
|
|
#if !defined(DART_PRECOMPILED_RUNTIME)
|
|
|
|
ASSERT(block_ == nullptr);
|
|
|
|
#endif
|
|
|
|
ASSERT(!is_bound_);
|
2015-07-07 21:43:32 +00:00
|
|
|
pos_ = pos;
|
|
|
|
is_linked_ = true;
|
2020-04-16 22:59:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Used by IR builder to mark block label as used.
|
|
|
|
void SetLinked() {
|
|
|
|
#if !defined(DART_PRECOMPILED_RUNTIME)
|
|
|
|
ASSERT(block_ != nullptr);
|
|
|
|
#endif
|
|
|
|
if (!is_bound_) {
|
|
|
|
is_linked_ = true;
|
|
|
|
}
|
2015-07-07 21:43:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2020-04-16 22:59:03 +00:00
|
|
|
bool is_bound_ = false;
|
|
|
|
bool is_linked_ = false;
|
|
|
|
intptr_t pos_ = -1;
|
|
|
|
#if !defined(DART_PRECOMPILED_RUNTIME)
|
|
|
|
JoinEntryInstr* block_ = nullptr;
|
|
|
|
#endif // !defined(DART_PRECOMPILED_RUNTIME)
|
2014-11-26 09:32:43 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class RegExpMacroAssembler : public ZoneAllocated {
|
2014-11-03 10:00:31 +00:00
|
|
|
public:
|
|
|
|
// The implementation must be able to handle at least:
|
2014-11-26 09:32:43 +00:00
|
|
|
static const intptr_t kMaxRegister = (1 << 16) - 1;
|
|
|
|
static const intptr_t kMaxCPOffset = (1 << 15) - 1;
|
|
|
|
static const intptr_t kMinCPOffset = -(1 << 15);
|
2014-11-03 10:00:31 +00:00
|
|
|
|
2014-11-26 09:32:43 +00:00
|
|
|
static const intptr_t kTableSizeBits = 7;
|
|
|
|
static const intptr_t kTableSize = 1 << kTableSizeBits;
|
|
|
|
static const intptr_t kTableMask = kTableSize - 1;
|
2014-11-03 10:00:31 +00:00
|
|
|
|
2014-11-26 09:32:43 +00:00
|
|
|
enum {
|
2015-09-04 08:06:02 +00:00
|
|
|
kParamRegExpIndex = 0,
|
|
|
|
kParamStringIndex,
|
2014-11-26 09:32:43 +00:00
|
|
|
kParamStartOffsetIndex,
|
|
|
|
kParamCount
|
2014-11-03 10:00:31 +00:00
|
|
|
};
|
|
|
|
|
2016-11-08 21:54:47 +00:00
|
|
|
enum IrregexpImplementation { kBytecodeImplementation, kIRImplementation };
|
2014-11-03 10:00:31 +00:00
|
|
|
|
2015-03-17 19:24:26 +00:00
|
|
|
explicit RegExpMacroAssembler(Zone* zone);
|
2014-11-03 10:00:31 +00:00
|
|
|
virtual ~RegExpMacroAssembler();
|
|
|
|
// The maximal number of pushes between stack checks. Users must supply
|
|
|
|
// kCheckStackLimit flag to push operations (instead of kNoStackLimitCheck)
|
|
|
|
// at least once for every stack_limit() pushes that are executed.
|
2014-11-26 09:32:43 +00:00
|
|
|
virtual intptr_t stack_limit_slack() = 0;
|
2014-11-03 10:00:31 +00:00
|
|
|
virtual bool CanReadUnaligned() = 0;
|
2014-11-26 09:32:43 +00:00
|
|
|
virtual void AdvanceCurrentPosition(intptr_t by) = 0; // Signed cp change.
|
|
|
|
virtual void AdvanceRegister(intptr_t reg, intptr_t by) = 0; // r[reg] += by.
|
2014-11-03 10:00:31 +00:00
|
|
|
// Continues execution from the position pushed on the top of the backtrack
|
2014-11-26 09:32:43 +00:00
|
|
|
// stack by an earlier PushBacktrack(BlockLabel*).
|
2014-11-03 10:00:31 +00:00
|
|
|
virtual void Backtrack() = 0;
|
2014-11-26 09:32:43 +00:00
|
|
|
virtual void BindBlock(BlockLabel* label) = 0;
|
|
|
|
virtual void CheckAtStart(BlockLabel* on_at_start) = 0;
|
2014-11-03 10:00:31 +00:00
|
|
|
// Dispatch after looking the current character up in a 2-bits-per-entry
|
|
|
|
// map. The destinations vector has up to 4 labels.
|
2014-11-26 09:32:43 +00:00
|
|
|
virtual void CheckCharacter(unsigned c, BlockLabel* on_equal) = 0;
|
2014-11-03 10:00:31 +00:00
|
|
|
// Bitwise and the current character with the given constant and then
|
|
|
|
// check for a match with c.
|
|
|
|
virtual void CheckCharacterAfterAnd(unsigned c,
|
|
|
|
unsigned and_with,
|
2014-11-26 09:32:43 +00:00
|
|
|
BlockLabel* on_equal) = 0;
|
|
|
|
virtual void CheckCharacterGT(uint16_t limit, BlockLabel* on_greater) = 0;
|
|
|
|
virtual void CheckCharacterLT(uint16_t limit, BlockLabel* on_less) = 0;
|
|
|
|
virtual void CheckGreedyLoop(BlockLabel* on_tos_equals_current_position) = 0;
|
[VM] Adding regexp lookbehind assertion support.
See https://github.com/tc39/proposal-regexp-lookbehind
for a high-level description of the feature and examples. This is one of the
features requested in https://github.com/dart-lang/sdk/issues/34935.
This work takes the feature as present in the v8 engine and appropriately
merges it into our irregexp fork. Notable changes to the irregexp codebase to
introduce this feature:
-----
We can no longer assume that all matching proceeds forwards, since lookbehind
matching proceeds backwards. Similarly, we cannot assume that we can only be
at the start of a string if we started matching from that point. The direction
of matching must also be taken into consideration when doing bounds checking,
which previously assumed the engine would never attempt to look before the
start of a string.
-----
We may now parse backreferences to captures before the capture they
reference, since we parse regular expressions left to right, but lookbehinds
perform captures as they evaluate the string from right to left. Since
RegExpBackReference objects contain a pointer to their corresponding capture,
this means that we may need to create RegExpCapture objects prior to the
parsing of the corresponding captured subexpression.
Thus, RegExpCapture objects are now only initialized with their index, and the
body is set later when the subexpression is encountered and parsed. This means
any method that operates on the body of a RegExpCapture can no longer be const,
which also affects the rest of the RegExpTree class hierarchy. This also means
that we don't have a valid max_match length for backreferences based off the
capture body, and must assume they can end up being any length.
-----
Change-Id: Iffe0e71b17b1a0c6fea77235e8aee5c093005811
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/94540
Commit-Queue: Stevie Strickland <sstrickl@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
2019-03-14 14:26:47 +00:00
|
|
|
virtual void CheckNotAtStart(intptr_t cp_offset,
|
|
|
|
BlockLabel* on_not_at_start) = 0;
|
2016-11-08 21:54:47 +00:00
|
|
|
virtual void CheckNotBackReference(intptr_t start_reg,
|
[VM] Adding regexp lookbehind assertion support.
See https://github.com/tc39/proposal-regexp-lookbehind
for a high-level description of the feature and examples. This is one of the
features requested in https://github.com/dart-lang/sdk/issues/34935.
This work takes the feature as present in the v8 engine and appropriately
merges it into our irregexp fork. Notable changes to the irregexp codebase to
introduce this feature:
-----
We can no longer assume that all matching proceeds forwards, since lookbehind
matching proceeds backwards. Similarly, we cannot assume that we can only be
at the start of a string if we started matching from that point. The direction
of matching must also be taken into consideration when doing bounds checking,
which previously assumed the engine would never attempt to look before the
start of a string.
-----
We may now parse backreferences to captures before the capture they
reference, since we parse regular expressions left to right, but lookbehinds
perform captures as they evaluate the string from right to left. Since
RegExpBackReference objects contain a pointer to their corresponding capture,
this means that we may need to create RegExpCapture objects prior to the
parsing of the corresponding captured subexpression.
Thus, RegExpCapture objects are now only initialized with their index, and the
body is set later when the subexpression is encountered and parsed. This means
any method that operates on the body of a RegExpCapture can no longer be const,
which also affects the rest of the RegExpTree class hierarchy. This also means
that we don't have a valid max_match length for backreferences based off the
capture body, and must assume they can end up being any length.
-----
Change-Id: Iffe0e71b17b1a0c6fea77235e8aee5c093005811
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/94540
Commit-Queue: Stevie Strickland <sstrickl@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
2019-03-14 14:26:47 +00:00
|
|
|
bool read_backward,
|
2016-11-08 21:54:47 +00:00
|
|
|
BlockLabel* on_no_match) = 0;
|
2014-11-26 09:32:43 +00:00
|
|
|
virtual void CheckNotBackReferenceIgnoreCase(intptr_t start_reg,
|
[VM] Adding regexp lookbehind assertion support.
See https://github.com/tc39/proposal-regexp-lookbehind
for a high-level description of the feature and examples. This is one of the
features requested in https://github.com/dart-lang/sdk/issues/34935.
This work takes the feature as present in the v8 engine and appropriately
merges it into our irregexp fork. Notable changes to the irregexp codebase to
introduce this feature:
-----
We can no longer assume that all matching proceeds forwards, since lookbehind
matching proceeds backwards. Similarly, we cannot assume that we can only be
at the start of a string if we started matching from that point. The direction
of matching must also be taken into consideration when doing bounds checking,
which previously assumed the engine would never attempt to look before the
start of a string.
-----
We may now parse backreferences to captures before the capture they
reference, since we parse regular expressions left to right, but lookbehinds
perform captures as they evaluate the string from right to left. Since
RegExpBackReference objects contain a pointer to their corresponding capture,
this means that we may need to create RegExpCapture objects prior to the
parsing of the corresponding captured subexpression.
Thus, RegExpCapture objects are now only initialized with their index, and the
body is set later when the subexpression is encountered and parsed. This means
any method that operates on the body of a RegExpCapture can no longer be const,
which also affects the rest of the RegExpTree class hierarchy. This also means
that we don't have a valid max_match length for backreferences based off the
capture body, and must assume they can end up being any length.
-----
Change-Id: Iffe0e71b17b1a0c6fea77235e8aee5c093005811
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/94540
Commit-Queue: Stevie Strickland <sstrickl@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
2019-03-14 14:26:47 +00:00
|
|
|
bool read_backward,
|
2019-04-29 09:11:48 +00:00
|
|
|
bool unicode,
|
2014-11-26 09:32:43 +00:00
|
|
|
BlockLabel* on_no_match) = 0;
|
2014-11-03 10:00:31 +00:00
|
|
|
// Check the current character for a match with a literal character. If we
|
|
|
|
// fail to match then goto the on_failure label. End of input always
|
|
|
|
// matches. If the label is NULL then we should pop a backtrack address off
|
|
|
|
// the stack and go to that.
|
2014-11-26 09:32:43 +00:00
|
|
|
virtual void CheckNotCharacter(unsigned c, BlockLabel* on_not_equal) = 0;
|
2014-11-03 10:00:31 +00:00
|
|
|
virtual void CheckNotCharacterAfterAnd(unsigned c,
|
|
|
|
unsigned and_with,
|
2014-11-26 09:32:43 +00:00
|
|
|
BlockLabel* on_not_equal) = 0;
|
2014-11-03 10:00:31 +00:00
|
|
|
// Subtract a constant from the current character, then and with the given
|
|
|
|
// constant and then check for a match with c.
|
2014-11-26 09:32:43 +00:00
|
|
|
virtual void CheckNotCharacterAfterMinusAnd(uint16_t c,
|
|
|
|
uint16_t minus,
|
|
|
|
uint16_t and_with,
|
|
|
|
BlockLabel* on_not_equal) = 0;
|
|
|
|
virtual void CheckCharacterInRange(uint16_t from,
|
|
|
|
uint16_t to, // Both inclusive.
|
|
|
|
BlockLabel* on_in_range) = 0;
|
|
|
|
virtual void CheckCharacterNotInRange(uint16_t from,
|
|
|
|
uint16_t to, // Both inclusive.
|
|
|
|
BlockLabel* on_not_in_range) = 0;
|
2014-11-03 10:00:31 +00:00
|
|
|
|
|
|
|
// The current character (modulus the kTableSize) is looked up in the byte
|
|
|
|
// array, and if the found byte is non-zero, we jump to the on_bit_set label.
|
2014-11-26 09:32:43 +00:00
|
|
|
virtual void CheckBitInTable(const TypedData& table,
|
|
|
|
BlockLabel* on_bit_set) = 0;
|
2014-11-03 10:00:31 +00:00
|
|
|
|
2017-06-23 10:51:52 +00:00
|
|
|
// Checks for preemption and serves as an OSR entry.
|
|
|
|
virtual void CheckPreemption(bool is_backtrack) {}
|
|
|
|
|
2014-11-03 10:00:31 +00:00
|
|
|
// Checks whether the given offset from the current position is before
|
|
|
|
// the end of the string. May overwrite the current character.
|
2014-11-26 09:32:43 +00:00
|
|
|
virtual void CheckPosition(intptr_t cp_offset, BlockLabel* on_outside_input) {
|
2014-11-03 10:00:31 +00:00
|
|
|
LoadCurrentCharacter(cp_offset, on_outside_input, true);
|
|
|
|
}
|
|
|
|
// Check whether a standard/default character class matches the current
|
|
|
|
// character. Returns false if the type of special character class does
|
|
|
|
// not have custom support.
|
|
|
|
// May clobber the current loaded character.
|
2014-11-26 09:32:43 +00:00
|
|
|
virtual bool CheckSpecialCharacterClass(uint16_t type,
|
|
|
|
BlockLabel* on_no_match) {
|
2014-11-03 10:00:31 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
virtual void Fail() = 0;
|
|
|
|
// Check whether a register is >= a given constant and go to a label if it
|
|
|
|
// is. Backtracks instead if the label is NULL.
|
2016-11-08 21:54:47 +00:00
|
|
|
virtual void IfRegisterGE(intptr_t reg,
|
|
|
|
intptr_t comparand,
|
|
|
|
BlockLabel* if_ge) = 0;
|
2014-11-03 10:00:31 +00:00
|
|
|
// Check whether a register is < a given constant and go to a label if it is.
|
|
|
|
// Backtracks instead if the label is NULL.
|
2016-11-08 21:54:47 +00:00
|
|
|
virtual void IfRegisterLT(intptr_t reg,
|
|
|
|
intptr_t comparand,
|
|
|
|
BlockLabel* if_lt) = 0;
|
2014-11-03 10:00:31 +00:00
|
|
|
// Check whether a register is == to the current position and go to a
|
|
|
|
// label if it is.
|
2014-11-26 09:32:43 +00:00
|
|
|
virtual void IfRegisterEqPos(intptr_t reg, BlockLabel* if_eq) = 0;
|
2014-11-03 10:00:31 +00:00
|
|
|
virtual IrregexpImplementation Implementation() = 0;
|
2014-11-26 09:32:43 +00:00
|
|
|
// The assembler is closed, iff there is no current instruction assigned.
|
|
|
|
virtual bool IsClosed() const = 0;
|
|
|
|
// Jump to the target label without setting it as the current instruction.
|
|
|
|
virtual void GoTo(BlockLabel* to) = 0;
|
|
|
|
virtual void LoadCurrentCharacter(intptr_t cp_offset,
|
|
|
|
BlockLabel* on_end_of_input,
|
2014-11-03 10:00:31 +00:00
|
|
|
bool check_bounds = true,
|
2014-11-26 09:32:43 +00:00
|
|
|
intptr_t characters = 1) = 0;
|
2014-11-03 10:00:31 +00:00
|
|
|
virtual void PopCurrentPosition() = 0;
|
2014-11-26 09:32:43 +00:00
|
|
|
virtual void PopRegister(intptr_t register_index) = 0;
|
|
|
|
// Prints string within the generated code. Used for debugging.
|
|
|
|
virtual void Print(const char* str) = 0;
|
|
|
|
// Prints all emitted blocks.
|
|
|
|
virtual void PrintBlocks() = 0;
|
2014-11-03 10:00:31 +00:00
|
|
|
// Pushes the label on the backtrack stack, so that a following Backtrack
|
|
|
|
// will go to this label. Always checks the backtrack stack limit.
|
2014-11-26 09:32:43 +00:00
|
|
|
virtual void PushBacktrack(BlockLabel* label) = 0;
|
2014-11-03 10:00:31 +00:00
|
|
|
virtual void PushCurrentPosition() = 0;
|
2014-11-26 09:32:43 +00:00
|
|
|
virtual void PushRegister(intptr_t register_index) = 0;
|
|
|
|
virtual void ReadCurrentPositionFromRegister(intptr_t reg) = 0;
|
|
|
|
virtual void ReadStackPointerFromRegister(intptr_t reg) = 0;
|
|
|
|
virtual void SetCurrentPositionFromEnd(intptr_t by) = 0;
|
|
|
|
virtual void SetRegister(intptr_t register_index, intptr_t to) = 0;
|
2014-11-03 10:00:31 +00:00
|
|
|
// Return whether the matching (with a global regexp) will be restarted.
|
|
|
|
virtual bool Succeed() = 0;
|
2016-11-08 21:54:47 +00:00
|
|
|
virtual void WriteCurrentPositionToRegister(intptr_t reg,
|
|
|
|
intptr_t cp_offset) = 0;
|
2014-11-26 09:32:43 +00:00
|
|
|
virtual void ClearRegisters(intptr_t reg_from, intptr_t reg_to) = 0;
|
|
|
|
virtual void WriteStackPointerToRegister(intptr_t reg) = 0;
|
2014-11-03 10:00:31 +00:00
|
|
|
|
2019-04-29 09:11:48 +00:00
|
|
|
// Check that we are not in the middle of a surrogate pair.
|
|
|
|
void CheckNotInSurrogatePair(intptr_t cp_offset, BlockLabel* on_failure);
|
|
|
|
|
2014-11-03 10:00:31 +00:00
|
|
|
// Controls the generation of large inlined constants in the code.
|
|
|
|
void set_slow_safe(bool ssc) { slow_safe_compiler_ = ssc; }
|
|
|
|
bool slow_safe() { return slow_safe_compiler_; }
|
|
|
|
|
2019-04-29 09:11:48 +00:00
|
|
|
enum GlobalMode {
|
|
|
|
NOT_GLOBAL,
|
|
|
|
GLOBAL,
|
|
|
|
GLOBAL_NO_ZERO_LENGTH_CHECK,
|
|
|
|
GLOBAL_UNICODE
|
|
|
|
};
|
2014-11-03 10:00:31 +00:00
|
|
|
// Set whether the regular expression has the global flag. Exiting due to
|
|
|
|
// a failure in a global regexp may still mean success overall.
|
|
|
|
inline void set_global_mode(GlobalMode mode) { global_mode_ = mode; }
|
|
|
|
inline bool global() { return global_mode_ != NOT_GLOBAL; }
|
2019-04-29 09:11:48 +00:00
|
|
|
inline bool global_with_zero_length_check() {
|
|
|
|
return global_mode_ == GLOBAL || global_mode_ == GLOBAL_UNICODE;
|
|
|
|
}
|
|
|
|
inline bool global_unicode() { return global_mode_ == GLOBAL_UNICODE; }
|
2014-11-03 10:00:31 +00:00
|
|
|
|
2015-03-17 19:24:26 +00:00
|
|
|
Zone* zone() const { return zone_; }
|
2014-11-03 10:00:31 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
bool slow_safe_compiler_;
|
2019-04-29 09:11:48 +00:00
|
|
|
GlobalMode global_mode_;
|
2015-03-17 19:24:26 +00:00
|
|
|
Zone* zone_;
|
2014-11-26 09:32:43 +00:00
|
|
|
};
|
|
|
|
|
2014-11-03 10:00:31 +00:00
|
|
|
} // namespace dart
|
|
|
|
|
2016-10-26 07:26:03 +00:00
|
|
|
#endif // RUNTIME_VM_REGEXP_ASSEMBLER_H_
|