Commit 693276a4 authored by jgruber's avatar jgruber Committed by Commit bot

[stubs] Add TruncationMode argument to ToInteger

Passing kTruncateMinusZero truncates -0.0 to Smi 0, while kNoTruncation returns
-0.0 as a heap number.

BUG=

Review-Url: https://codereview.chromium.org/2361363002
Cr-Commit-Position: refs/heads/master@{#39710}
parent 22606f0c
......@@ -294,7 +294,6 @@ BUILTIN(StringFromCodePoint) {
void Builtins::Generate_StringPrototypeCharAt(CodeStubAssembler* assembler) {
typedef CodeStubAssembler::Label Label;
typedef compiler::Node Node;
typedef CodeStubAssembler::Variable Variable;
Node* receiver = assembler->Parameter(0);
Node* position = assembler->Parameter(1);
......@@ -306,72 +305,24 @@ void Builtins::Generate_StringPrototypeCharAt(CodeStubAssembler* assembler) {
// Convert the {position} to a Smi and check that it's in bounds of the
// {receiver}.
// TODO(bmeurer): Find an abstraction for this!
{
// Check if the {position} is already a Smi.
Variable var_position(assembler, MachineRepresentation::kTagged);
var_position.Bind(position);
Label if_positionissmi(assembler),
if_positionisnotsmi(assembler, Label::kDeferred);
assembler->Branch(assembler->WordIsSmi(position), &if_positionissmi,
&if_positionisnotsmi);
assembler->Bind(&if_positionisnotsmi);
{
// Convert the {position} to an Integer via the ToIntegerStub.
Node* index = assembler->ToInteger(context, position);
// Check if the resulting {index} is now a Smi.
Label if_indexissmi(assembler, Label::kDeferred),
if_indexisnotsmi(assembler, Label::kDeferred);
assembler->Branch(assembler->WordIsSmi(index), &if_indexissmi,
&if_indexisnotsmi);
assembler->Bind(&if_indexissmi);
{
var_position.Bind(index);
assembler->Goto(&if_positionissmi);
}
assembler->Bind(&if_indexisnotsmi);
{
// The ToIntegerStub canonicalizes everything in Smi range to Smi
// representation, so any HeapNumber returned is not in Smi range.
// The only exception here is -0.0, which we treat as 0.
Node* index_value = assembler->LoadHeapNumberValue(index);
Label if_indexiszero(assembler, Label::kDeferred),
if_indexisnotzero(assembler, Label::kDeferred);
assembler->Branch(assembler->Float64Equal(
index_value, assembler->Float64Constant(0.0)),
&if_indexiszero, &if_indexisnotzero);
assembler->Bind(&if_indexiszero);
{
var_position.Bind(assembler->SmiConstant(Smi::FromInt(0)));
assembler->Goto(&if_positionissmi);
}
assembler->Bind(&if_indexisnotzero);
{
// The {index} is some other integral Number, that is definitely
// neither -0.0 nor in Smi range.
assembler->Return(assembler->EmptyStringConstant());
}
}
}
assembler->Bind(&if_positionissmi);
position = var_position.value();
Label return_emptystring(assembler, Label::kDeferred);
position = assembler->ToInteger(context, position,
CodeStubAssembler::kTruncateMinusZero);
assembler->GotoUnless(assembler->WordIsSmi(position), &return_emptystring);
// Determine the actual length of the {receiver} String.
Node* receiver_length =
assembler->LoadObjectField(receiver, String::kLengthOffset);
// Return "" if the Smi {position} is outside the bounds of the {receiver}.
Label if_positioninbounds(assembler),
if_positionnotinbounds(assembler, Label::kDeferred);
Label if_positioninbounds(assembler);
assembler->Branch(assembler->SmiAboveOrEqual(position, receiver_length),
&if_positionnotinbounds, &if_positioninbounds);
assembler->Bind(&if_positionnotinbounds);
&return_emptystring, &if_positioninbounds);
assembler->Bind(&return_emptystring);
assembler->Return(assembler->EmptyStringConstant());
assembler->Bind(&if_positioninbounds);
}
......@@ -388,7 +339,6 @@ void Builtins::Generate_StringPrototypeCharCodeAt(
CodeStubAssembler* assembler) {
typedef CodeStubAssembler::Label Label;
typedef compiler::Node Node;
typedef CodeStubAssembler::Variable Variable;
Node* receiver = assembler->Parameter(0);
Node* position = assembler->Parameter(1);
......@@ -400,72 +350,24 @@ void Builtins::Generate_StringPrototypeCharCodeAt(
// Convert the {position} to a Smi and check that it's in bounds of the
// {receiver}.
// TODO(bmeurer): Find an abstraction for this!
{
// Check if the {position} is already a Smi.
Variable var_position(assembler, MachineRepresentation::kTagged);
var_position.Bind(position);
Label if_positionissmi(assembler),
if_positionisnotsmi(assembler, Label::kDeferred);
assembler->Branch(assembler->WordIsSmi(position), &if_positionissmi,
&if_positionisnotsmi);
assembler->Bind(&if_positionisnotsmi);
{
// Convert the {position} to an Integer via the ToIntegerStub.
Node* index = assembler->ToInteger(context, position);
// Check if the resulting {index} is now a Smi.
Label if_indexissmi(assembler, Label::kDeferred),
if_indexisnotsmi(assembler, Label::kDeferred);
assembler->Branch(assembler->WordIsSmi(index), &if_indexissmi,
&if_indexisnotsmi);
assembler->Bind(&if_indexissmi);
{
var_position.Bind(index);
assembler->Goto(&if_positionissmi);
}
assembler->Bind(&if_indexisnotsmi);
{
// The ToIntegerStub canonicalizes everything in Smi range to Smi
// representation, so any HeapNumber returned is not in Smi range.
// The only exception here is -0.0, which we treat as 0.
Node* index_value = assembler->LoadHeapNumberValue(index);
Label if_indexiszero(assembler, Label::kDeferred),
if_indexisnotzero(assembler, Label::kDeferred);
assembler->Branch(assembler->Float64Equal(
index_value, assembler->Float64Constant(0.0)),
&if_indexiszero, &if_indexisnotzero);
assembler->Bind(&if_indexiszero);
{
var_position.Bind(assembler->SmiConstant(Smi::FromInt(0)));
assembler->Goto(&if_positionissmi);
}
assembler->Bind(&if_indexisnotzero);
{
// The {index} is some other integral Number, that is definitely
// neither -0.0 nor in Smi range.
assembler->Return(assembler->NaNConstant());
}
}
}
assembler->Bind(&if_positionissmi);
position = var_position.value();
Label return_nan(assembler, Label::kDeferred);
position = assembler->ToInteger(context, position,
CodeStubAssembler::kTruncateMinusZero);
assembler->GotoUnless(assembler->WordIsSmi(position), &return_nan);
// Determine the actual length of the {receiver} String.
Node* receiver_length =
assembler->LoadObjectField(receiver, String::kLengthOffset);
// Return NaN if the Smi {position} is outside the bounds of the {receiver}.
Label if_positioninbounds(assembler),
if_positionnotinbounds(assembler, Label::kDeferred);
Label if_positioninbounds(assembler);
assembler->Branch(assembler->SmiAboveOrEqual(position, receiver_length),
&if_positionnotinbounds, &if_positioninbounds);
assembler->Bind(&if_positionnotinbounds);
&return_nan, &if_positioninbounds);
assembler->Bind(&return_nan);
assembler->Return(assembler->NaNConstant());
assembler->Bind(&if_positioninbounds);
}
......
......@@ -2985,7 +2985,8 @@ Node* CodeStubAssembler::ToNumber(Node* context, Node* input) {
return var_result.value();
}
Node* CodeStubAssembler::ToInteger(Node* context, Node* input) {
Node* CodeStubAssembler::ToInteger(Node* context, Node* input,
ToIntegerTruncationMode mode) {
// We might need to loop once for ToNumber conversion.
Variable var_arg(this, MachineRepresentation::kTagged);
Label loop(this, &var_arg), out(this);
......@@ -3018,6 +3019,12 @@ Node* CodeStubAssembler::ToInteger(Node* context, Node* input) {
// Truncate {arg} towards zero.
Node* value = Float64Trunc(arg_value);
if (mode == kTruncateMinusZero) {
// Truncate -0.0 to 0.
GotoIf(Float64Equal(value, Float64Constant(0.0)), &return_zero);
}
var_arg.Bind(ChangeFloat64ToTagged(value));
Goto(&out);
}
......
......@@ -489,8 +489,14 @@ class CodeStubAssembler : public compiler::CodeAssembler {
// Convert any object to a Number.
compiler::Node* ToNumber(compiler::Node* context, compiler::Node* input);
enum ToIntegerTruncationMode {
kNoTruncation,
kTruncateMinusZero,
};
// Convert any object to an Integer.
compiler::Node* ToInteger(compiler::Node* context, compiler::Node* input);
compiler::Node* ToInteger(compiler::Node* context, compiler::Node* input,
ToIntegerTruncationMode mode = kNoTruncation);
// Returns a node that contains a decoded (unsigned!) value of a bit
// field |T| in |word32|. Returns result as an uint32 node.
......
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