[regexp] Avoid runtime call on OOB lastIndex values

At this point, last_index is definitely a canonicalized non-negative
number, which implies that any non-Smi last_index is greater than
the maximal string length. That in turn means that the matcher will
definitely fail, and we can avoid the expensive runtime call.

BUG=v8:6365,v8:6344

Review-Url: https://codereview.chromium.org/2863643004
Cr-Commit-Position: refs/heads/master@{#45143}
This commit is contained in:
jgruber 2017-05-05 09:44:45 -07:00 committed by Commit bot
parent 3f4536894a
commit 2fd1afc0c8
3 changed files with 24 additions and 5 deletions

View File

@ -306,9 +306,16 @@ Node* RegExpBuiltinsAssembler::RegExpExecInternal(Node* const context,
Node* const smi_string_length = LoadStringLength(string);
// Bail out to runtime for invalid {last_index} values.
GotoIfNot(TaggedIsSmi(last_index), &runtime);
GotoIf(SmiAboveOrEqual(last_index, smi_string_length), &runtime);
// At this point, last_index is definitely a canonicalized non-negative
// number, which implies that any non-Smi last_index is greater than
// the maximal string length. If lastIndex > string.length then the matcher
// must fail.
Label if_failure(this);
CSA_ASSERT(this, IsNumberNormalized(last_index));
CSA_ASSERT(this, IsNumberPositive(last_index));
GotoIfNot(TaggedIsSmi(last_index), &if_failure); // Outside Smi range.
GotoIf(SmiGreaterThan(last_index, smi_string_length), &if_failure);
// Load the irregexp code object and offsets into the subject string. Both
// depend on whether the string is one- or two-byte.
@ -358,8 +365,7 @@ Node* RegExpBuiltinsAssembler::RegExpExecInternal(Node* const context,
GotoIf(TaggedIsSmi(code), &runtime);
CSA_ASSERT(this, HasInstanceType(code, CODE_TYPE));
Label if_success(this), if_failure(this),
if_exception(this, Label::kDeferred);
Label if_success(this), if_exception(this, Label::kDeferred);
{
IncrementCounter(isolate()->counters()->regexp_entry_native(), 1);

View File

@ -3362,6 +3362,18 @@ Node* CodeStubAssembler::IsNumberNormalized(Node* number) {
return var_result.value();
}
Node* CodeStubAssembler::IsNumberPositive(Node* number) {
CSA_ASSERT(this, IsNumber(number));
Node* const float_zero = Float64Constant(0.);
return Select(TaggedIsSmi(number),
[=] { return TaggedIsPositiveSmi(number); },
[=] {
Node* v = LoadHeapNumberValue(number);
return Float64GreaterThanOrEqual(v, float_zero);
},
MachineRepresentation::kWord32);
}
Node* CodeStubAssembler::StringCharCodeAt(Node* string, Node* index,
ParameterMode parameter_mode) {
if (parameter_mode == SMI_PARAMETERS) CSA_ASSERT(this, TaggedIsSmi(index));

View File

@ -791,6 +791,7 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
// True iff |number| is either a Smi, or a HeapNumber whose value is not
// within Smi range.
Node* IsNumberNormalized(Node* number);
Node* IsNumberPositive(Node* number);
// ElementsKind helpers:
Node* IsFastElementsKind(Node* elements_kind);