[CSA][cleanup] TNodify builtins regexp gen
Bug: v8:6949, v8:9396 Change-Id: I035a00f61077e49377c9cd39ae1b216a80c98e6b Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1803615 Reviewed-by: Dan Elphick <delphick@chromium.org> Commit-Queue: Santiago Aboy Solanes <solanes@chromium.org> Cr-Commit-Position: refs/heads/master@{#63848}
This commit is contained in:
parent
c3d7f5f188
commit
7fcbde16e7
@ -237,8 +237,7 @@ TNode<JSRegExpResult> RegExpBuiltinsAssembler::ConstructNewResultFromMatchInfo(
|
|||||||
IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex + 2));
|
IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex + 2));
|
||||||
TVARIABLE(IntPtrT, var_to_cursor, IntPtrConstant(1));
|
TVARIABLE(IntPtrT, var_to_cursor, IntPtrConstant(1));
|
||||||
|
|
||||||
Variable* vars[] = {&var_from_cursor, &var_to_cursor};
|
Label loop(this, {&var_from_cursor, &var_to_cursor});
|
||||||
Label loop(this, 2, vars);
|
|
||||||
|
|
||||||
Goto(&loop);
|
Goto(&loop);
|
||||||
BIND(&loop);
|
BIND(&loop);
|
||||||
@ -317,9 +316,7 @@ TNode<JSRegExpResult> RegExpBuiltinsAssembler::ConstructNewResultFromMatchInfo(
|
|||||||
|
|
||||||
TVARIABLE(IntPtrT, var_i, IntPtrZero());
|
TVARIABLE(IntPtrT, var_i, IntPtrZero());
|
||||||
|
|
||||||
Variable* vars[] = {&var_i};
|
Label loop(this, &var_i);
|
||||||
const int vars_count = sizeof(vars) / sizeof(vars[0]);
|
|
||||||
Label loop(this, vars_count, vars);
|
|
||||||
|
|
||||||
Goto(&loop);
|
Goto(&loop);
|
||||||
BIND(&loop);
|
BIND(&loop);
|
||||||
@ -908,14 +905,13 @@ TNode<BoolT> RegExpBuiltinsAssembler::IsReceiverInitialRegExpPrototype(
|
|||||||
return TaggedEqual(receiver, initial_prototype);
|
return TaggedEqual(receiver, initial_prototype);
|
||||||
}
|
}
|
||||||
|
|
||||||
Node* RegExpBuiltinsAssembler::IsFastRegExpNoPrototype(
|
TNode<BoolT> RegExpBuiltinsAssembler::IsFastRegExpNoPrototype(
|
||||||
SloppyTNode<Context> context, SloppyTNode<Object> object,
|
TNode<Context> context, TNode<Object> object, TNode<Map> map) {
|
||||||
SloppyTNode<Map> map) {
|
|
||||||
Label out(this);
|
Label out(this);
|
||||||
VARIABLE(var_result, MachineRepresentation::kWord32);
|
TVARIABLE(BoolT, var_result);
|
||||||
|
|
||||||
#ifdef V8_ENABLE_FORCE_SLOW_PATH
|
#ifdef V8_ENABLE_FORCE_SLOW_PATH
|
||||||
var_result.Bind(Int32Constant(0));
|
var_result = Int32FalseConstant();
|
||||||
GotoIfForceSlowPath(&out);
|
GotoIfForceSlowPath(&out);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -926,13 +922,13 @@ Node* RegExpBuiltinsAssembler::IsFastRegExpNoPrototype(
|
|||||||
LoadObjectField(regexp_fun, JSFunction::kPrototypeOrInitialMapOffset);
|
LoadObjectField(regexp_fun, JSFunction::kPrototypeOrInitialMapOffset);
|
||||||
TNode<BoolT> const has_initialmap = TaggedEqual(map, initial_map);
|
TNode<BoolT> const has_initialmap = TaggedEqual(map, initial_map);
|
||||||
|
|
||||||
var_result.Bind(has_initialmap);
|
var_result = has_initialmap;
|
||||||
GotoIfNot(has_initialmap, &out);
|
GotoIfNot(has_initialmap, &out);
|
||||||
|
|
||||||
// The smi check is required to omit ToLength(lastIndex) calls with possible
|
// The smi check is required to omit ToLength(lastIndex) calls with possible
|
||||||
// user-code execution on the fast path.
|
// user-code execution on the fast path.
|
||||||
TNode<Object> last_index = FastLoadLastIndexBeforeSmiCheck(CAST(object));
|
TNode<Object> last_index = FastLoadLastIndexBeforeSmiCheck(CAST(object));
|
||||||
var_result.Bind(TaggedIsPositiveSmi(last_index));
|
var_result = TaggedIsPositiveSmi(last_index);
|
||||||
Goto(&out);
|
Goto(&out);
|
||||||
|
|
||||||
BIND(&out);
|
BIND(&out);
|
||||||
@ -984,8 +980,8 @@ TNode<BoolT> RegExpBuiltinsAssembler::IsFastRegExpWithOriginalExec(
|
|||||||
return var_result.value();
|
return var_result.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
Node* RegExpBuiltinsAssembler::IsFastRegExpNoPrototype(
|
TNode<BoolT> RegExpBuiltinsAssembler::IsFastRegExpNoPrototype(
|
||||||
SloppyTNode<Context> context, SloppyTNode<Object> object) {
|
TNode<Context> context, TNode<Object> object) {
|
||||||
CSA_ASSERT(this, TaggedIsNotSmi(object));
|
CSA_ASSERT(this, TaggedIsNotSmi(object));
|
||||||
return IsFastRegExpNoPrototype(context, object, LoadMap(CAST(object)));
|
return IsFastRegExpNoPrototype(context, object, LoadMap(CAST(object)));
|
||||||
}
|
}
|
||||||
@ -1060,10 +1056,9 @@ void RegExpBuiltinsAssembler::BranchIfFastRegExp_Permissive(
|
|||||||
if_isunmodified, if_ismodified);
|
if_isunmodified, if_ismodified);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RegExpBuiltinsAssembler::BranchIfFastRegExpResult(Node* const context,
|
void RegExpBuiltinsAssembler::BranchIfFastRegExpResult(
|
||||||
Node* const object,
|
const TNode<Context> context, const TNode<Object> object,
|
||||||
Label* if_isunmodified,
|
Label* if_isunmodified, Label* if_ismodified) {
|
||||||
Label* if_ismodified) {
|
|
||||||
// Could be a Smi.
|
// Could be a Smi.
|
||||||
TNode<Map> const map = LoadReceiverMap(object);
|
TNode<Map> const map = LoadReceiverMap(object);
|
||||||
|
|
||||||
@ -1260,7 +1255,7 @@ TNode<String> RegExpBuiltinsAssembler::FlagsGetter(TNode<Context> context,
|
|||||||
{
|
{
|
||||||
TNode<String> const result = AllocateSeqOneByteString(var_length.value());
|
TNode<String> const result = AllocateSeqOneByteString(var_length.value());
|
||||||
|
|
||||||
VARIABLE(var_offset, MachineType::PointerRepresentation(),
|
TVARIABLE(IntPtrT, var_offset,
|
||||||
IntPtrConstant(SeqOneByteString::kHeaderSize - kHeapObjectTag));
|
IntPtrConstant(SeqOneByteString::kHeaderSize - kHeapObjectTag));
|
||||||
|
|
||||||
#define CASE_FOR_FLAG(FLAG, CHAR) \
|
#define CASE_FOR_FLAG(FLAG, CHAR) \
|
||||||
@ -1270,7 +1265,7 @@ TNode<String> RegExpBuiltinsAssembler::FlagsGetter(TNode<Context> context,
|
|||||||
TNode<Int32T> const value = Int32Constant(CHAR); \
|
TNode<Int32T> const value = Int32Constant(CHAR); \
|
||||||
StoreNoWriteBarrier(MachineRepresentation::kWord8, result, \
|
StoreNoWriteBarrier(MachineRepresentation::kWord8, result, \
|
||||||
var_offset.value(), value); \
|
var_offset.value(), value); \
|
||||||
var_offset.Bind(IntPtrAdd(var_offset.value(), int_one)); \
|
var_offset = IntPtrAdd(var_offset.value(), int_one); \
|
||||||
Goto(&next); \
|
Goto(&next); \
|
||||||
BIND(&next); \
|
BIND(&next); \
|
||||||
} while (false)
|
} while (false)
|
||||||
@ -1339,12 +1334,9 @@ TNode<BoolT> RegExpBuiltinsAssembler::IsRegExp(TNode<Context> context,
|
|||||||
|
|
||||||
// ES#sec-regexpinitialize
|
// ES#sec-regexpinitialize
|
||||||
// Runtime Semantics: RegExpInitialize ( obj, pattern, flags )
|
// Runtime Semantics: RegExpInitialize ( obj, pattern, flags )
|
||||||
Node* RegExpBuiltinsAssembler::RegExpInitialize(Node* const context,
|
TNode<Object> RegExpBuiltinsAssembler::RegExpInitialize(
|
||||||
Node* const regexp,
|
const TNode<Context> context, const TNode<JSRegExp> regexp,
|
||||||
Node* const maybe_pattern,
|
const TNode<Object> maybe_pattern, const TNode<Object> maybe_flags) {
|
||||||
Node* const maybe_flags) {
|
|
||||||
CSA_ASSERT(this, IsJSRegExp(regexp));
|
|
||||||
|
|
||||||
// Normalize pattern.
|
// Normalize pattern.
|
||||||
TNode<Object> const pattern = Select<Object>(
|
TNode<Object> const pattern = Select<Object>(
|
||||||
IsUndefined(maybe_pattern), [=] { return EmptyStringConstant(); },
|
IsUndefined(maybe_pattern), [=] { return EmptyStringConstant(); },
|
||||||
@ -1451,7 +1443,7 @@ TF_BUILTIN(RegExpConstructor, RegExpBuiltinsAssembler) {
|
|||||||
|
|
||||||
// Allocate.
|
// Allocate.
|
||||||
|
|
||||||
VARIABLE(var_regexp, MachineRepresentation::kTagged);
|
TVARIABLE(JSRegExp, var_regexp);
|
||||||
{
|
{
|
||||||
Label allocate_jsregexp(this), allocate_generic(this, Label::kDeferred),
|
Label allocate_jsregexp(this), allocate_generic(this, Label::kDeferred),
|
||||||
next(this);
|
next(this);
|
||||||
@ -1462,25 +1454,23 @@ TF_BUILTIN(RegExpConstructor, RegExpBuiltinsAssembler) {
|
|||||||
{
|
{
|
||||||
TNode<Map> const initial_map = CAST(LoadObjectField(
|
TNode<Map> const initial_map = CAST(LoadObjectField(
|
||||||
regexp_function, JSFunction::kPrototypeOrInitialMapOffset));
|
regexp_function, JSFunction::kPrototypeOrInitialMapOffset));
|
||||||
TNode<JSObject> const regexp = AllocateJSObjectFromMap(initial_map);
|
var_regexp = CAST(AllocateJSObjectFromMap(initial_map));
|
||||||
var_regexp.Bind(regexp);
|
|
||||||
Goto(&next);
|
Goto(&next);
|
||||||
}
|
}
|
||||||
|
|
||||||
BIND(&allocate_generic);
|
BIND(&allocate_generic);
|
||||||
{
|
{
|
||||||
ConstructorBuiltinsAssembler constructor_assembler(this->state());
|
ConstructorBuiltinsAssembler constructor_assembler(this->state());
|
||||||
TNode<JSObject> const regexp = constructor_assembler.EmitFastNewObject(
|
var_regexp = CAST(constructor_assembler.EmitFastNewObject(
|
||||||
context, regexp_function, CAST(var_new_target.value()));
|
context, regexp_function, CAST(var_new_target.value())));
|
||||||
var_regexp.Bind(regexp);
|
|
||||||
Goto(&next);
|
Goto(&next);
|
||||||
}
|
}
|
||||||
|
|
||||||
BIND(&next);
|
BIND(&next);
|
||||||
}
|
}
|
||||||
|
|
||||||
Node* const result = RegExpInitialize(context, var_regexp.value(),
|
const TNode<Object> result = RegExpInitialize(
|
||||||
var_pattern.value(), var_flags.value());
|
context, var_regexp.value(), var_pattern.value(), var_flags.value());
|
||||||
Return(result);
|
Return(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1494,10 +1484,10 @@ TF_BUILTIN(RegExpPrototypeCompile, RegExpBuiltinsAssembler) {
|
|||||||
|
|
||||||
ThrowIfNotInstanceType(context, maybe_receiver, JS_REGEXP_TYPE,
|
ThrowIfNotInstanceType(context, maybe_receiver, JS_REGEXP_TYPE,
|
||||||
"RegExp.prototype.compile");
|
"RegExp.prototype.compile");
|
||||||
Node* const receiver = maybe_receiver;
|
const TNode<JSRegExp> receiver = CAST(maybe_receiver);
|
||||||
|
|
||||||
VARIABLE(var_flags, MachineRepresentation::kTagged, maybe_flags);
|
TVARIABLE(Object, var_flags, maybe_flags);
|
||||||
VARIABLE(var_pattern, MachineRepresentation::kTagged, maybe_pattern);
|
TVARIABLE(Object, var_pattern, maybe_pattern);
|
||||||
|
|
||||||
// Handle a JSRegExp pattern.
|
// Handle a JSRegExp pattern.
|
||||||
{
|
{
|
||||||
@ -1506,8 +1496,6 @@ TF_BUILTIN(RegExpPrototypeCompile, RegExpBuiltinsAssembler) {
|
|||||||
GotoIf(TaggedIsSmi(maybe_pattern), &next);
|
GotoIf(TaggedIsSmi(maybe_pattern), &next);
|
||||||
GotoIfNot(IsJSRegExp(CAST(maybe_pattern)), &next);
|
GotoIfNot(IsJSRegExp(CAST(maybe_pattern)), &next);
|
||||||
|
|
||||||
Node* const pattern = maybe_pattern;
|
|
||||||
|
|
||||||
// {maybe_flags} must be undefined in this case, otherwise throw.
|
// {maybe_flags} must be undefined in this case, otherwise throw.
|
||||||
{
|
{
|
||||||
Label next(this);
|
Label next(this);
|
||||||
@ -1518,19 +1506,20 @@ TF_BUILTIN(RegExpPrototypeCompile, RegExpBuiltinsAssembler) {
|
|||||||
BIND(&next);
|
BIND(&next);
|
||||||
}
|
}
|
||||||
|
|
||||||
TNode<String> const new_flags = FlagsGetter(context, CAST(pattern), true);
|
const TNode<JSRegExp> pattern = CAST(maybe_pattern);
|
||||||
|
TNode<String> const new_flags = FlagsGetter(context, pattern, true);
|
||||||
TNode<Object> const new_pattern =
|
TNode<Object> const new_pattern =
|
||||||
LoadObjectField(pattern, JSRegExp::kSourceOffset);
|
LoadObjectField(pattern, JSRegExp::kSourceOffset);
|
||||||
|
|
||||||
var_flags.Bind(new_flags);
|
var_flags = new_flags;
|
||||||
var_pattern.Bind(new_pattern);
|
var_pattern = new_pattern;
|
||||||
|
|
||||||
Goto(&next);
|
Goto(&next);
|
||||||
BIND(&next);
|
BIND(&next);
|
||||||
}
|
}
|
||||||
|
|
||||||
Node* const result = RegExpInitialize(context, receiver, var_pattern.value(),
|
const TNode<Object> result = RegExpInitialize(
|
||||||
var_flags.value());
|
context, receiver, var_pattern.value(), var_flags.value());
|
||||||
Return(result);
|
Return(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1601,8 +1590,9 @@ TNode<BoolT> RegExpBuiltinsAssembler::FlagGetter(TNode<Context> context,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ES#sec-regexpexec Runtime Semantics: RegExpExec ( R, S )
|
// ES#sec-regexpexec Runtime Semantics: RegExpExec ( R, S )
|
||||||
TNode<Object> RegExpBuiltinsAssembler::RegExpExec(TNode<Context> context,
|
TNode<Object> RegExpBuiltinsAssembler::RegExpExec(
|
||||||
Node* regexp, Node* string) {
|
TNode<Context> context, TNode<JSReceiver> maybe_regexp,
|
||||||
|
TNode<String> string) {
|
||||||
TVARIABLE(Object, var_result);
|
TVARIABLE(Object, var_result);
|
||||||
Label out(this);
|
Label out(this);
|
||||||
|
|
||||||
@ -1611,7 +1601,7 @@ TNode<Object> RegExpBuiltinsAssembler::RegExpExec(TNode<Context> context,
|
|||||||
|
|
||||||
// Get the exec property.
|
// Get the exec property.
|
||||||
TNode<Object> const exec =
|
TNode<Object> const exec =
|
||||||
GetProperty(context, regexp, isolate()->factory()->exec_string());
|
GetProperty(context, maybe_regexp, isolate()->factory()->exec_string());
|
||||||
|
|
||||||
// Is {exec} callable?
|
// Is {exec} callable?
|
||||||
Label if_iscallable(this), if_isnotcallable(this);
|
Label if_iscallable(this), if_isnotcallable(this);
|
||||||
@ -1624,7 +1614,8 @@ TNode<Object> RegExpBuiltinsAssembler::RegExpExec(TNode<Context> context,
|
|||||||
BIND(&if_iscallable);
|
BIND(&if_iscallable);
|
||||||
{
|
{
|
||||||
Callable call_callable = CodeFactory::Call(isolate());
|
Callable call_callable = CodeFactory::Call(isolate());
|
||||||
var_result = CAST(CallJS(call_callable, context, exec, regexp, string));
|
var_result =
|
||||||
|
CAST(CallJS(call_callable, context, exec, maybe_regexp, string));
|
||||||
|
|
||||||
GotoIf(IsNull(var_result.value()), &out);
|
GotoIf(IsNull(var_result.value()), &out);
|
||||||
|
|
||||||
@ -1636,11 +1627,11 @@ TNode<Object> RegExpBuiltinsAssembler::RegExpExec(TNode<Context> context,
|
|||||||
|
|
||||||
BIND(&if_isnotcallable);
|
BIND(&if_isnotcallable);
|
||||||
{
|
{
|
||||||
ThrowIfNotInstanceType(context, regexp, JS_REGEXP_TYPE,
|
ThrowIfNotInstanceType(context, maybe_regexp, JS_REGEXP_TYPE,
|
||||||
"RegExp.prototype.exec");
|
"RegExp.prototype.exec");
|
||||||
|
|
||||||
var_result = CallBuiltin(Builtins::kRegExpPrototypeExecSlow, context,
|
var_result = CallBuiltin(Builtins::kRegExpPrototypeExecSlow, context,
|
||||||
regexp, string);
|
maybe_regexp, string);
|
||||||
Goto(&out);
|
Goto(&out);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1731,7 +1722,7 @@ TNode<Object> RegExpBuiltinsAssembler::RegExpPrototypeMatchBody(
|
|||||||
{
|
{
|
||||||
var_result = is_fastpath ? RegExpPrototypeExecBody(context, CAST(regexp),
|
var_result = is_fastpath ? RegExpPrototypeExecBody(context, CAST(regexp),
|
||||||
string, true)
|
string, true)
|
||||||
: RegExpExec(context, regexp, string);
|
: RegExpExec(context, CAST(regexp), string);
|
||||||
Goto(&done);
|
Goto(&done);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1749,9 +1740,9 @@ TNode<Object> RegExpBuiltinsAssembler::RegExpPrototypeMatchBody(
|
|||||||
// Loop preparations. Within the loop, collect results from RegExpExec
|
// Loop preparations. Within the loop, collect results from RegExpExec
|
||||||
// and store match strings in the array.
|
// and store match strings in the array.
|
||||||
|
|
||||||
Variable* vars[] = {array.var_array(), array.var_length(),
|
Label loop(this,
|
||||||
array.var_capacity()};
|
{array.var_array(), array.var_length(), array.var_capacity()}),
|
||||||
Label loop(this, 3, vars), out(this);
|
out(this);
|
||||||
|
|
||||||
// Check if the regexp is an ATOM type. If then, keep the literal string to
|
// Check if the regexp is an ATOM type. If then, keep the literal string to
|
||||||
// search for so that we can avoid calling substring in the loop below.
|
// search for so that we can avoid calling substring in the loop below.
|
||||||
@ -1772,7 +1763,7 @@ TNode<Object> RegExpBuiltinsAssembler::RegExpPrototypeMatchBody(
|
|||||||
|
|
||||||
BIND(&loop);
|
BIND(&loop);
|
||||||
{
|
{
|
||||||
VARIABLE(var_match, MachineRepresentation::kTagged);
|
TVARIABLE(String, var_match);
|
||||||
|
|
||||||
Label if_didmatch(this), if_didnotmatch(this);
|
Label if_didmatch(this), if_didnotmatch(this);
|
||||||
if (is_fastpath) {
|
if (is_fastpath) {
|
||||||
@ -1790,24 +1781,24 @@ TNode<Object> RegExpBuiltinsAssembler::RegExpPrototypeMatchBody(
|
|||||||
match_indices, RegExpMatchInfo::kFirstCaptureIndex);
|
match_indices, RegExpMatchInfo::kFirstCaptureIndex);
|
||||||
TNode<Object> const match_to = UnsafeLoadFixedArrayElement(
|
TNode<Object> const match_to = UnsafeLoadFixedArrayElement(
|
||||||
match_indices, RegExpMatchInfo::kFirstCaptureIndex + 1);
|
match_indices, RegExpMatchInfo::kFirstCaptureIndex + 1);
|
||||||
var_match.Bind(CallBuiltin(Builtins::kSubString, context, string,
|
var_match = CAST(CallBuiltin(Builtins::kSubString, context, string,
|
||||||
match_from, match_to));
|
match_from, match_to));
|
||||||
Goto(&if_didmatch);
|
Goto(&if_didmatch);
|
||||||
}
|
}
|
||||||
|
|
||||||
BIND(&donotsubstring);
|
BIND(&donotsubstring);
|
||||||
var_match.Bind(var_search_string.value());
|
var_match = var_search_string.value();
|
||||||
Goto(&if_didmatch);
|
Goto(&if_didmatch);
|
||||||
} else {
|
} else {
|
||||||
DCHECK(!is_fastpath);
|
DCHECK(!is_fastpath);
|
||||||
TNode<Object> const result = RegExpExec(context, regexp, string);
|
TNode<Object> const result = RegExpExec(context, CAST(regexp), string);
|
||||||
|
|
||||||
Label load_match(this);
|
Label load_match(this);
|
||||||
Branch(IsNull(result), &if_didnotmatch, &load_match);
|
Branch(IsNull(result), &if_didnotmatch, &load_match);
|
||||||
|
|
||||||
BIND(&load_match);
|
BIND(&load_match);
|
||||||
var_match.Bind(
|
var_match =
|
||||||
ToString_Inline(context, GetProperty(context, result, SmiZero())));
|
ToString_Inline(context, GetProperty(context, result, SmiZero()));
|
||||||
Goto(&if_didmatch);
|
Goto(&if_didmatch);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1821,11 +1812,11 @@ TNode<Object> RegExpBuiltinsAssembler::RegExpPrototypeMatchBody(
|
|||||||
|
|
||||||
BIND(&if_didmatch);
|
BIND(&if_didmatch);
|
||||||
{
|
{
|
||||||
Node* match = var_match.value();
|
TNode<String> match = var_match.value();
|
||||||
|
|
||||||
// Store the match, growing the fixed array if needed.
|
// Store the match, growing the fixed array if needed.
|
||||||
|
|
||||||
array.Push(CAST(match));
|
array.Push(match);
|
||||||
|
|
||||||
// Advance last index if the match is the empty string.
|
// Advance last index if the match is the empty string.
|
||||||
|
|
||||||
@ -2113,11 +2104,9 @@ TNode<JSArray> RegExpBuiltinsAssembler::RegExpPrototypeSplitBody(
|
|||||||
TVARIABLE(Smi, var_last_matched_until, SmiZero());
|
TVARIABLE(Smi, var_last_matched_until, SmiZero());
|
||||||
TVARIABLE(Smi, var_next_search_from, SmiZero());
|
TVARIABLE(Smi, var_next_search_from, SmiZero());
|
||||||
|
|
||||||
Variable* vars[] = {array.var_array(), array.var_length(),
|
Label loop(this, {array.var_array(), array.var_length(), array.var_capacity(),
|
||||||
array.var_capacity(), &var_last_matched_until,
|
&var_last_matched_until, &var_next_search_from}),
|
||||||
&var_next_search_from};
|
push_suffix_and_out(this), out(this);
|
||||||
const int vars_count = sizeof(vars) / sizeof(vars[0]);
|
|
||||||
Label loop(this, vars_count, vars), push_suffix_and_out(this), out(this);
|
|
||||||
Goto(&loop);
|
Goto(&loop);
|
||||||
|
|
||||||
BIND(&loop);
|
BIND(&loop);
|
||||||
@ -2194,19 +2183,18 @@ TNode<JSArray> RegExpBuiltinsAssembler::RegExpPrototypeSplitBody(
|
|||||||
match_indices, RegExpMatchInfo::kNumberOfCapturesIndex));
|
match_indices, RegExpMatchInfo::kNumberOfCapturesIndex));
|
||||||
TNode<IntPtrT> const int_num_registers = SmiUntag(num_registers);
|
TNode<IntPtrT> const int_num_registers = SmiUntag(num_registers);
|
||||||
|
|
||||||
VARIABLE(var_reg, MachineType::PointerRepresentation());
|
TVARIABLE(IntPtrT, var_reg, IntPtrConstant(2));
|
||||||
var_reg.Bind(IntPtrConstant(2));
|
|
||||||
|
|
||||||
Variable* vars[] = {array.var_array(), array.var_length(),
|
VariableList vars({array.var_array(), array.var_length(),
|
||||||
array.var_capacity(), &var_reg};
|
array.var_capacity(), &var_reg},
|
||||||
const int vars_count = sizeof(vars) / sizeof(vars[0]);
|
zone());
|
||||||
Label nested_loop(this, vars_count, vars), nested_loop_out(this);
|
Label nested_loop(this, vars), nested_loop_out(this);
|
||||||
Branch(IntPtrLessThan(var_reg.value(), int_num_registers), &nested_loop,
|
Branch(IntPtrLessThan(var_reg.value(), int_num_registers), &nested_loop,
|
||||||
&nested_loop_out);
|
&nested_loop_out);
|
||||||
|
|
||||||
BIND(&nested_loop);
|
BIND(&nested_loop);
|
||||||
{
|
{
|
||||||
Node* const reg = var_reg.value();
|
const TNode<IntPtrT> reg = var_reg.value();
|
||||||
TNode<Object> const from = LoadFixedArrayElement(
|
TNode<Object> const from = LoadFixedArrayElement(
|
||||||
match_indices, reg,
|
match_indices, reg,
|
||||||
RegExpMatchInfo::kFirstCaptureIndex * kTaggedSize, mode);
|
RegExpMatchInfo::kFirstCaptureIndex * kTaggedSize, mode);
|
||||||
@ -2215,30 +2203,30 @@ TNode<JSArray> RegExpBuiltinsAssembler::RegExpPrototypeSplitBody(
|
|||||||
(RegExpMatchInfo::kFirstCaptureIndex + 1) * kTaggedSize, mode));
|
(RegExpMatchInfo::kFirstCaptureIndex + 1) * kTaggedSize, mode));
|
||||||
|
|
||||||
Label select_capture(this), select_undefined(this), store_value(this);
|
Label select_capture(this), select_undefined(this), store_value(this);
|
||||||
VARIABLE(var_value, MachineRepresentation::kTagged);
|
TVARIABLE(Object, var_value);
|
||||||
Branch(SmiEqual(to, SmiConstant(-1)), &select_undefined,
|
Branch(SmiEqual(to, SmiConstant(-1)), &select_undefined,
|
||||||
&select_capture);
|
&select_capture);
|
||||||
|
|
||||||
BIND(&select_capture);
|
BIND(&select_capture);
|
||||||
{
|
{
|
||||||
var_value.Bind(
|
var_value =
|
||||||
CallBuiltin(Builtins::kSubString, context, string, from, to));
|
CallBuiltin(Builtins::kSubString, context, string, from, to);
|
||||||
Goto(&store_value);
|
Goto(&store_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
BIND(&select_undefined);
|
BIND(&select_undefined);
|
||||||
{
|
{
|
||||||
var_value.Bind(UndefinedConstant());
|
var_value = UndefinedConstant();
|
||||||
Goto(&store_value);
|
Goto(&store_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
BIND(&store_value);
|
BIND(&store_value);
|
||||||
{
|
{
|
||||||
array.Push(CAST(var_value.value()));
|
array.Push(var_value.value());
|
||||||
GotoIf(WordEqual(array.length(), int_limit), &out);
|
GotoIf(WordEqual(array.length(), int_limit), &out);
|
||||||
|
|
||||||
TNode<WordT> const new_reg = IntPtrAdd(reg, IntPtrConstant(2));
|
const TNode<IntPtrT> new_reg = IntPtrAdd(reg, IntPtrConstant(2));
|
||||||
var_reg.Bind(new_reg);
|
var_reg = new_reg;
|
||||||
|
|
||||||
Branch(IntPtrLessThan(new_reg, int_num_registers), &nested_loop,
|
Branch(IntPtrLessThan(new_reg, int_num_registers), &nested_loop,
|
||||||
&nested_loop_out);
|
&nested_loop_out);
|
||||||
@ -2255,8 +2243,8 @@ TNode<JSArray> RegExpBuiltinsAssembler::RegExpPrototypeSplitBody(
|
|||||||
|
|
||||||
BIND(&push_suffix_and_out);
|
BIND(&push_suffix_and_out);
|
||||||
{
|
{
|
||||||
TNode<Smi> const from = var_last_matched_until.value();
|
const TNode<Smi> from = var_last_matched_until.value();
|
||||||
Node* const to = string_length;
|
const TNode<Smi> to = string_length;
|
||||||
array.Push(CallBuiltin(Builtins::kSubString, context, string, from, to));
|
array.Push(CallBuiltin(Builtins::kSubString, context, string, from, to));
|
||||||
Goto(&out);
|
Goto(&out);
|
||||||
}
|
}
|
||||||
|
@ -139,17 +139,17 @@ class RegExpBuiltinsAssembler : public CodeStubAssembler {
|
|||||||
|
|
||||||
// Performs fast path checks on the given object itself, but omits prototype
|
// Performs fast path checks on the given object itself, but omits prototype
|
||||||
// checks.
|
// checks.
|
||||||
Node* IsFastRegExpNoPrototype(SloppyTNode<Context> context,
|
TNode<BoolT> IsFastRegExpNoPrototype(TNode<Context> context,
|
||||||
SloppyTNode<Object> object);
|
TNode<Object> object);
|
||||||
Node* IsFastRegExpNoPrototype(SloppyTNode<Context> context,
|
TNode<BoolT> IsFastRegExpNoPrototype(TNode<Context> context,
|
||||||
SloppyTNode<Object> object,
|
TNode<Object> object, TNode<Map> map);
|
||||||
SloppyTNode<Map> map);
|
|
||||||
|
|
||||||
// For debugging only. Uses a slow GetProperty call to fetch object.exec.
|
// For debugging only. Uses a slow GetProperty call to fetch object.exec.
|
||||||
TNode<BoolT> IsFastRegExpWithOriginalExec(TNode<Context> context,
|
TNode<BoolT> IsFastRegExpWithOriginalExec(TNode<Context> context,
|
||||||
TNode<JSRegExp> object);
|
TNode<JSRegExp> object);
|
||||||
|
|
||||||
void BranchIfFastRegExpResult(Node* const context, Node* const object,
|
void BranchIfFastRegExpResult(const TNode<Context> context,
|
||||||
|
const TNode<Object> object,
|
||||||
Label* if_isunmodified, Label* if_ismodified);
|
Label* if_isunmodified, Label* if_ismodified);
|
||||||
|
|
||||||
TNode<String> FlagsGetter(TNode<Context> context, TNode<Object> regexp,
|
TNode<String> FlagsGetter(TNode<Context> context, TNode<Object> regexp,
|
||||||
@ -167,10 +167,14 @@ class RegExpBuiltinsAssembler : public CodeStubAssembler {
|
|||||||
TNode<BoolT> FlagGetter(TNode<Context> context, TNode<Object> regexp,
|
TNode<BoolT> FlagGetter(TNode<Context> context, TNode<Object> regexp,
|
||||||
JSRegExp::Flag flag, bool is_fastpath);
|
JSRegExp::Flag flag, bool is_fastpath);
|
||||||
|
|
||||||
Node* RegExpInitialize(Node* const context, Node* const regexp,
|
TNode<Object> RegExpInitialize(const TNode<Context> context,
|
||||||
Node* const maybe_pattern, Node* const maybe_flags);
|
const TNode<JSRegExp> regexp,
|
||||||
|
const TNode<Object> maybe_pattern,
|
||||||
|
const TNode<Object> maybe_flags);
|
||||||
|
|
||||||
TNode<Object> RegExpExec(TNode<Context> context, Node* regexp, Node* string);
|
TNode<Object> RegExpExec(TNode<Context> context,
|
||||||
|
TNode<JSReceiver> maybe_regexp,
|
||||||
|
TNode<String> string);
|
||||||
|
|
||||||
TNode<Number> AdvanceStringIndex(SloppyTNode<String> string,
|
TNode<Number> AdvanceStringIndex(SloppyTNode<String> string,
|
||||||
SloppyTNode<Number> index,
|
SloppyTNode<Number> index,
|
||||||
|
@ -22,7 +22,7 @@ namespace regexp {
|
|||||||
BranchIfFastRegExp_Permissive(o) otherwise return true, return false;
|
BranchIfFastRegExp_Permissive(o) otherwise return true, return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern macro RegExpBuiltinsAssembler::RegExpExec(Context, JSAny, JSAny):
|
extern macro RegExpBuiltinsAssembler::RegExpExec(Context, JSReceiver, String):
|
||||||
JSAny;
|
JSAny;
|
||||||
|
|
||||||
extern macro
|
extern macro
|
||||||
|
Loading…
Reference in New Issue
Block a user