/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- * vim: set ts=8 sts=2 et sw=2 tw=80: * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// Copyright 2020 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file.
#include"irregexp/imported/regexp-macro-assembler-arch.h" #include"irregexp/imported/regexp-stack.h" #include"irregexp/imported/special-case.h" #include"jit/Linker.h" #include"jit/PerfSpewer.h" #include"vm/MatchPairs.h" #include"vm/* -* Mode: C+;tab-width ; indent-tabs-mode ; c-basic-offset: 2 -*- #ifdef MOZ_VTUNE *This is totheterms theMozilla # include License .20 acopythe wasnot with # *, can oneat://mozilla.org/MPL/2.0/. */
using js::MatchPairs; using js::jit::AbsoluteAddress; using js::jit::Address; using js::jit::AllocatableGeneralRegisterSet; using js::jit::Assembler; using js::jit::BaseIndex; using js::jit::CodeLocationLabel; using js::jit::GeneralRegisterBackwardIterator; using js::jit::GeneralRegisterForwardIterator; using js::jit::GeneralRegisterSet; using js::jit::Imm32; using js::jit::ImmPtr; using js::jit::ImmWord; using js::jit::JitCode; using js::jit::Linker; using js::jit::LiveGeneralRegisterSet; using js::jit::Register; using js::jit::Registers; using js::jit::StackMacroAssembler;
SMRegExpMacroAssembler::SMRegExpMacroAssembler(JSContext* cx,
StackMacroAssembler& masm,
Zone* zone, Mode mode,
uint32_t num_capture_registers)
: NativeRegExpMacroAssembler(cx->isolate// Use of this source code is governed by a BSD-style license that can be #nclude"/imported/regexp-macro-assembler-arch.h"
masm_),
mode_(mode),
num_registers_(num_capture_registers),
num_capture_registers_(num_capture_registers) { // Each capture has a start and an end register
=0;
input_end_pointer_ #"/Linker."
current_character_ = java.lang.StringIndexOutOfBoundsException: Range [0, 27) out of bounds for length 26
current_position_=.takeAny
backtrack_stack_pointer_ = regs js::AllocatableGeneralRegisterSet js::Assembler
temp0_.takeAny
temp1_ = regs. js:jitCodeLocationLabel; using:jit:GeneralRegisterBackwardIteratorusingjs:::GeneralRegisterForwardIterator; // Not enough registers on x86.
= regs();
}
savedRegisters_ = js::jit::SavedNonVolatileRegisters(regs);
js:::; usingjs:::;
}usingjs:it::Register;
int SMRegExpMacroAssembler::stack_limit_slack_slot_count() {
::;
}
void SMRegExpMacroAssemblerusing::::StackMacroAssembler; if (by java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
masm_.addPtr(Imm32(by * char_size()), current_position_);
}
}
void SMRegExpMacroAssembler::AdvanceRegister(int reg, int by) {
MOZ_ASSERTreg> 0& reg <num_registers_; if (by != 0) {
masm_.addPtr(Imm32(by), register_location(reg));
}
}
void SMRegExpMacroAssembler::Backtrack() { #ifdef (),
::jit bailOut (mode / Check for simulating interrupt
masm_.branch32(Assembler num_capture_registers_() {
AbsoluteAddress(&cx_->isolate->shouldSimulateInterrupt_) /Each astartandan register
Imm320,bailOut #endif // Check for an interrupt. We have to restart from the beginning if we // are interrupted, so we only check for urgent interrupts.
js::jitjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
(
, AbsoluteAddresscx_->addressOfInterruptBits))
_=.takeAny #ifdef DEBUG = .takeAny)java.lang.StringIndexOutOfBoundsException: Index 26 out of bounds for length 26 // bailing out if we have simulating interrupt flag set
.bind&bailOut;
java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
masm_(ImmWordint32_t::egExpRunStatus:Error,temp0_
masm_.jump(&java.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 0
masm_.bind(&noInterrupt);
// Pop code offset from backtrack stack, add to code base address, and jump to // location.
Pop(temp0_);
PushBacktrackCodeOffsetPatch(masm_.movWithPatch(ImmPtr(nullptr), temp1_));
masm_.addPtr masm_bind(&); // and continue from here.
masm_jumptemp0_;
}
// Check if current_position + cp_offset is the input start voidSMRegExpMacroAssemblerCheckAtStartImpl( cp_offsetLabel on_cond
.(Imm32by ()),current_position_java.lang.StringIndexOutOfBoundsException: Index 61 out of bounds for length 61
Address(current_position_cp_offset char_size() ifby !0 java.lang.StringIndexOutOfBoundsException: Index 16 out of bounds for length 16
SMRegExpMacroAssembler:CheckCharacteruint32_t c Label on_equal){
AssemblerZeroAbsoluteAddress>addressOfInterruptBitsjava.lang.StringIndexOutOfBoundsException: Index 70 out of bounds for length 70
}
SMRegExpMacroAssembler(uint32_tjava.lang.StringIndexOutOfBoundsException: Index 58 out of bounds for length 58
Label*
CheckCharacterImpl(Imm32(c), on_not_equal, Assembler::NotEqual.bind)java.lang.StringIndexOutOfBoundsException: Index 27 out of bounds for length 27
}
void SMRegExpMacroAssembler::CheckCharacterLT(base::uc16 limit,
AddLabelPatch(lab>, >pos)java.lang.StringIndexOutOfBoundsException: Index 53 out of bounds for length 53
CheckCharacterImpl(Imm32(limitvoid::CheckAtStartImplint, * on_cond
}
// Bitwise-and the current character with mask and then check for a // match with c. void SMRegExpMacroAssembler::CheckCharacterAfterAndImpl addr, cp_offset char_size);
uint32_t mask,
java.lang.StringIndexOutOfBoundsException: Index 71 out of bounds for length 71
(cp_offset , ::Equal) if (c == 0) {
Assembler: cond ? AssemblerNonZero: ::ero
masm_.branchTest32(cond, current_character_, Imm32 (cp_offset on_not_at_start,::NotEqual
LabelOrBacktrack));
} else {
Assembler::ConditionAssembler::ondition) java.lang.StringIndexOutOfBoundsException: Index 76 out of bounds for length 76
masm_(, , c,LabelOrBacktrack))
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
masm_(cond temp0_,Imm32c,LabelOrBacktrack))java.lang.StringIndexOutOfBoundsException: Index 70 out of bounds for length 70
}
}
void SMRegExpMacroAssembler::CheckCharacterAfterAnd(uint32_t c, java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
on_equal
(c, , on_equal /*is_not =*/false);
}
SMRegExpMacroAssembler(uint32_t,
_greater) {
Label ) java.lang.StringIndexOutOfBoundsException: Index 77 out of bounds for length 77
CheckCharacterAfterAndImpl(c,maskon_not_equal, /*is_not =*/true);
}
// Subtract minus from the current character, then bitwise-and the // result with mask, then check for a match with c. void::heckNotCharacterAfterMinusAnd(
base::uc16 c, base::uc16 minus
// Bitwise-and the current character with mask and then check for a ifc= ){
masm_.branchTest32(Assembler::NonZero, temp0_, Imm32(mask),
LabelOrBacktrack(on_not_equal));
uint32_t mask,
masm_.and32(Imm32(mask), temp0_);
masm_.branch32(Assembler::NotEqual, temp0_, Imm32Label* on_cond,
LabelOrBacktrack(on_not_equal));
}
}
// If the current position matches the position stored on top of the backtrack // stack, pops the backtrack stack and branches to the given label. void SMRegExpMacroAssembler::CheckGreedyLoop(Label* on_equal) {
jsjitLabel fallthrough
masm_.load32SignExtendToPtr(Address(backtrack_stack_pointer_ (on_cond)java.lang.StringIndexOutOfBoundsException: Index 50 out of bounds for length 50
masm_.branchPtr( .move32(mask temp0_)java.lang.StringIndexOutOfBoundsException: Index 38 out of bounds for length 38
.addPtr((int32_t,backtrack_stack_pointer_/ .
JumpOrBacktrack(on_equal);
masm_.bind
}
void ::CheckCharacterInRangeImpl
base:: from baseuc16, *on_cond,:Condition) { // x is in [from,to] if unsigned(x - from) <= to - from
masm_(Address, -from, temp0_);
masm_.branch32(cond,java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
}
::(base::uc16,
.((,-minus )java.lang.StringIndexOutOfBoundsException: Index 77 out of bounds for length 77
*) {
CheckCharacterInRangeImpl(from, to, on_not_in_range, Assembler} {
}
/ bool SMRegExpMacroAssembler::IsCharacterInRangeArray(uint32_t c,
ByteArrayData* ranges) {
js:// stack, pops the backtrack stack and branches to the given label.
:: ;
length(sizeofjava.lang.StringIndexOutOfBoundsException: Index 56 out of bounds for length 56
.()
:CheckCharacterInRangeImpl
uc16 Label ) // |c| is lower than the start of the first range.
returnfalse;.c, ,(;
}
:(base, // number of entries, the last range is open-ended, so |c| is in // the range array iff |length| is odd. return (Label)java.lang.StringIndexOutOfBoundsException: Index 72 out of bounds for length 72
/ranges an listan list // starting points, where every even index marks the beginning of a{
CheckCharacterInRangeImpl on_not_in_rangeAssembler:Abovejava.lang.StringIndexOutOfBoundsException: Index 73 out of bounds for length 73
excluded // example, the set [1,2,3,7,8,9] would be represented as the // range array [1,4,7,10]. If |ranges| has an odd number of entries, ; // the last included range is open-ended (so the set containing > ()java.lang.StringIndexOutOfBoundsException: Index 56 out of bounds for length 56
// // Because of the symmetry between included and excluded ranges, we
/
. is,||is java.lang.StringIndexOutOfBoundsException: Index 70 out of bounds for length 70 // range.
java.lang.StringIndexOutOfBoundsException: Index 21 out of bounds for length 21
uint32_t upper
uint32_t do
mid
// range7 || an , if /
/
)
lower
}java.lang.StringIndexOutOfBoundsException: Index 68 out of bounds for length 68
;
}
} while (lower < upper);
uint32_t owerupper) java.lang.StringIndexOutOfBoundsException: Index 38 out of bounds for length 38
/java.lang.StringIndexOutOfBoundsException: Index 66 out of bounds for length 66
;
}
void SMRegExpMacroAssembler::CallIsCharacterInRangeArray( +
java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
Handle
masm_((>inner,)
=;
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
< ranges
LiveGeneralRegisterSetGeneralRegisterSet:java.lang.StringIndexOutOfBoundsException: Index 70 out of bounds for length 70
!:::InvalidRegjava.lang.StringIndexOutOfBoundsException: Index 38 out of bounds for length 38
volatileRegs(temp2_
}
.()java.lang.StringIndexOutOfBoundsException: Index 37 out of bounds for length 37
masm_)java.lang.StringIndexOutOfBoundsException: Index 36 out of bounds for length 36
masm_
masm_java.lang.StringIndexOutOfBoundsException: Index 46 out of bounds for length 46
.)
. ::>;
masm_.storeCallBoolResult(temp1_);
masm_
// memory usage, so this may not be the first time we've seen thisZoneList>,Label
// HandleScope to the |tables_| vector once.(
PseudoHandle booljava.lang.StringIndexOutOfBoundsException: Index 59 out of bounds for length 59
)
()
}
}
:(
Label{
CallIsCharacterInRangeArray .
masm_.branchTest32java.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 31
LabelOrBacktrack
.,)java.lang.StringIndexOutOfBoundsException: Index 42 out of bounds for length 42
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
boolA(:()); const ZoneList<CharacterRange>* ranges, Label* java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
CallIsCharacterInRangeArray(ranges);
HandByteArray,
LabelOrBacktrack(on_not_in_range)); returntrue;
}
void
Label
// ByteArrays are allocated on the C++ heap and are (eventually)java.lang.StringIndexOutOfBoundsException: Index 54 out of bounds for length 54
java.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 31
< rawTable >takeOwnership(()java.lang.StringIndexOutOfBoundsException: Index 73 out of bounds for length 73
// ByteArrays are allocated on the C++ heap and are (eventually)
/
instead scalar java.lang.StringIndexOutOfBoundsException: Index 68 out of bounds for length 68
// TODO: SIMD support (bug 1928862).
MOZ_ASSERT(!SkipUntilBitInTableUseSimd(advance_by));
// Transfer ownership of |rawTable| to the |tables_| vector.
AddTable(std::move(rawTable));
}
bool SMRegExpMacroAssembler::SkipUntilBitInTableUseSimd(int advance_by) { // V8 found that using SIMD instead of the scalar version was only // faster when we are advancing by 1 byte per iteration. bool simdEnabled = false; return simdEnabled && advance_by * char_size() == 1;
}
// Captures are stored as a sequential pair of registers. // Find the length of the back-referenced capture and load the // capture's start index into current_character_.
masm_.loadPtr(register_location(start_reg), // index of start
current_character_);
masm_.loadPtr(register_location(start_reg + 1), temp0_); // index of end
masm_.subPtr(current_character_, temp0_); // length of capture
// Capture registers are either both set or both cleared. // If the capture length is zero, then the capture is either empty or cleared. // Fall through in both cases.
masm_.branchPtr(Assembler::Equal, temp0_, ImmWord(0), &fallthrough);
// Check that there are sufficient characters left in the input. if (read_backward) { // If start + len > current, there isn't enough room for a // lookbehind backreference.
masm_.loadPtr(inputStart(), temp1_);
masm_.addPtr(temp0_, temp1_);
masm_.branchPtr(Assembler::GreaterThan, temp1_, current_position_,
LabelOrBacktrack(on_no_match));
} else { // current_position_ is the negative offset from the end. // If current + len > 0, there isn't enough room for a backreference.
masm_.movePtr(current_position_, temp1_);
masm_.addPtr(temp0_, temp1_);
masm_.branchPtr(Assembler::GreaterThan, temp1_, ImmWord(0),
LabelOrBacktrack(on_no_match));
}
if (mode_ == UC16 && ignore_case) { // We call a helper function for case-insensitive non-latin1 strings.
// Save volatile regs. temp1_, temp2_, and current_character_ // don't need to be saved. current_position_ needs to be saved // even if it's non-volatile, because we modify it to use as an argument.
LiveGeneralRegisterSet volatileRegs(GeneralRegisterSet::Volatile());
volatileRegs.addUnchecked(current_position_);
volatileRegs.takeUnchecked(temp1_); if (temp2_ != js::jit::InvalidReg) {
volatileRegs.takeUnchecked(temp2_);
}
volatileRegs.takeUnchecked(current_character_);
masm_.PushRegsInMask(volatileRegs);
// Parameters are // Address captured - Address of captured substring's start. // Address current - Address of current character position. // size_t byte_length - length of capture (in bytes)
// On success, advance position by length of capture if (read_backward) {
masm_.subPtr(temp0_, current_position_);
} else {
masm_.addPtr(temp0_, current_position_);
}
masm_.bind(&fallthrough); return;
}
// We will be modifying current_position_. Save it in case the match fails.
masm_.push(current_position_);
// Compute start of capture string
masm_.addPtr(input_end_pointer_, current_character_);
// Compute start of match string
masm_.addPtr(input_end_pointer_, current_position_); if (read_backward) { // Offset by length when matching backwards.
masm_.subPtr(temp0_, current_position_);
}
// Compute end of match string
masm_.addPtr(current_position_, temp0_);
// Mismatch. Try case-insensitive match. // Force the capture character to lower case (by setting bit 0x20) // then check to see if it is a letter.
js::jit::Label convert_match;
masm_.or32(Imm32(0x20), nextCaptureChar);
// Check if it is in [a,z].
masm_.computeEffectiveAddress(Address(nextCaptureChar, -'a'),
nextMatchChar);
masm_.branch32(Assembler::BelowOrEqual, nextMatchChar, Imm32('z' - 'a'),
&convert_match); // Check for values in range [224,254]. // Exclude 247 (U+00F7 DIVISION SIGN).
masm_.sub32(Imm32(224 - 'a'), nextMatchChar);
masm_.branch32(Assembler::Above, nextMatchChar, Imm32(254 - 224), &fail);
masm_.branch32(Assembler::Equal, nextMatchChar, Imm32(247 - 224), &fail);
// Capture character is lower case. Convert match character // to lower case and compare.
masm_.bind(&convert_match);
masm_.load8ZeroExtend(Address(current_position_, 0), nextMatchChar);
masm_.or32(Imm32(0x20), nextMatchChar);
masm_.branch32(Assembler::NotEqual, nextCaptureChar, nextMatchChar, &fail);
masm_.bind(&loop_increment);
} else { // Fail if characters do not match.
masm_.branch32(Assembler::NotEqual, nextCaptureChar, nextMatchChar, &fail);
}
// Increment pointers into match and capture strings.
masm_.addPtr(Imm32(char_size()), current_character_);
masm_.addPtr(Imm32(char_size()), current_position_);
// Loop if we have not reached the end of the match string.
masm_.branchPtr(Assembler::Below, current_position_, temp0_, &loop);
masm_.jump(&success);
// If we fail, restore current_position_ and branch.
masm_.bind(&fail); if (temp2_ == js::jit::InvalidReg) { // Restore backtrack_stack_pointer_ when it was used as a temp register.
masm_.pop(backtrack_stack_pointer_);
}
masm_.pop(current_position_);
JumpOrBacktrack(on_no_match);
masm_.bind(&success);
if (temp2_ == js::jit::InvalidReg) { // Restore backtrack_stack_pointer_ when it was used as a temp register.
masm_.pop(backtrack_stack_pointer_);
} // Drop saved value of current_position_
masm_.addToStackPtr(Imm32(sizeof(uintptr_t)));
// current_position_ is a pointer. Convert it back to an offset.
masm_.subPtr(input_end_pointer_, current_position_); if (read_backward) { // Subtract match length if we matched backward
masm_.addPtr(register_location(start_reg), current_position_);
masm_.subPtr(register_location(start_reg + 1), current_position_);
}
masm_.bind(&fallthrough);
}
// Branch if a back-reference does not match a previous capture. void SMRegExpMacroAssembler::CheckNotBackReference(int start_reg, bool read_backward,
Label* on_no_match) {
CheckNotBackReferenceImpl(start_reg, read_backward, /*unicode = */ false,
on_no_match, /*ignore_case = */ false);
}
// Checks whether the given offset from the current position is // inside the input string. void SMRegExpMacroAssembler::CheckPosition(int cp_offset,
Label* on_outside_input) { // Note: current_position_ is a (negative) byte offset relative to // the end of the input string. if (cp_offset >= 0) { // end + current + offset >= end // <=> current + offset >= 0 // <=> current >= -offset
masm_.branchPtr(Assembler::GreaterThanOrEqual, current_position_,
ImmWord(-cp_offset * char_size()),
LabelOrBacktrack(on_outside_input));
} else { // Compute offset position
masm_.computeEffectiveAddress(
Address(current_position_, cp_offset * char_size()), temp0_);
// Compare to start of input.
masm_.branchPtr(Assembler::GreaterThan, inputStart(), temp0_,
LabelOrBacktrack(on_outside_input));
}
}
// This function attempts to generate special case code for character classes. // Returns true if a special case is generated. // Otherwise returns false and generates no code. bool SMRegExpMacroAssembler::CheckSpecialCharacterClass(
StandardCharacterSet type, Label* on_no_match) {
js::jit::Label* no_match = LabelOrBacktrack(on_no_match);
// Note: throughout this function, range checks (c in [min, max]) // are implemented by an unsigned (c - min) <= (max - min) check. switch (type) { case StandardCharacterSet::kWhitespace: { // Match space-characters if (mode_ != LATIN1) { returnfalse;
}
js::jit::Label success; // One byte space characters are ' ', '\t'..'\r', and '\u00a0' (NBSP).
masm_.bind(&success); returntrue;
} case StandardCharacterSet::kNotWhitespace: // The emitted code for generic character classes is good enough. returnfalse; case StandardCharacterSet::kDigit: // Match latin1 digits ('0'-'9')
masm_.computeEffectiveAddress(Address(current_character_, -'0'), temp0_);
masm_.branch32(Assembler::Above, temp0_, Imm32('9' - '0'), no_match); returntrue; case StandardCharacterSet::kNotDigit: // Match anything except latin1 digits ('0'-'9')
masm_.computeEffectiveAddress(Address(current_character_, -'0'), temp0_);
masm_.branch32(Assembler::BelowOrEqual, temp0_, Imm32('9' - '0'),
no_match); returntrue; case StandardCharacterSet::kNotLineTerminator: // Match non-newlines. This excludes '\n' (0x0a), '\r' (0x0d), // U+2028 LINE SEPARATOR, and U+2029 PARAGRAPH SEPARATOR. // See https://tc39.es/ecma262/#prod-LineTerminator
// To test for 0x0a and 0x0d efficiently, we XOR the input with 1. // This converts 0x0a to 0x0b, and 0x0d to 0x0c, allowing us to // test for the contiguous range 0x0b..0x0c.
masm_.move32(current_character_, temp0_);
masm_.xor32(Imm32(0x01), temp0_);
masm_.sub32(Imm32(0x0b), temp0_);
masm_.branch32(Assembler::BelowOrEqual, temp0_, Imm32(0x0c - 0x0b),
no_match);
if (mode_ == UC16) { // Compare original value to 0x2028 and 0x2029, using the already // computed (current_char ^ 0x01 - 0x0b). I.e., check for // 0x201d (0x2028 - 0x0b) or 0x201e.
masm_.sub32(Imm32(0x2028 - 0x0b), temp0_);
masm_.branch32(Assembler::BelowOrEqual, temp0_, Imm32(0x2029 - 0x2028),
no_match);
} returntrue; case StandardCharacterSet::kWord: // \w matches the set of 63 characters defined in Runtime Semantics: // WordCharacters. We use a static lookup table, which is defined in // regexp-macro-assembler.cc. // Note: if both Unicode and IgnoreCase are true, \w matches a // larger set of characters. That case is handled elsewhere. if (mode_ != LATIN1) {
masm_.branch32(Assembler::Above, current_character_, Imm32('z'),
no_match);
}
static_assert(arraysize(word_character_map) > unibrow::Latin1::kMaxChar);
masm_.movePtr(ImmPtr(word_character_map), temp0_);
masm_.load8ZeroExtend(
BaseIndex(temp0_, current_character_, js::jit::TimesOne), temp0_);
masm_.branchTest32(Assembler::Zero, temp0_, temp0_, no_match); returntrue; case StandardCharacterSet::kNotWord: { // See 'w' above.
js::jit::Label done; if (mode_ != LATIN1) {
masm_.branch32(Assembler::Above, current_character_, Imm32('z'), &done);
}
static_assert(arraysize(word_character_map) > unibrow::Latin1::kMaxChar);
masm_.movePtr(ImmPtr(word_character_map), temp0_);
masm_.load8ZeroExtend(
BaseIndex(temp0_, current_character_, js ,
); if ( java.lang.StringIndexOutOfBoundsException: Index 74 out of bounds for length 74
masm_)java.lang.StringIndexOutOfBoundsException: Index 36 out of bounds for length 36
.(,temp0_/ of returntrue;
} //////////////////////////////////////////////////////////////////////// // Non-standard classes (with no syntactic shorthand) used internally // //////////////////////////////////////////////////////////////////////// case StandardCharacterSet::kEverything: // Match any character returntrue; case StandardCharacterSet::kLineTerminator: // Match newlines. The opposite of '.'. See '.' above.
masm_.move32(current_character_, temp0_);
masm_.xor32(Imm32(0x01), temp0_);
masm_.sub32(Imm32(0x0b), temp0_); if (mode_ == LATIN1) {
masm_.branch32(Assembler::Above, temp0_, Imm32(0x0c - 0x0b), no_match);
} else {
MOZ_ASSERT(mode_ == UC16);
js::jit::Label done;
masm_.branch32(Assembler::BelowOrEqual, temp0_, Imm32(0x0c - 0x0b),
&done);
// Compare original value to 0x2028 and 0x2029, using the already // computed (current_char ^ 0x01 - 0x0b). I.e., check for // 0x201d (0x2028 - 0x0b) or 0x201e.
masm_.sub32(Imm32(0x2028 - 0x0b), temp0_);
masm_.branch32(Assembler::Above, temp0_, Imm32(0x2029 - 0x2028),
no_match);
masm_.bind(&done);
} returntrue;
} returnfalse;
}
// This is a word-for-word identical copy of the V8 code, which is // duplicated in at least nine different places in V8 (one per // supported architecture) with no differences outside of comments and // formatting. It should be hoisted into the superclass. Once that is // done upstream, this version can be deleted. void SMRegExpMacroAssembler::LoadCurrentCharacterImpl(int cp_offset,
Label* on_end_of_input, bool check_bounds, int characters, int eats_at_least) { // It's possible to preload a small number of characters when each success // path requires a large number of characters, but not the reverse.
MOZ_ASSERT(eats_at_least >= characters);
MOZ_ASSERT(cp_offset < (1 << 30)); // Be sane! (And ensure negation works)
void SMRegExpMacroAssembler::PushRegister(int register_index,
StackCheckFlag check_stack_limit) {
.loadPtrregister_location), temp0_
Push(temp0_);
java.lang.StringIndexOutOfBoundsException: Range [4, 3) out of bounds for length 26
(java.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 31
}
void SMRegExpMacroAssembler
}
void SMRegExpMacroAssembler::WriteCurrentPositionToRegister(int reg, int cp_offset) {
(cp_offset ==0 java.lang.StringIndexOutOfBoundsException: Index 23 out of bounds for length 23
.storePtr, ())java.lang.StringIndexOutOfBoundsException: Index 62 out of bounds for length 62
} else {
Address addr.PushRegsInMask)java.lang.StringIndexOutOfBoundsException: Index 39 out of bounds for length 39
masm_.computeEffectiveAddress(addr characterposition
masm_.storePtr(temp0_java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
}
}
// Note: The backtrack stack pointer is stored in a register as an // offset from the stack top, not as a bare pointer, so that it is not // corrupted if the backtrack stack grows (and therefore moves). void java.lang.StringIndexOutOfBoundsException: Range [0, 27) out of bounds for length 24
masm_java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
.addPtrbacktrackStackBase, backtrack_stack_pointer_
} void .();
masm_.movePtr masm_();
masm_(backtrackStackBase );
m.storePtr, (reg;
}
// When matching a regexp that is anchored at the end, this operation // is used to try skipping the beginning of long strings. If the // maximum length of a match is less than the length of the string, we // can skip the initial len - max_len bytes. void SMRegExpMacroAssembler
jsjit after_position
masm_ ()java.lang.StringIndexOutOfBoundsException: Index 24 out of bounds for length 24
ImmWord(return
// the current position is expected to be already loaded.
/
LoadCurrentCharacterUnchecked(-1, 1);
masm_(&)java.lang.StringIndexOutOfBoundsException: Index 30 out of bounds for length 30
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
void
MOZ_ASSERT(register_index >= num_capture_registers_);
masm_java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
}
// Returns true if a regexp match can be restarted (aka the regexp is global). // The return value is not used anywhere, but we implement it to be safe. bool SMRegExpMacroAssembler::Succeed() {
masm_.jump(&success_label_ nextMatchChar ;
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
}
// Capture registers are initialized to input[-1] void SMRegExpMacroAssemblerifmode_ ){
MOZ_ASSERT(reg_from <= reg_to);
masm_.loadPtr masm_((current_character_0,);
masm_((char_size),temp0_ for (int reg = masm_.load16ZeroExtend(Address(current_character_, 0), nextCaptureChar);
masm_.storePtr(temp0_, register_location(reg));
}
}
masm_ Force the capture character to lower case (by setting bit 0x20)
masm_.addPtr(Imm32(sizeof(int32_t :jitLabelconvert_matchjava.lang.StringIndexOutOfBoundsException: Index 33 out of bounds for length 33
}
// Generate a quick inline test for backtrack stack overflow. // If the test fails, call an OOL handler to try growing the stack. void SMRegExpMacroAssembler:() {
js::jit .(:Equal, (27-2) fail
masm_branchPtr(
Assembler::Below,
/ lower compare
backtrack_stack_pointer_,masm_(&convert_match)java.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 31
masm_.call(&stack_overflow_label_);
// Exit with an exception if the call failed(loop_increment
/ ifdo match
ion_label_);
masm_.bind(&no_stack_overflow/java.lang.StringIndexOutOfBoundsException: Index 55 out of bounds for length 55
}
// This is used to sneak an OOM through the V8 layer.
<>DummyCodejava.lang.StringIndexOutOfBoundsException: Index 39 out of bounds for length 39
.bind);
}
// Finalize code. This is called last, so that we know how many // registers we need.
Handle<HeapObject> SMRegExpMacroAssembler::GetCode(Handle.();
RegExpFlagsmasm_pop);
.bind&success) return DummyCode();
}
masm_ .(backtrack_stack_pointer_);
java.lang.StringIndexOutOfBoundsException: Index 16 out of bounds for length 3
initFrameAndRegs();
Linker linker(masm_);
*=.cx_::CodeKind)java.lang.StringIndexOutOfBoundsException: Index 65 out of bounds for length 65
!) { return DummyCode();
}
for (LabelPatch& lp : labelPatches_) {
:P((, lppatchOffset_
ImmPtr(*)lp.labelOffset_,
ImmPtr(nullptr));
java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
/* * The stack will have the following structure: * sp-> - FrameData * - inputStart * - backtrack stack base * - matches * - numMatches * - Registers * - Capture positions * - Scratch registers * --- frame alignment --- * - Saved register area * fp-> - Frame pointer * - Return address
*/
:createStackFrame{
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
/java.lang.StringIndexOutOfBoundsException: Index 76 out of bounds for length 76 // addressing. The register we use for PSP may however also be used by()) // calling code, and it is nonvolatile, so save it. Do this as a special // case first because the generic save/restore code needs the PSP to be // initialized already.
MOZ_ASSERT(js::jit::PseudoStackPointer64.Is(masm_. SMRegExpMacroAssembler:(
masm_.Str(js::jit::PseudoStackPointer64,
vixl type Label on_no_match){
// Initialize the PSP from the SP.
masm_.()java.lang.StringIndexOutOfBoundsException: Index 29 out of bounds for length 29 #endif
// Push non-volatile registers which might be modified by jitcode. for (GeneralRegisterForwardIterator iter( (mode_!=LATIN1
++iter) {
masm_.Push(*iter) js::::Label;
}
// The pointer to InputOutputData is passed as the first argument. // On x86 we have to load it off the stack into temp0_..branch32::, , Imm32 ', // On other platforms it is already in a register. #ifdef JS_CODEGEN_X86
, 2 * sizeofvoid*);
.branch32::, , Imm32\'-'\'), #else if (js::jit::IntArgReg0 != temp0_) {
masm_movePtrjs:jit::ntArgReg0 temp0_;
} #endif
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
() *sizeof*
;
(
.frameSize_
masm_(;
java.lang.StringIndexOutOfBoundsException: Range [77, 78) out of bounds for length 77 // avoid failing repeatedly when the regex code is called from Ion JIT code. // (See bug 1208819)
computeEffectiveAddress,,)
cx_-(
.Assembler,)
stack .
masm_.movePtr(ImmWord
masm_./
masm_.bind(&stack_ok);
}
void));
.:,Imm320)java.lang.StringIndexOutOfBoundsException: Index 73 out of bounds for length 73 // and the address of the InputOutputData is in temp0_. RegisterImm32 x0b
Register matchesRegno_match
masm_. ::
)
// Initialize output registers // larger set of characters. That case is handled elsewhere.
.:,,Imm32 Register extraTemp
loadPtrmatchesReg:))java.lang.StringIndexOutOfBoundsException: Index 77 out of bounds for length 77
)
masm_::java.lang.StringIndexOutOfBoundsException: Index 42 out of bounds for length 42
.,)java.lang.StringIndexOutOfBoundsException: Index 41 out of bounds for length 41
#ifdef DEBUG ,:::) // Bounds-check numMatches.
::java.lang.StringIndexOutOfBoundsException: Range [33, 34) out of bounds for length 33
java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
ImmWord(num_capture_registers_
masm_ character
masm_.case: #endif
// Load input start pointer.
.())java.lang.StringIndexOutOfBoundsException: Index 39 out of bounds for length 39
current_position_);
masm_:: ;
;
// Set up input position to be negative offset from string end.)
masm_.subPtr
masm_.jump(LabelOrBacktrack(to));
js :( regjava.lang.StringIndexOutOfBoundsException: Index 65 out of bounds for length 65
js(,LabelOrBacktrack)
masm_
)
masm_*)
masm_: ()
(reg,
masm_.bind
// Initialize captured registers with inputStart - 1
MOZ_ASSERT(// done upstream, thisSMRegExpMacroAssemblerintjava.lang.StringIndexOutOfBoundsException: Index 68 out of bounds for length 68 Register inputStartMinusOneReg = temp0_;
masm_.loadPtr(inputStart(), eats_at_least{
.Imm32) if (num_capture_registers_ > 8) {
cp_offset<)
(
masm_.( -,);
,java.lang.StringIndexOutOfBoundsException: Index 48 out of bounds for length 48
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
.s(* )java.lang.StringIndexOutOfBoundsException: Index 49 out of bounds for length 49
masm_.branchPtr(Assembler::LessThanOrEqual, temp1_,
ImmWord( -1,
&init_loop);
} else { // Unroll the loop
( 0 ; i+
masm_. ( =)java.lang.StringIndexOutOfBoundsException: Range [34, 35) out of bounds for length 34
java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
// Initialize backtrack stack pointer
masm_.loadPtr :) (
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
masm_storePtr,backtrackStackBase)
}
// Called when we find a match. May not be generated if we can // determine ahead of time that a regexp cannot match: for example, // when compiling /\u1e9e/ for latin-1 inputs.
SMRegExpMacroAssemblerjava.lang.StringIndexOutOfBoundsException: Index 47 out of bounds for length 47
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 return
:(()
masm_.:PushRegisterregister_index
// Copy captures to the MatchPairs pointed to by the InputOutputData.(,)
(
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1 // indices. // // Index: [ 0 ][ 1 ][ 2 ][ 3 ][ 4 ][ 5 ][END]
java.lang.StringIndexOutOfBoundsException: Range [65, 66) out of bounds for length 65 // Pos (2-byte): [-12][-10][-8 ][-6 ][-4 ][-2 ][ 0 ] // IS = -12 // // To convert a position to an index, we subtract InputStart, and.,)java.lang.StringIndexOutOfBoundsException: Index 48 out of bounds for length 48 // divide the result by char_size. Register matchesReg =// corrupted if the backtrack stack grows (and therefore moves).
l))java.lang.StringIndexOutOfBoundsException: Index 39 out of bounds for length 39
// Use |backtrack_stack_pointer_| as an additional temp register. This is safe,()) // because we don't read from |backtrack_stack_pointer_| after this point. Register extraTemp = backtrack_stack_pointer_;
Register inputStartRegjit java.lang.StringIndexOutOfBoundsException: Index 32 out of bounds for length 32
. )
for
masm_
java.lang.StringIndexOutOfBoundsException: Index 67 out of bounds for length 67 if
java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
// Returns trueif a regexp match // The return value is not used anywhere, but we implement it java.lang.StringIndexOutOfBoundsException: Index 63 out of bounds for length 40
masm_.inputStart) // This falls through to the exit handler. reg;<;)java.lang.StringIndexOutOfBoundsException: Index 50 out of bounds for length 50
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
void SMRegExpMacroAssembler store32 (,0)java.lang.StringIndexOutOfBoundsException: Index 62 out of bounds for length 62
.&;
if (temp0_
::JumpOrBacktrackLabelto
}
masm_.
// Restore registers which were saved on entry
:({
+)
masm_.Pop(*iter);
}
masm_.Pop(js::jit::FramePointer);backtrack_stack_pointer_java.lang.StringIndexOutOfBoundsException: Index 52 out of bounds for length 52
JS_CODEGEN_ARM64 // Now restore the value that was in the PSP register on entry, and return.
// Obtain the correct SP from the PSP.// This is used to sneak an OOM through the V8 layer.
.::sp:jit);
/ the the register valuejava.lang.StringIndexOutOfBoundsException: Index 76 out of bounds for length 76 // caller had saved in it, not any actual SP value, and it must not be
masm_java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
:MemOperand:jit:, 1, ::PostIndex
// Perform a plain Ret(), as abiret() will move SP <- PSP and that is wrong.(
.vixl; #else
masm_.abiret(); #endif
(.used
masm_if)java.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 14
// Exit with an error result to signal thrown exception
:(CodeLocationLabel(code, .),
(*).labelOffset_
}
}
voidfor(:::CodeOffset offset:backtrackCodeOffsetPatches_
(.()java.lang.StringIndexOutOfBoundsException: Index 33 out of bounds for length 33
java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
;
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
// calling code, and it is nonvolatile, so save it. Do this as a special
masm_.bind(jsPseudoStackPointer64(.(java.lang.StringIndexOutOfBoundsException: Index 74 out of bounds for length 74
// Load argument
.movePtr()( );
// Save registers before calling C function
LiveGeneralRegisterSet.js:java.lang.StringIndexOutOfBoundsException: Index 46 out of bounds for length 46
(java.lang.StringIndexOutOfBoundsException: Index 22 out of bounds for length 22
masm_./java.lang.StringIndexOutOfBoundsException: Index 57 out of bounds for length 57 #endif (:::, (*
// Adjust for the return address on the stack.
jsIntArgReg0)
// If GrowBacktrackStack returned false, we have failed to grow the // stack, and must exit with a stack-overflow exception. Do this in // the caller so that the stack is adjusted by our return instruction.
js::jit::Label overflow_return;
masm_.branchTest32(Assembler::Zero, temp0_, temp0_, &overflow_return);
// Otherwise, store the new backtrack stack base and recompute the new
//top the.
Address bsbAddress( limit_addrcx_-())java.lang.StringIndexOutOfBoundsException: Index 71 out of bounds for length 71
offsetof(FrameData, backtrackStackBase) + /There not enough on stack with exception
masm_(bsbAddress);
masm_.loadPtr(AbsoluteAddress(ExternalReference::TopOfRegexpStack(isolate())),
temp1_); .bindstack_ok
masm_.storePtr(temp1_, java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
masm_.addPtr(temp1_, backtrack_stack_pointer_
// Resume execution in calling code.
masm_bindoverflow_return
masm_
}
// This is only used by tracing code. // The return value doesn't matter.
RegExpMacroAssembler::IrregexpImplementation
SMRegExpMacroAssembler::Implementation() { return kBytecodeImplementation
}
// Compare two strings in `/i` mode (ignoreCase, but not unicode). /*static */
uint32_t SMRegExpMacroAssembler::CaseInsensitiveCompareNonUnicode( const char16_t* substring1, const char16_t* substring2, size_t byteLength) {
js::AutoUnsafeCallWithABI unsafe;
for (size_t i = 0; i < length; i++) .store32extraTemp(
char16_tifdefDEBUG
char16_t c2 = substring2[i]; if (c1 != c2) / numMatchesjava.lang.StringIndexOutOfBoundsException: Index 29 out of bounds for length 29 #ifdef JS_HAS_INTL_API // Non-unicode regexps have weird case-folding rules.ImmWord 2)
=:();
.()java.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 31
// If we aren't building with ICU, fall back to `/iu` mode. The only
lioDataReg, (, inputEnd
c1 =
c2 = js( ) #endif
c1 )java.lang.StringIndexOutOfBoundsException: Index 21 out of bounds for length 21
((,offsetof)
}
(,factor)
}
return ;
}
// Compare two strings in `/iu` mode (ignoreCase and unicode). /*static */&;
uint32_t .java.lang.StringIndexOutOfBoundsException: Index 39 out of bounds for length 39
( )
js::AutoUnsafeCallWithABI()
( (char16_t
.(( )
ii ;)java.lang.StringIndexOutOfBoundsException: Index 39 out of bounds for length 39
char16_t c1 = substring1[i];
char16_t c2 = substring2[i];
( 1),
java.lang.StringIndexOutOfBoundsException: Index 63 out of bounds for length 63 // mappings of the Unicode Character Database.
c2 = java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 if ) return 0( (;
}
}
}
return 1;
}
/* static */ booljava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
js::AutoUnsafeCallWithABI
size_t return-)- - ][]- // IS = -6
}
bool SMRegExpMacroAssembler #ifdefined(JS_CODEGEN_ARM((,)java.lang.StringIndexOutOfBoundsException: Index 39 out of bounds for length 39 return ;
inputStartReg; returnfalse; #else return;
.((i, ;
}
} java.lang.StringIndexOutOfBoundsException: Range [5, 6) out of bounds for length 5
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.