Commit 12ecb4f5 authored by Jakob Gruber's avatar Jakob Gruber Committed by V8 LUCI CQ

[regexp] Various refactors

No functional changes.

- Removed unused Isolate* argument from regexp extrefs.
- Added const where possible.
- Removed unused functions.
- Shuffled declarations for better readability.
- ...

Change-Id: I6d9093052e8de4e33e9411541a691d0bab7b20c9
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3217193
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Auto-Submit: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: 's avatarPatrick Thier <pthier@chromium.org>
Cr-Commit-Position: refs/heads/main@{#77316}
parent 3e9ba672
......@@ -296,12 +296,6 @@ struct IsValidExternalReferenceType<Result (Class::*)(Args...)> {
return ExternalReference(Redirect(FUNCTION_ADDR(Target))); \
}
#define FUNCTION_REFERENCE_WITH_ISOLATE(Name, Target) \
ExternalReference ExternalReference::Name(Isolate* isolate) { \
STATIC_ASSERT(IsValidExternalReferenceType<decltype(&Target)>::value); \
return ExternalReference(Redirect(FUNCTION_ADDR(Target))); \
}
#define FUNCTION_REFERENCE_WITH_TYPE(Name, Target, Type) \
ExternalReference ExternalReference::Name() { \
STATIC_ASSERT(IsValidExternalReferenceType<decltype(&Target)>::value); \
......@@ -719,11 +713,10 @@ ExternalReference ExternalReference::invoke_accessor_getter_callback() {
UNREACHABLE();
#endif
FUNCTION_REFERENCE_WITH_ISOLATE(re_check_stack_guard_state, re_stack_check_func)
FUNCTION_REFERENCE(re_check_stack_guard_state, re_stack_check_func)
#undef re_stack_check_func
FUNCTION_REFERENCE_WITH_ISOLATE(re_grow_stack,
NativeRegExpMacroAssembler::GrowStack)
FUNCTION_REFERENCE(re_grow_stack, NativeRegExpMacroAssembler::GrowStack)
FUNCTION_REFERENCE(re_match_for_call_from_js,
IrregexpInterpreter::MatchForCallFromJs)
......@@ -731,15 +724,13 @@ FUNCTION_REFERENCE(re_match_for_call_from_js,
FUNCTION_REFERENCE(re_experimental_match_for_call_from_js,
ExperimentalRegExp::MatchForCallFromJs)
FUNCTION_REFERENCE_WITH_ISOLATE(
re_case_insensitive_compare_unicode,
NativeRegExpMacroAssembler::CaseInsensitiveCompareUnicode)
FUNCTION_REFERENCE(re_case_insensitive_compare_unicode,
NativeRegExpMacroAssembler::CaseInsensitiveCompareUnicode)
FUNCTION_REFERENCE_WITH_ISOLATE(
re_case_insensitive_compare_non_unicode,
NativeRegExpMacroAssembler::CaseInsensitiveCompareNonUnicode)
FUNCTION_REFERENCE(re_case_insensitive_compare_non_unicode,
NativeRegExpMacroAssembler::CaseInsensitiveCompareNonUnicode)
ExternalReference ExternalReference::re_word_character_map(Isolate* isolate) {
ExternalReference ExternalReference::re_word_character_map() {
return ExternalReference(
NativeRegExpMacroAssembler::word_character_map_address());
}
......@@ -1380,7 +1371,6 @@ void abort_with_reason(int reason) {
}
#undef FUNCTION_REFERENCE
#undef FUNCTION_REFERENCE_WITH_ISOLATE
#undef FUNCTION_REFERENCE_WITH_TYPE
} // namespace internal
......
......@@ -77,14 +77,6 @@ class StatsCounter;
V(address_of_static_offsets_vector, "OffsetsVector::static_offsets_vector") \
V(thread_in_wasm_flag_address_address, \
"Isolate::thread_in_wasm_flag_address_address") \
V(re_case_insensitive_compare_unicode, \
"NativeRegExpMacroAssembler::CaseInsensitiveCompareUnicode()") \
V(re_case_insensitive_compare_non_unicode, \
"NativeRegExpMacroAssembler::CaseInsensitiveCompareNonUnicode()") \
V(re_check_stack_guard_state, \
"RegExpMacroAssembler*::CheckStackGuardState()") \
V(re_grow_stack, "NativeRegExpMacroAssembler::GrowStack()") \
V(re_word_character_map, "NativeRegExpMacroAssembler::word_character_map") \
V(javascript_execution_assert, "javascript_execution_assert") \
EXTERNAL_REFERENCE_LIST_WITH_ISOLATE_HEAP_SANDBOX(V)
......@@ -292,6 +284,14 @@ class StatsCounter;
"tsan_relaxed_load_function_64_bits") \
V(js_finalization_registry_remove_cell_from_unregister_token_map, \
"JSFinalizationRegistry::RemoveCellFromUnregisterTokenMap") \
V(re_case_insensitive_compare_unicode, \
"RegExpMacroAssembler::CaseInsensitiveCompareUnicode()") \
V(re_case_insensitive_compare_non_unicode, \
"RegExpMacroAssembler::CaseInsensitiveCompareNonUnicode()") \
V(re_check_stack_guard_state, \
"RegExpMacroAssembler*::CheckStackGuardState()") \
V(re_grow_stack, "NativeRegExpMacroAssembler::GrowStack()") \
V(re_word_character_map, "NativeRegExpMacroAssembler::word_character_map") \
V(re_match_for_call_from_js, "IrregexpInterpreter::MatchForCallFromJs") \
V(re_experimental_match_for_call_from_js, \
"ExperimentalRegExp::MatchForCallFromJs") \
......
......@@ -336,10 +336,9 @@ void RegExpMacroAssemblerARM::CheckNotBackReferenceIgnoreCase(
{
AllowExternalCallThatCantCauseGC scope(masm_.get());
ExternalReference function =
unicode ? ExternalReference::re_case_insensitive_compare_unicode(
isolate())
: ExternalReference::re_case_insensitive_compare_non_unicode(
isolate());
unicode
? ExternalReference::re_case_insensitive_compare_unicode()
: ExternalReference::re_case_insensitive_compare_non_unicode();
__ CallCFunction(function, argument_count);
}
......@@ -577,7 +576,7 @@ bool RegExpMacroAssemblerARM::CheckSpecialCharacterClass(base::uc16 type,
__ cmp(current_character(), Operand('z'));
BranchOrBacktrack(hi, on_no_match);
}
ExternalReference map = ExternalReference::re_word_character_map(isolate());
ExternalReference map = ExternalReference::re_word_character_map();
__ mov(r0, Operand(map));
__ ldrb(r0, MemOperand(r0, current_character()));
__ cmp(r0, Operand::Zero());
......@@ -591,7 +590,7 @@ bool RegExpMacroAssemblerARM::CheckSpecialCharacterClass(base::uc16 type,
__ cmp(current_character(), Operand('z'));
__ b(hi, &done);
}
ExternalReference map = ExternalReference::re_word_character_map(isolate());
ExternalReference map = ExternalReference::re_word_character_map();
__ mov(r0, Operand(map));
__ ldrb(r0, MemOperand(r0, current_character()));
__ cmp(r0, Operand::Zero());
......@@ -931,8 +930,7 @@ Handle<HeapObject> RegExpMacroAssemblerARM::GetCode(Handle<String> source) {
static constexpr int kNumArguments = 1;
__ PrepareCallCFunction(kNumArguments);
__ mov(r0, Operand(ExternalReference::isolate_address(isolate())));
ExternalReference grow_stack =
ExternalReference::re_grow_stack(isolate());
ExternalReference grow_stack = ExternalReference::re_grow_stack();
__ CallCFunction(grow_stack, kNumArguments);
// If nullptr is returned, we have failed to grow the stack, and must exit
// with a stack-overflow exception.
......@@ -1127,7 +1125,7 @@ void RegExpMacroAssemblerARM::CallCheckStackGuardState() {
__ mov(r0, sp);
ExternalReference stack_guard_check =
ExternalReference::re_check_stack_guard_state(isolate());
ExternalReference::re_check_stack_guard_state();
__ mov(ip, Operand(stack_guard_check));
EmbeddedData d = EmbeddedData::FromBlob();
......
......@@ -425,10 +425,9 @@ void RegExpMacroAssemblerARM64::CheckNotBackReferenceIgnoreCase(
{
AllowExternalCallThatCantCauseGC scope(masm_.get());
ExternalReference function =
unicode ? ExternalReference::re_case_insensitive_compare_unicode(
isolate())
: ExternalReference::re_case_insensitive_compare_non_unicode(
isolate());
unicode
? ExternalReference::re_case_insensitive_compare_unicode()
: ExternalReference::re_case_insensitive_compare_non_unicode();
__ CallCFunction(function, argument_count);
}
......@@ -663,7 +662,7 @@ bool RegExpMacroAssemblerARM64::CheckSpecialCharacterClass(base::uc16 type,
// Table is 256 entries, so all Latin1 characters can be tested.
CompareAndBranchOrBacktrack(current_character(), 'z', hi, on_no_match);
}
ExternalReference map = ExternalReference::re_word_character_map(isolate());
ExternalReference map = ExternalReference::re_word_character_map();
__ Mov(x10, map);
__ Ldrb(w10, MemOperand(x10, current_character(), UXTW));
CompareAndBranchOrBacktrack(w10, 0, eq, on_no_match);
......@@ -676,7 +675,7 @@ bool RegExpMacroAssemblerARM64::CheckSpecialCharacterClass(base::uc16 type,
__ Cmp(current_character(), 'z');
__ B(hi, &done);
}
ExternalReference map = ExternalReference::re_word_character_map(isolate());
ExternalReference map = ExternalReference::re_word_character_map();
__ Mov(x10, map);
__ Ldrb(w10, MemOperand(x10, current_character(), UXTW));
CompareAndBranchOrBacktrack(w10, 0, ne, on_no_match);
......@@ -1121,8 +1120,7 @@ Handle<HeapObject> RegExpMacroAssemblerARM64::GetCode(Handle<String> source) {
// Call GrowStack(isolate)
static constexpr int kNumArguments = 1;
__ Mov(x0, ExternalReference::isolate_address(isolate()));
__ CallCFunction(ExternalReference::re_grow_stack(isolate()),
kNumArguments);
__ CallCFunction(ExternalReference::re_grow_stack(), kNumArguments);
// If return nullptr, we have failed to grow the stack, and must exit with
// a stack-overflow exception. Returning from the regexp code restores the
// stack (sp <- fp) so we don't need to drop the link register from it
......@@ -1447,7 +1445,7 @@ void RegExpMacroAssemblerARM64::CallCheckStackGuardState(Register scratch) {
DCHECK_EQ(scratch, x10);
ExternalReference check_stack_guard_state =
ExternalReference::re_check_stack_guard_state(isolate());
ExternalReference::re_check_stack_guard_state();
__ Mov(scratch, check_stack_guard_state);
__ CallBuiltin(Builtin::kDirectCEntry);
......
......@@ -336,10 +336,9 @@ void RegExpMacroAssemblerIA32::CheckNotBackReferenceIgnoreCase(
{
AllowExternalCallThatCantCauseGC scope(masm_.get());
ExternalReference compare =
unicode ? ExternalReference::re_case_insensitive_compare_unicode(
isolate())
: ExternalReference::re_case_insensitive_compare_non_unicode(
isolate());
unicode
? ExternalReference::re_case_insensitive_compare_unicode()
: ExternalReference::re_case_insensitive_compare_non_unicode();
__ CallCFunction(compare, argument_count);
}
// Pop original values before reacting on result value.
......@@ -581,8 +580,7 @@ bool RegExpMacroAssemblerIA32::CheckSpecialCharacterClass(base::uc16 type,
BranchOrBacktrack(above, on_no_match);
}
DCHECK_EQ(0, word_character_map[0]); // Character '\0' is not a word char.
ExternalReference word_map =
ExternalReference::re_word_character_map(isolate());
ExternalReference word_map = ExternalReference::re_word_character_map();
__ test_b(current_character(),
Operand(current_character(), times_1, word_map.address(),
RelocInfo::EXTERNAL_REFERENCE));
......@@ -597,8 +595,7 @@ bool RegExpMacroAssemblerIA32::CheckSpecialCharacterClass(base::uc16 type,
__ j(above, &done);
}
DCHECK_EQ(0, word_character_map[0]); // Character '\0' is not a word char.
ExternalReference word_map =
ExternalReference::re_word_character_map(isolate());
ExternalReference word_map = ExternalReference::re_word_character_map();
__ test_b(current_character(),
Operand(current_character(), times_1, word_map.address(),
RelocInfo::EXTERNAL_REFERENCE));
......@@ -969,8 +966,7 @@ Handle<HeapObject> RegExpMacroAssemblerIA32::GetCode(Handle<String> source) {
__ PrepareCallCFunction(kNumArguments, ebx);
__ mov(Operand(esp, 0 * kSystemPointerSize),
Immediate(ExternalReference::isolate_address(isolate())));
__ CallCFunction(ExternalReference::re_grow_stack(isolate()),
kNumArguments);
__ CallCFunction(ExternalReference::re_grow_stack(), kNumArguments);
// If return nullptr, we have failed to grow the stack, and
// must exit with a stack-overflow exception.
__ or_(eax, eax);
......@@ -1151,7 +1147,7 @@ void RegExpMacroAssemblerIA32::CallCheckStackGuardState(Register scratch) {
__ lea(eax, Operand(esp, -kSystemPointerSize));
__ mov(Operand(esp, 0 * kSystemPointerSize), eax);
ExternalReference check_stack_guard =
ExternalReference::re_check_stack_guard_state(isolate());
ExternalReference::re_check_stack_guard_state();
__ CallCFunction(check_stack_guard, num_arguments);
}
......
......@@ -45,29 +45,25 @@ class RegExpVisitor {
#undef MAKE_CASE
};
// A simple closed interval.
class Interval {
public:
Interval() : from_(kNone), to_(kNone - 1) {} // '- 1' for branchless size().
Interval(int from, int to) : from_(from), to_(to) {}
Interval Union(Interval that) {
if (that.from_ == kNone)
return *this;
else if (from_ == kNone)
return that;
else
return Interval(std::min(from_, that.from_), std::max(to_, that.to_));
if (that.from_ == kNone) return *this;
if (from_ == kNone) return that;
return Interval(std::min(from_, that.from_), std::max(to_, that.to_));
}
bool Contains(int value) { return (from_ <= value) && (value <= to_); }
bool is_empty() { return from_ == kNone; }
static Interval Empty() { return Interval(); }
bool Contains(int value) const { return (from_ <= value) && (value <= to_); }
bool is_empty() const { return from_ == kNone; }
int from() const { return from_; }
int to() const { return to_; }
int size() const { return to_ - from_ + 1; }
static Interval Empty() { return Interval(); }
static constexpr int kNone = -1;
private:
......@@ -79,21 +75,13 @@ class Interval {
// to to_, both ends are inclusive.
class CharacterRange {
public:
CharacterRange() : from_(0), to_(0) {}
// For compatibility with the CHECK_OK macro
CharacterRange() = default;
// For compatibility with the CHECK_OK macro.
CharacterRange(void* null) { DCHECK_NULL(null); } // NOLINT
V8_EXPORT_PRIVATE static void AddClassEscape(char type,
ZoneList<CharacterRange>* ranges,
Zone* zone);
// Add class escapes. Add case equivalent closure for \w and \W if necessary.
V8_EXPORT_PRIVATE static void AddClassEscape(
char type, ZoneList<CharacterRange>* ranges,
bool add_unicode_case_equivalents, Zone* zone);
static base::Vector<const int> GetWordBounds();
static inline CharacterRange Singleton(base::uc32 value) {
return CharacterRange(value, value);
}
static constexpr int kMaxCodePoint = 0x10ffff;
static inline CharacterRange Range(base::uc32 from, base::uc32 to) {
DCHECK(0 <= from && to <= kMaxCodePoint);
DCHECK(static_cast<uint32_t>(from) <= static_cast<uint32_t>(to));
......@@ -102,6 +90,7 @@ class CharacterRange {
static inline CharacterRange Everything() {
return CharacterRange(0, kMaxCodePoint);
}
static inline ZoneList<CharacterRange>* List(Zone* zone,
CharacterRange range) {
ZoneList<CharacterRange>* list =
......@@ -109,17 +98,23 @@ class CharacterRange {
list->Add(range, zone);
return list;
}
bool Contains(base::uc32 i) { return from_ <= i && i <= to_; }
base::uc32 from() const { return from_; }
void set_from(base::uc32 value) { from_ = value; }
base::uc32 to() const { return to_; }
void set_to(base::uc32 value) { to_ = value; }
bool is_valid() { return from_ <= to_; }
bool IsEverything(base::uc32 max) { return from_ == 0 && to_ >= max; }
bool IsSingleton() { return (from_ == to_); }
V8_EXPORT_PRIVATE static void AddClassEscape(char type,
ZoneList<CharacterRange>* ranges,
Zone* zone);
// Add class escapes. Add case equivalent closure for \w and \W if necessary.
V8_EXPORT_PRIVATE static void AddClassEscape(
char type, ZoneList<CharacterRange>* ranges,
bool add_unicode_case_equivalents, Zone* zone);
V8_EXPORT_PRIVATE static void AddCaseEquivalents(
Isolate* isolate, Zone* zone, ZoneList<CharacterRange>* ranges,
bool is_one_byte);
bool Contains(base::uc32 i) const { return from_ <= i && i <= to_; }
base::uc32 from() const { return from_; }
base::uc32 to() const { return to_; }
bool IsEverything(base::uc32 max) const { return from_ == 0 && to_ >= max; }
bool IsSingleton() const { return from_ == to_; }
// Whether a range list is in canonical form: Ranges ordered by from value,
// and ranges non-overlapping and non-adjacent.
V8_EXPORT_PRIVATE static bool IsCanonical(ZoneList<CharacterRange>* ranges);
......@@ -131,71 +126,22 @@ class CharacterRange {
// Negate the contents of a character range in canonical form.
static void Negate(ZoneList<CharacterRange>* src,
ZoneList<CharacterRange>* dst, Zone* zone);
static const int kStartMarker = (1 << 24);
static const int kPayloadMask = (1 << 24) - 1;
private:
CharacterRange(base::uc32 from, base::uc32 to) : from_(from), to_(to) {}
base::uc32 from_;
base::uc32 to_;
};
class CharacterSet final {
public:
explicit CharacterSet(base::uc16 standard_set_type)
: ranges_(nullptr), standard_set_type_(standard_set_type) {}
explicit CharacterSet(ZoneList<CharacterRange>* ranges)
: ranges_(ranges), standard_set_type_(0) {}
ZoneList<CharacterRange>* ranges(Zone* zone);
base::uc16 standard_set_type() const { return standard_set_type_; }
void set_standard_set_type(base::uc16 special_set_type) {
standard_set_type_ = special_set_type;
}
bool is_standard() { return standard_set_type_ != 0; }
V8_EXPORT_PRIVATE void Canonicalize();
private:
ZoneList<CharacterRange>* ranges_;
// If non-zero, the value represents a standard set (e.g., all whitespace
// characters) without having to expand the ranges.
base::uc16 standard_set_type_;
};
class TextElement final {
public:
enum TextType { ATOM, CHAR_CLASS };
static TextElement Atom(RegExpAtom* atom);
static TextElement CharClass(RegExpCharacterClass* char_class);
int cp_offset() const { return cp_offset_; }
void set_cp_offset(int cp_offset) { cp_offset_ = cp_offset; }
int length() const;
TextType text_type() const { return text_type_; }
RegExpTree* tree() const { return tree_; }
RegExpAtom* atom() const {
DCHECK(text_type() == ATOM);
return reinterpret_cast<RegExpAtom*>(tree());
}
RegExpCharacterClass* char_class() const {
DCHECK(text_type() == CHAR_CLASS);
return reinterpret_cast<RegExpCharacterClass*>(tree());
}
private:
TextElement(TextType text_type, RegExpTree* tree)
: cp_offset_(-1), text_type_(text_type), tree_(tree) {}
static constexpr int kMaxCodePoint = 0x10ffff;
int cp_offset_;
TextType text_type_;
RegExpTree* tree_;
base::uc32 from_ = 0;
base::uc32 to_ = 0;
};
#define DECL_BOILERPLATE(Name) \
void* Accept(RegExpVisitor* visitor, void* data) override; \
RegExpNode* ToNode(RegExpCompiler* compiler, RegExpNode* on_success) \
override; \
RegExp##Name* As##Name() override; \
bool Is##Name() override
class RegExpTree : public ZoneObject {
public:
......@@ -225,16 +171,15 @@ class RegExpTree : public ZoneObject {
class RegExpDisjunction final : public RegExpTree {
public:
explicit RegExpDisjunction(ZoneList<RegExpTree*>* alternatives);
void* Accept(RegExpVisitor* visitor, void* data) override;
RegExpNode* ToNode(RegExpCompiler* compiler, RegExpNode* on_success) override;
RegExpDisjunction* AsDisjunction() override;
DECL_BOILERPLATE(Disjunction);
Interval CaptureRegisters() override;
bool IsDisjunction() override;
bool IsAnchoredAtStart() override;
bool IsAnchoredAtEnd() override;
int min_match() override { return min_match_; }
int max_match() override { return max_match_; }
ZoneList<RegExpTree*>* alternatives() { return alternatives_; }
ZoneList<RegExpTree*>* alternatives() const { return alternatives_; }
private:
bool SortConsecutiveAtoms(RegExpCompiler* compiler);
......@@ -249,16 +194,15 @@ class RegExpDisjunction final : public RegExpTree {
class RegExpAlternative final : public RegExpTree {
public:
explicit RegExpAlternative(ZoneList<RegExpTree*>* nodes);
void* Accept(RegExpVisitor* visitor, void* data) override;
RegExpNode* ToNode(RegExpCompiler* compiler, RegExpNode* on_success) override;
RegExpAlternative* AsAlternative() override;
DECL_BOILERPLATE(Alternative);
Interval CaptureRegisters() override;
bool IsAlternative() override;
bool IsAnchoredAtStart() override;
bool IsAnchoredAtEnd() override;
int min_match() override { return min_match_; }
int max_match() override { return max_match_; }
ZoneList<RegExpTree*>* nodes() { return nodes_; }
ZoneList<RegExpTree*>* nodes() const { return nodes_; }
private:
ZoneList<RegExpTree*>* nodes_;
......@@ -279,10 +223,9 @@ class RegExpAssertion final : public RegExpTree {
LAST_TYPE = NON_BOUNDARY,
};
explicit RegExpAssertion(AssertionType type) : assertion_type_(type) {}
void* Accept(RegExpVisitor* visitor, void* data) override;
RegExpNode* ToNode(RegExpCompiler* compiler, RegExpNode* on_success) override;
RegExpAssertion* AsAssertion() override;
bool IsAssertion() override;
DECL_BOILERPLATE(Assertion);
bool IsAnchoredAtStart() override;
bool IsAnchoredAtEnd() override;
int min_match() override { return 0; }
......@@ -293,6 +236,27 @@ class RegExpAssertion final : public RegExpTree {
const AssertionType assertion_type_;
};
class CharacterSet final {
public:
explicit CharacterSet(base::uc16 standard_set_type)
: standard_set_type_(standard_set_type) {}
explicit CharacterSet(ZoneList<CharacterRange>* ranges) : ranges_(ranges) {}
ZoneList<CharacterRange>* ranges(Zone* zone);
base::uc16 standard_set_type() const { return standard_set_type_; }
void set_standard_set_type(base::uc16 special_set_type) {
standard_set_type_ = special_set_type;
}
bool is_standard() const { return standard_set_type_ != 0; }
V8_EXPORT_PRIVATE void Canonicalize();
private:
ZoneList<CharacterRange>* ranges_ = nullptr;
// If non-zero, the value represents a standard set (e.g., all whitespace
// characters) without having to expand the ranges. See the comment on top of
// `standard_type` below.
base::uc16 standard_set_type_ = 0;
};
class RegExpCharacterClass final : public RegExpTree {
public:
......@@ -318,18 +282,18 @@ class RegExpCharacterClass final : public RegExpTree {
}
explicit RegExpCharacterClass(base::uc16 type)
: set_(type), character_class_flags_(CharacterClassFlags()) {}
void* Accept(RegExpVisitor* visitor, void* data) override;
RegExpNode* ToNode(RegExpCompiler* compiler, RegExpNode* on_success) override;
RegExpCharacterClass* AsCharacterClass() override;
bool IsCharacterClass() override;
DECL_BOILERPLATE(CharacterClass);
bool IsTextElement() override { return true; }
int min_match() override { return 1; }
// The character class may match two code units for unicode regexps.
// TODO(yangguo): we should split this class for usage in TextElement, and
// make max_match() dependent on the character class content.
int max_match() override { return 2; }
void AppendToText(RegExpText* text, Zone* zone) override;
CharacterSet character_set() { return set_; }
// TODO(lrn): Remove need for complex version if is_standard that
// recognizes a mangled standard set and just do { return set_.is_special(); }
bool is_standard(Zone* zone);
......@@ -345,7 +309,10 @@ class RegExpCharacterClass final : public RegExpTree {
// . : non-newline
// * : All characters, for advancing unanchored regexp
base::uc16 standard_type() const { return set_.standard_set_type(); }
CharacterSet character_set() const { return set_; }
ZoneList<CharacterRange>* ranges(Zone* zone) { return set_.ranges(zone); }
bool is_negated() const { return (character_class_flags_ & NEGATED) != 0; }
bool contains_split_surrogate() const {
return (character_class_flags_ & CONTAINS_SPLIT_SURROGATE) != 0;
......@@ -360,29 +327,61 @@ class RegExpCharacterClass final : public RegExpTree {
class RegExpAtom final : public RegExpTree {
public:
explicit RegExpAtom(base::Vector<const base::uc16> data) : data_(data) {}
void* Accept(RegExpVisitor* visitor, void* data) override;
RegExpNode* ToNode(RegExpCompiler* compiler, RegExpNode* on_success) override;
RegExpAtom* AsAtom() override;
bool IsAtom() override;
DECL_BOILERPLATE(Atom);
bool IsTextElement() override { return true; }
int min_match() override { return data_.length(); }
int max_match() override { return data_.length(); }
void AppendToText(RegExpText* text, Zone* zone) override;
base::Vector<const base::uc16> data() { return data_; }
int length() { return data_.length(); }
base::Vector<const base::uc16> data() const { return data_; }
int length() const { return data_.length(); }
private:
base::Vector<const base::uc16> data_;
};
class TextElement final {
public:
enum TextType { ATOM, CHAR_CLASS };
static TextElement Atom(RegExpAtom* atom);
static TextElement CharClass(RegExpCharacterClass* char_class);
int cp_offset() const { return cp_offset_; }
void set_cp_offset(int cp_offset) { cp_offset_ = cp_offset; }
int length() const;
TextType text_type() const { return text_type_; }
RegExpTree* tree() const { return tree_; }
RegExpAtom* atom() const {
DCHECK(text_type() == ATOM);
return reinterpret_cast<RegExpAtom*>(tree());
}
RegExpCharacterClass* char_class() const {
DCHECK(text_type() == CHAR_CLASS);
return reinterpret_cast<RegExpCharacterClass*>(tree());
}
private:
TextElement(TextType text_type, RegExpTree* tree)
: cp_offset_(-1), text_type_(text_type), tree_(tree) {}
int cp_offset_;
TextType text_type_;
RegExpTree* tree_;
};
class RegExpText final : public RegExpTree {
public:
explicit RegExpText(Zone* zone) : elements_(2, zone), length_(0) {}
void* Accept(RegExpVisitor* visitor, void* data) override;
RegExpNode* ToNode(RegExpCompiler* compiler, RegExpNode* on_success) override;
RegExpText* AsText() override;
bool IsText() override;
explicit RegExpText(Zone* zone) : elements_(2, zone) {}
DECL_BOILERPLATE(Text);
bool IsTextElement() override { return true; }
int min_match() override { return length_; }
int max_match() override { return length_; }
......@@ -395,7 +394,7 @@ class RegExpText final : public RegExpTree {
private:
ZoneList<TextElement> elements_;
int length_;
int length_ = 0;
};
......@@ -418,23 +417,22 @@ class RegExpQuantifier final : public RegExpTree {
max_match_ = max * body->max_match();
}
}
void* Accept(RegExpVisitor* visitor, void* data) override;
RegExpNode* ToNode(RegExpCompiler* compiler, RegExpNode* on_success) override;
DECL_BOILERPLATE(Quantifier);
static RegExpNode* ToNode(int min, int max, bool is_greedy, RegExpTree* body,
RegExpCompiler* compiler, RegExpNode* on_success,
bool not_at_start = false);
RegExpQuantifier* AsQuantifier() override;
Interval CaptureRegisters() override;
bool IsQuantifier() override;
int min_match() override { return min_match_; }
int max_match() override { return max_match_; }
int min() const { return min_; }
int max() const { return max_; }
QuantifierType quantifier_type() const { return quantifier_type_; }
bool is_possessive() const { return quantifier_type_ == POSSESSIVE; }
bool is_non_greedy() { return quantifier_type_ == NON_GREEDY; }
bool is_non_greedy() const { return quantifier_type_ == NON_GREEDY; }
bool is_greedy() const { return quantifier_type_ == GREEDY; }
RegExpTree* body() { return body_; }
RegExpTree* body() const { return body_; }
private:
RegExpTree* body_;
......@@ -454,15 +452,14 @@ class RegExpCapture final : public RegExpTree {
min_match_(0),
max_match_(0),
name_(nullptr) {}
void* Accept(RegExpVisitor* visitor, void* data) override;
RegExpNode* ToNode(RegExpCompiler* compiler, RegExpNode* on_success) override;
DECL_BOILERPLATE(Capture);
static RegExpNode* ToNode(RegExpTree* body, int index,
RegExpCompiler* compiler, RegExpNode* on_success);
RegExpCapture* AsCapture() override;
bool IsAnchoredAtStart() override;
bool IsAnchoredAtEnd() override;
Interval CaptureRegisters() override;
bool IsCapture() override;
int min_match() override { return min_match_; }
int max_match() override { return max_match_; }
RegExpTree* body() { return body_; }
......@@ -478,11 +475,11 @@ class RegExpCapture final : public RegExpTree {
static int EndRegister(int index) { return index * 2 + 1; }
private:
RegExpTree* body_;
RegExpTree* body_ = nullptr;
int index_;
int min_match_;
int max_match_;
const ZoneVector<base::uc16>* name_;
int min_match_ = 0;
int max_match_ = 0;
const ZoneVector<base::uc16>* name_ = nullptr;
};
class RegExpGroup final : public RegExpTree {
......@@ -491,19 +488,15 @@ class RegExpGroup final : public RegExpTree {
: body_(body),
min_match_(body->min_match()),
max_match_(body->max_match()) {}
void* Accept(RegExpVisitor* visitor, void* data) override;
RegExpNode* ToNode(RegExpCompiler* compiler,
RegExpNode* on_success) override {
return body_->ToNode(compiler, on_success);
}
RegExpGroup* AsGroup() override;
DECL_BOILERPLATE(Group);
bool IsAnchoredAtStart() override { return body_->IsAnchoredAtStart(); }
bool IsAnchoredAtEnd() override { return body_->IsAnchoredAtEnd(); }
bool IsGroup() override;
int min_match() override { return min_match_; }
int max_match() override { return max_match_; }
Interval CaptureRegisters() override { return body_->CaptureRegisters(); }
RegExpTree* body() { return body_; }
RegExpTree* body() const { return body_; }
private:
RegExpTree* body_;
......@@ -523,26 +516,24 @@ class RegExpLookaround final : public RegExpTree {
capture_from_(capture_from),
type_(type) {}
void* Accept(RegExpVisitor* visitor, void* data) override;
RegExpNode* ToNode(RegExpCompiler* compiler, RegExpNode* on_success) override;
RegExpLookaround* AsLookaround() override;
DECL_BOILERPLATE(Lookaround);
Interval CaptureRegisters() override;
bool IsLookaround() override;
bool IsAnchoredAtStart() override;
int min_match() override { return 0; }
int max_match() override { return 0; }
RegExpTree* body() { return body_; }
bool is_positive() { return is_positive_; }
int capture_count() { return capture_count_; }
int capture_from() { return capture_from_; }
Type type() { return type_; }
RegExpTree* body() const { return body_; }
bool is_positive() const { return is_positive_; }
int capture_count() const { return capture_count_; }
int capture_from() const { return capture_from_; }
Type type() const { return type_; }
class Builder {
public:
Builder(bool is_positive, RegExpNode* on_success,
int stack_pointer_register, int position_register,
int capture_register_count = 0, int capture_register_start = 0);
RegExpNode* on_match_success() { return on_match_success_; }
RegExpNode* on_match_success() const { return on_match_success_; }
RegExpNode* ForMatch(RegExpNode* match);
private:
......@@ -564,38 +555,32 @@ class RegExpLookaround final : public RegExpTree {
class RegExpBackReference final : public RegExpTree {
public:
explicit RegExpBackReference(RegExpFlags flags)
: capture_(nullptr), name_(nullptr), flags_(flags) {}
explicit RegExpBackReference(RegExpFlags flags) : flags_(flags) {}
RegExpBackReference(RegExpCapture* capture, RegExpFlags flags)
: capture_(capture), name_(nullptr), flags_(flags) {}
void* Accept(RegExpVisitor* visitor, void* data) override;
RegExpNode* ToNode(RegExpCompiler* compiler, RegExpNode* on_success) override;
RegExpBackReference* AsBackReference() override;
bool IsBackReference() override;
: capture_(capture), flags_(flags) {}
DECL_BOILERPLATE(BackReference);
int min_match() override { return 0; }
// The back reference may be recursive, e.g. /(\2)(\1)/. To avoid infinite
// recursion, we give up. Ignorance is bliss.
int max_match() override { return kInfinity; }
int index() { return capture_->index(); }
RegExpCapture* capture() { return capture_; }
int index() const { return capture_->index(); }
RegExpCapture* capture() const { return capture_; }
void set_capture(RegExpCapture* capture) { capture_ = capture; }
const ZoneVector<base::uc16>* name() const { return name_; }
void set_name(const ZoneVector<base::uc16>* name) { name_ = name; }
private:
RegExpCapture* capture_;
const ZoneVector<base::uc16>* name_;
RegExpCapture* capture_ = nullptr;
const ZoneVector<base::uc16>* name_ = nullptr;
const RegExpFlags flags_;
};
class RegExpEmpty final : public RegExpTree {
public:
RegExpEmpty() = default;
void* Accept(RegExpVisitor* visitor, void* data) override;
RegExpNode* ToNode(RegExpCompiler* compiler, RegExpNode* on_success) override;
RegExpEmpty* AsEmpty() override;
bool IsEmpty() override;
DECL_BOILERPLATE(Empty);
int min_match() override { return 0; }
int max_match() override { return 0; }
};
......@@ -603,4 +588,6 @@ class RegExpEmpty final : public RegExpTree {
} // namespace internal
} // namespace v8
#undef DECL_BOILERPLATE
#endif // V8_REGEXP_REGEXP_AST_H_
......@@ -27,7 +27,7 @@ class V8_EXPORT_PRIVATE RegExpBytecodeGenerator : public RegExpMacroAssembler {
~RegExpBytecodeGenerator() override;
// The byte-code interpreter checks on each push anyway.
int stack_limit_slack() override { return 1; }
bool CanReadUnaligned() override { return false; }
bool CanReadUnaligned() const override { return false; }
void Bind(Label* label) override;
void AdvanceCurrentPosition(int by) override; // Signed cp change.
void PopCurrentPosition() override;
......
......@@ -845,6 +845,11 @@ RegExpNode* RegExpEmpty::ToNode(RegExpCompiler* compiler,
return on_success;
}
RegExpNode* RegExpGroup::ToNode(RegExpCompiler* compiler,
RegExpNode* on_success) {
return body_->ToNode(compiler, on_success);
}
RegExpLookaround::Builder::Builder(bool is_positive, RegExpNode* on_success,
int stack_pointer_register,
int position_register,
......@@ -1116,10 +1121,6 @@ void CharacterRange::AddClassEscape(char type, ZoneList<CharacterRange>* ranges,
}
}
base::Vector<const int> CharacterRange::GetWordBounds() {
return base::Vector<const int>(kWordRanges, kWordRangeCount - 1);
}
// static
void CharacterRange::AddCaseEquivalents(Isolate* isolate, Zone* zone,
ZoneList<CharacterRange>* ranges,
......
......@@ -18,7 +18,9 @@ class RegExpMacroAssemblerTracer: public RegExpMacroAssembler {
~RegExpMacroAssemblerTracer() override;
void AbortedCodeGeneration() override;
int stack_limit_slack() override { return assembler_->stack_limit_slack(); }
bool CanReadUnaligned() override { return assembler_->CanReadUnaligned(); }
bool CanReadUnaligned() const override {
return assembler_->CanReadUnaligned();
}
void AdvanceCurrentPosition(int by) override; // Signed cp change.
void AdvanceRegister(int reg, int by) override; // r[reg] += by.
void Backtrack() override;
......
......@@ -28,12 +28,11 @@ RegExpMacroAssembler::RegExpMacroAssembler(Isolate* isolate, Zone* zone)
isolate_(isolate),
zone_(zone) {}
RegExpMacroAssembler::~RegExpMacroAssembler() = default;
bool RegExpMacroAssembler::has_backtrack_limit() const {
return backtrack_limit_ != JSRegExp::kNoBacktrackLimit;
}
// static
int RegExpMacroAssembler::CaseInsensitiveCompareNonUnicode(Address byte_offset1,
Address byte_offset2,
size_t byte_length,
......@@ -62,6 +61,7 @@ int RegExpMacroAssembler::CaseInsensitiveCompareNonUnicode(Address byte_offset1,
#endif
}
// static
int RegExpMacroAssembler::CaseInsensitiveCompareUnicode(Address byte_offset1,
Address byte_offset2,
size_t byte_length,
......@@ -135,17 +135,6 @@ void RegExpMacroAssembler::LoadCurrentCharacter(int cp_offset,
eats_at_least);
}
bool RegExpMacroAssembler::CheckSpecialCharacterClass(base::uc16 type,
Label* on_no_match) {
return false;
}
NativeRegExpMacroAssembler::NativeRegExpMacroAssembler(Isolate* isolate,
Zone* zone)
: RegExpMacroAssembler(isolate, zone) {}
NativeRegExpMacroAssembler::~NativeRegExpMacroAssembler() = default;
void NativeRegExpMacroAssembler::LoadCurrentCharacterImpl(
int cp_offset, Label* on_end_of_input, bool check_bounds, int characters,
int eats_at_least) {
......@@ -164,13 +153,14 @@ void NativeRegExpMacroAssembler::LoadCurrentCharacterImpl(
LoadCurrentCharacterUnchecked(cp_offset, characters);
}
bool NativeRegExpMacroAssembler::CanReadUnaligned() {
bool NativeRegExpMacroAssembler::CanReadUnaligned() const {
return FLAG_enable_regexp_unaligned_accesses && !slow_safe();
}
#ifndef COMPILING_IRREGEXP_FOR_EXTERNAL_EMBEDDER
// This method may only be called after an interrupt.
// static
int NativeRegExpMacroAssembler::CheckStackGuardState(
Isolate* isolate, int start_index, RegExp::CallOrigin call_origin,
Address* return_address, Code re_code, Address* subject,
......@@ -298,6 +288,15 @@ int NativeRegExpMacroAssembler::Match(Handle<JSRegExp> regexp,
offsets_vector_length, isolate, *regexp);
}
// static
int NativeRegExpMacroAssembler::ExecuteForTesting(
String input, int start_offset, const byte* input_start,
const byte* input_end, int* output, int output_size, Isolate* isolate,
JSRegExp regexp) {
return Execute(input, start_offset, input_start, input_end, output,
output_size, isolate, regexp);
}
// Returns a {Result} sentinel, or the number of successful matches.
// TODO(pthier): The JSRegExp object is passed to native irregexp code to match
// the signature of the interpreter. We should get rid of JS objects passed to
......@@ -380,6 +379,7 @@ const byte NativeRegExpMacroAssembler::word_character_map[] = {
};
// clang-format on
// static
Address NativeRegExpMacroAssembler::GrowStack(Isolate* isolate) {
DisallowGarbageCollection no_gc;
......
......@@ -13,7 +13,9 @@ namespace v8 {
namespace internal {
class ByteArray;
class JSRegExp;
class Label;
class String;
static const base::uc32 kLeadSurrogateStart = 0xd800;
static const base::uc32 kLeadSurrogateEnd = 0xdbff;
......@@ -22,12 +24,6 @@ static const base::uc32 kTrailSurrogateEnd = 0xdfff;
static const base::uc32 kNonBmpStart = 0x10000;
static const base::uc32 kNonBmpEnd = 0x10ffff;
struct DisjunctDecisionRow {
RegExpCharacterClass cc;
Label* on_match;
};
class RegExpMacroAssembler {
public:
// The implementation must be able to handle at least:
......@@ -42,41 +38,11 @@ class RegExpMacroAssembler {
static constexpr int kUseCharactersValue = -1;
#define IMPLEMENTATIONS_LIST(V) \
V(IA32) \
V(ARM) \
V(ARM64) \
V(MIPS) \
V(LOONG64) \
V(RISCV) \
V(S390) \
V(PPC) \
V(X64) \
V(Bytecode)
enum IrregexpImplementation {
#define V(Name) k##Name##Implementation,
IMPLEMENTATIONS_LIST(V)
#undef V
};
inline const char* ImplementationToString(IrregexpImplementation impl) {
static const char* const kNames[] = {
#define V(Name) #Name,
IMPLEMENTATIONS_LIST(V)
#undef V
};
return kNames[impl];
}
#undef IMPLEMENTATIONS_LIST
RegExpMacroAssembler(Isolate* isolate, Zone* zone);
virtual ~RegExpMacroAssembler() = default;
enum StackCheckFlag {
kNoStackLimitCheck = false,
kCheckStackLimit = true
};
virtual Handle<HeapObject> GetCode(Handle<String> source) = 0;
RegExpMacroAssembler(Isolate* isolate, Zone* zone);
virtual ~RegExpMacroAssembler();
// This function is called when code generation is aborted, so that
// the assembler could clean up internal data structures.
virtual void AbortedCodeGeneration() {}
......@@ -84,7 +50,8 @@ class RegExpMacroAssembler {
// kCheckStackLimit flag to push operations (instead of kNoStackLimitCheck)
// at least once for every stack_limit() pushes that are executed.
virtual int stack_limit_slack() = 0;
virtual bool CanReadUnaligned() = 0;
virtual bool CanReadUnaligned() const = 0;
virtual void AdvanceCurrentPosition(int by) = 0; // Signed cp change.
virtual void AdvanceRegister(int reg, int by) = 0; // r[reg] += by.
// Continues execution from the position pushed on the top of the backtrack
......@@ -140,14 +107,15 @@ class RegExpMacroAssembler {
// character. Returns false if the type of special character class does
// not have custom support.
// May clobber the current loaded character.
virtual bool CheckSpecialCharacterClass(base::uc16 type, Label* on_no_match);
virtual bool CheckSpecialCharacterClass(base::uc16 type, Label* on_no_match) {
return false;
}
// Control-flow integrity:
// Define a jump target and bind a label.
virtual void BindJumpTarget(Label* label) { Bind(label); }
virtual void Fail() = 0;
virtual Handle<HeapObject> GetCode(Handle<String> source) = 0;
virtual void GoTo(Label* label) = 0;
// Check whether a register is >= a given constant and go to a label if it
// is. Backtracks instead if the label is nullptr.
......@@ -158,7 +126,6 @@ class RegExpMacroAssembler {
// Check whether a register is == to the current position and go to a
// label if it is.
virtual void IfRegisterEqPos(int reg, Label* if_eq) = 0;
virtual IrregexpImplementation Implementation() = 0;
V8_EXPORT_PRIVATE void LoadCurrentCharacter(
int cp_offset, Label* on_end_of_input, bool check_bounds = true,
int characters = 1, int eats_at_least = kUseCharactersValue);
......@@ -171,6 +138,7 @@ class RegExpMacroAssembler {
// will go to this label. Always checks the backtrack stack limit.
virtual void PushBacktrack(Label* label) = 0;
virtual void PushCurrentPosition() = 0;
enum StackCheckFlag { kNoStackLimitCheck = false, kCheckStackLimit = true };
virtual void PushRegister(int register_index,
StackCheckFlag check_stack_limit) = 0;
virtual void ReadCurrentPositionFromRegister(int reg) = 0;
......@@ -183,8 +151,41 @@ class RegExpMacroAssembler {
virtual void ClearRegisters(int reg_from, int reg_to) = 0;
virtual void WriteStackPointerToRegister(int reg) = 0;
// Check that we are not in the middle of a surrogate pair.
void CheckNotInSurrogatePair(int cp_offset, Label* on_failure);
#define IMPLEMENTATIONS_LIST(V) \
V(IA32) \
V(ARM) \
V(ARM64) \
V(MIPS) \
V(LOONG64) \
V(RISCV) \
V(S390) \
V(PPC) \
V(X64) \
V(Bytecode)
enum IrregexpImplementation {
#define V(Name) k##Name##Implementation,
IMPLEMENTATIONS_LIST(V)
#undef V
};
inline const char* ImplementationToString(IrregexpImplementation impl) {
static const char* const kNames[] = {
#define V(Name) #Name,
IMPLEMENTATIONS_LIST(V)
#undef V
};
return kNames[impl];
}
#undef IMPLEMENTATIONS_LIST
virtual IrregexpImplementation Implementation() = 0;
// Compare two-byte strings case insensitively.
// Called from generated RegExp code.
//
// Called from generated code.
static int CaseInsensitiveCompareNonUnicode(Address byte_offset1,
Address byte_offset2,
size_t byte_length,
......@@ -194,12 +195,10 @@ class RegExpMacroAssembler {
size_t byte_length,
Isolate* isolate);
// Check that we are not in the middle of a surrogate pair.
void CheckNotInSurrogatePair(int cp_offset, Label* on_failure);
// 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_; }
bool slow_safe() const { return slow_safe_compiler_; }
// Controls after how many backtracks irregexp should abort execution. If it
// can fall back to the experimental engine (see `set_can_fallback`), it will
......@@ -223,11 +222,11 @@ class RegExpMacroAssembler {
// 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; }
inline bool global_with_zero_length_check() {
inline bool global() const { return global_mode_ != NOT_GLOBAL; }
inline bool global_with_zero_length_check() const {
return global_mode_ == GLOBAL || global_mode_ == GLOBAL_UNICODE;
}
inline bool global_unicode() { return global_mode_ == GLOBAL_UNICODE; }
inline bool global_unicode() const { return global_mode_ == GLOBAL_UNICODE; }
Isolate* isolate() const { return isolate_; }
Zone* zone() const { return zone_; }
......@@ -272,49 +271,62 @@ class NativeRegExpMacroAssembler: public RegExpMacroAssembler {
SMALLEST_REGEXP_RESULT = RegExp::kInternalRegExpSmallestResult,
};
NativeRegExpMacroAssembler(Isolate* isolate, Zone* zone);
~NativeRegExpMacroAssembler() override;
bool CanReadUnaligned() override;
NativeRegExpMacroAssembler(Isolate* isolate, Zone* zone)
: RegExpMacroAssembler(isolate, zone) {}
~NativeRegExpMacroAssembler() override = default;
// Returns a {Result} sentinel, or the number of successful matches.
static int Match(Handle<JSRegExp> regexp, Handle<String> subject,
int* offsets_vector, int offsets_vector_length,
int previous_index, Isolate* isolate);
V8_EXPORT_PRIVATE static int ExecuteForTesting(String input, int start_offset,
const byte* input_start,
const byte* input_end,
int* output, int output_size,
Isolate* isolate,
JSRegExp regexp);
bool CanReadUnaligned() const override;
void LoadCurrentCharacterImpl(int cp_offset, Label* on_end_of_input,
bool check_bounds, int characters,
int eats_at_least) override;
// Load a number of characters at the given offset from the
// current position, into the current-character register.
virtual void LoadCurrentCharacterUnchecked(int cp_offset,
int character_count) = 0;
// Called from RegExp if the backtrack stack limit is hit. Tries to expand
// the stack. Returns the new stack-pointer if successful, or returns 0 if
// unable to grow the stack.
// This function must not trigger a garbage collection.
//
// Called from generated code.
static Address GrowStack(Isolate* isolate);
// Called from generated code.
static int CheckStackGuardState(Isolate* isolate, int start_index,
RegExp::CallOrigin call_origin,
Address* return_address, Code re_code,
Address* subject, const byte** input_start,
const byte** input_end);
static Address word_character_map_address() {
return reinterpret_cast<Address>(&word_character_map[0]);
}
protected:
// Byte map of one byte characters with a 0xff if the character is a word
// character (digit, letter or underscore) and 0x00 otherwise.
// Used by generated RegExp code.
static const byte word_character_map[256];
static Address word_character_map_address() {
return reinterpret_cast<Address>(&word_character_map[0]);
}
private:
// Returns a {Result} sentinel, or the number of successful matches.
V8_EXPORT_PRIVATE static int Execute(String input, int start_offset,
const byte* input_start,
const byte* input_end, int* output,
int output_size, Isolate* isolate,
JSRegExp regexp);
void LoadCurrentCharacterImpl(int cp_offset, Label* on_end_of_input,
bool check_bounds, int characters,
int eats_at_least) override;
// Load a number of characters at the given offset from the
// current position, into the current-character register.
virtual void LoadCurrentCharacterUnchecked(int cp_offset,
int character_count) = 0;
static int Execute(String input, int start_offset, const byte* input_start,
const byte* input_end, int* output, int output_size,
Isolate* isolate, JSRegExp regexp);
};
} // namespace internal
......
......@@ -355,10 +355,9 @@ void RegExpMacroAssemblerX64::CheckNotBackReferenceIgnoreCase(
{
AllowExternalCallThatCantCauseGC scope(&masm_);
ExternalReference compare =
unicode ? ExternalReference::re_case_insensitive_compare_unicode(
isolate())
: ExternalReference::re_case_insensitive_compare_non_unicode(
isolate());
unicode
? ExternalReference::re_case_insensitive_compare_unicode()
: ExternalReference::re_case_insensitive_compare_non_unicode();
__ CallCFunction(compare, num_arguments);
}
......@@ -619,7 +618,7 @@ bool RegExpMacroAssemblerX64::CheckSpecialCharacterClass(base::uc16 type,
__ cmpl(current_character(), Immediate('z'));
BranchOrBacktrack(above, on_no_match);
}
__ Move(rbx, ExternalReference::re_word_character_map(isolate()));
__ Move(rbx, ExternalReference::re_word_character_map());
DCHECK_EQ(0, word_character_map[0]); // Character '\0' is not a word char.
__ testb(Operand(rbx, current_character(), times_1, 0),
current_character());
......@@ -633,7 +632,7 @@ bool RegExpMacroAssemblerX64::CheckSpecialCharacterClass(base::uc16 type,
__ cmpl(current_character(), Immediate('z'));
__ j(above, &done);
}
__ Move(rbx, ExternalReference::re_word_character_map(isolate()));
__ Move(rbx, ExternalReference::re_word_character_map());
DCHECK_EQ(0, word_character_map[0]); // Character '\0' is not a word char.
__ testb(Operand(rbx, current_character(), times_1, 0),
current_character());
......@@ -1023,8 +1022,7 @@ Handle<HeapObject> RegExpMacroAssemblerX64::GetCode(Handle<String> source) {
__ PrepareCallCFunction(kNumArguments);
__ LoadAddress(arg_reg_1, ExternalReference::isolate_address(isolate()));
ExternalReference grow_stack =
ExternalReference::re_grow_stack(isolate());
ExternalReference grow_stack = ExternalReference::re_grow_stack();
__ CallCFunction(grow_stack, kNumArguments);
// If nullptr is returned, we have failed to grow the stack, and must exit
// with a stack-overflow exception.
......@@ -1229,7 +1227,7 @@ void RegExpMacroAssemblerX64::CallCheckStackGuardState() {
__ leaq(rdi, Operand(rsp, -kSystemPointerSize));
#endif
ExternalReference stack_check =
ExternalReference::re_check_stack_guard_state(isolate());
ExternalReference::re_check_stack_guard_state();
__ CallCFunction(stack_check, num_arguments);
}
......
......@@ -655,7 +655,7 @@ static ArchRegExpMacroAssembler::Result Execute(JSRegExp regexp, String input,
Address input_end,
int* captures) {
return static_cast<NativeRegExpMacroAssembler::Result>(
NativeRegExpMacroAssembler::Execute(
NativeRegExpMacroAssembler::ExecuteForTesting(
input, start_offset, reinterpret_cast<byte*>(input_start),
reinterpret_cast<byte*>(input_end), captures, 0, CcTest::i_isolate(),
regexp));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment