@@ -3327,6 +3327,8 @@ Reduction JSCallReducer::ReduceJSCall(Node* node,
33273327 simplified ()->StringCodePointAt (UnicodeEncoding::UTF32), node);
33283328 case Builtins::kStringPrototypeSubstring :
33293329 return ReduceStringPrototypeSubstring (node);
3330+ case Builtins::kStringPrototypeSlice :
3331+ return ReduceStringPrototypeSlice (node);
33303332#ifdef V8_INTL_SUPPORT
33313333 case Builtins::kStringPrototypeToLowerCaseIntl :
33323334 return ReduceStringPrototypeToLowerCaseIntl (node);
@@ -3612,8 +3614,7 @@ Reduction JSCallReducer::ReduceJSConstruct(Node* node) {
36123614 return NoChange ();
36133615}
36143616
3615- // ES6 String.prototype.indexOf(searchString [, position])
3616- // #sec-string.prototype.indexof
3617+ // ES #sec-string.prototype.indexof
36173618Reduction JSCallReducer::ReduceStringPrototypeIndexOf (Node* node) {
36183619 DCHECK_EQ (IrOpcode::kJSCall , node->opcode ());
36193620 CallParameters const & p = CallParametersOf (node->op ());
@@ -3652,7 +3653,7 @@ Reduction JSCallReducer::ReduceStringPrototypeIndexOf(Node* node) {
36523653 return NoChange ();
36533654}
36543655
3655- // #sec-string.prototype.substring
3656+ // ES #sec-string.prototype.substring
36563657Reduction JSCallReducer::ReduceStringPrototypeSubstring (Node* node) {
36573658 if (node->op ()->ValueInputCount () < 3 ) return NoChange ();
36583659 CallParameters const & p = CallParametersOf (node->op ());
@@ -3715,6 +3716,108 @@ Reduction JSCallReducer::ReduceStringPrototypeSubstring(Node* node) {
37153716 return Replace (value);
37163717}
37173718
3719+ // ES #sec-string.prototype.slice
3720+ Reduction JSCallReducer::ReduceStringPrototypeSlice (Node* node) {
3721+ if (node->op ()->ValueInputCount () < 3 ) return NoChange ();
3722+ CallParameters const & p = CallParametersOf (node->op ());
3723+ if (p.speculation_mode () == SpeculationMode::kDisallowSpeculation ) {
3724+ return NoChange ();
3725+ }
3726+
3727+ Node* effect = NodeProperties::GetEffectInput (node);
3728+ Node* control = NodeProperties::GetControlInput (node);
3729+ Node* receiver = NodeProperties::GetValueInput (node, 1 );
3730+ Node* start = NodeProperties::GetValueInput (node, 2 );
3731+ Node* end = node->op ()->ValueInputCount () > 3
3732+ ? NodeProperties::GetValueInput (node, 3 )
3733+ : jsgraph ()->UndefinedConstant ();
3734+
3735+ receiver = effect = graph ()->NewNode (simplified ()->CheckString (p.feedback ()),
3736+ receiver, effect, control);
3737+
3738+ start = effect = graph ()->NewNode (simplified ()->CheckSmi (p.feedback ()), start,
3739+ effect, control);
3740+
3741+ Node* length = graph ()->NewNode (simplified ()->StringLength (), receiver);
3742+
3743+ // Replace {end} argument with {length} if it is undefined.
3744+ {
3745+ Node* check = graph ()->NewNode (simplified ()->ReferenceEqual (), end,
3746+ jsgraph ()->UndefinedConstant ());
3747+
3748+ Node* branch =
3749+ graph ()->NewNode (common ()->Branch (BranchHint::kFalse ), check, control);
3750+
3751+ Node* if_true = graph ()->NewNode (common ()->IfTrue (), branch);
3752+ Node* etrue = effect;
3753+ Node* vtrue = length;
3754+
3755+ Node* if_false = graph ()->NewNode (common ()->IfFalse (), branch);
3756+ Node* efalse = effect;
3757+ Node* vfalse = efalse = graph ()->NewNode (
3758+ simplified ()->CheckSmi (p.feedback ()), end, efalse, if_false);
3759+
3760+ control = graph ()->NewNode (common ()->Merge (2 ), if_true, if_false);
3761+ effect = graph ()->NewNode (common ()->EffectPhi (2 ), etrue, efalse, control);
3762+ end = graph ()->NewNode (common ()->Phi (MachineRepresentation::kTagged , 2 ),
3763+ vtrue, vfalse, control);
3764+ }
3765+
3766+ Node* from = graph ()->NewNode (
3767+ common ()->Select (MachineRepresentation::kTagged , BranchHint::kFalse ),
3768+ graph ()->NewNode (simplified ()->NumberLessThan (), start,
3769+ jsgraph ()->ZeroConstant ()),
3770+ graph ()->NewNode (
3771+ simplified ()->NumberMax (),
3772+ graph ()->NewNode (simplified ()->NumberAdd (), length, start),
3773+ jsgraph ()->ZeroConstant ()),
3774+ graph ()->NewNode (simplified ()->NumberMin (), start, length));
3775+ // {from} is always in non-negative Smi range, but our typer cannot
3776+ // figure that out yet.
3777+ from = effect = graph ()->NewNode (common ()->TypeGuard (Type::UnsignedSmall ()),
3778+ from, effect, control);
3779+
3780+ Node* to = graph ()->NewNode (
3781+ common ()->Select (MachineRepresentation::kTagged , BranchHint::kFalse ),
3782+ graph ()->NewNode (simplified ()->NumberLessThan (), end,
3783+ jsgraph ()->ZeroConstant ()),
3784+ graph ()->NewNode (simplified ()->NumberMax (),
3785+ graph ()->NewNode (simplified ()->NumberAdd (), length, end),
3786+ jsgraph ()->ZeroConstant ()),
3787+ graph ()->NewNode (simplified ()->NumberMin (), end, length));
3788+ // {to} is always in non-negative Smi range, but our typer cannot
3789+ // figure that out yet.
3790+ to = effect = graph ()->NewNode (common ()->TypeGuard (Type::UnsignedSmall ()), to,
3791+ effect, control);
3792+
3793+ Node* result_string = nullptr ;
3794+ // Return empty string if {from} is smaller than {to}.
3795+ {
3796+ Node* check = graph ()->NewNode (simplified ()->NumberLessThan (), from, to);
3797+
3798+ Node* branch =
3799+ graph ()->NewNode (common ()->Branch (BranchHint::kTrue ), check, control);
3800+
3801+ Node* if_true = graph ()->NewNode (common ()->IfTrue (), branch);
3802+ Node* etrue = effect;
3803+ Node* vtrue = etrue = graph ()->NewNode (simplified ()->StringSubstring (),
3804+ receiver, from, to, etrue, if_true);
3805+
3806+ Node* if_false = graph ()->NewNode (common ()->IfFalse (), branch);
3807+ Node* efalse = effect;
3808+ Node* vfalse = jsgraph ()->EmptyStringConstant ();
3809+
3810+ control = graph ()->NewNode (common ()->Merge (2 ), if_true, if_false);
3811+ effect = graph ()->NewNode (common ()->EffectPhi (2 ), etrue, efalse, control);
3812+ result_string =
3813+ graph ()->NewNode (common ()->Phi (MachineRepresentation::kTagged , 2 ),
3814+ vtrue, vfalse, control);
3815+ }
3816+
3817+ ReplaceWithValue (node, result_string, effect, control);
3818+ return Replace (result_string);
3819+ }
3820+
37183821Reduction JSCallReducer::ReduceJSConstructWithArrayLike (Node* node) {
37193822 DCHECK_EQ (IrOpcode::kJSConstructWithArrayLike , node->opcode ());
37203823 CallFrequency frequency = CallFrequencyOf (node->op ());
0 commit comments