Commit 06eef6e6 authored by bmeurer's avatar bmeurer Committed by Commit bot

[stubs] Don't unconditionally canonicalize in ChangeFloat64ToTagged.

Add a CanonicalizationMode to CodeStubAssembler::ChangeFloat64ToTagged,
so clients can request Smi canonicalization when desired, but otherwise
get Crankshaft/Fullcodegen compatible behavior of just boxing the double
into a HeapNumber.

R=verwaest@chromium.org
BUG=v8:5268

Review-Url: https://codereview.chromium.org/2380543002
Cr-Commit-Position: refs/heads/master@{#39804}
parent 19b39436
......@@ -1870,53 +1870,64 @@ Node* CodeStubAssembler::TruncateHeapNumberValueToWord32(Node* object) {
return TruncateFloat64ToWord32(value);
}
Node* CodeStubAssembler::ChangeFloat64ToTagged(Node* value) {
Node* value32 = RoundFloat64ToInt32(value);
Node* value64 = ChangeInt32ToFloat64(value32);
Label if_valueisint32(this), if_valueisheapnumber(this), if_join(this);
Node* CodeStubAssembler::ChangeFloat64ToTagged(Node* value,
CanonicalizationMode mode) {
switch (mode) {
case CanonicalizationMode::kDontCanonicalize: {
return AllocateHeapNumberWithValue(value);
}
case CanonicalizationMode::kCanonicalize: {
Node* value32 = RoundFloat64ToInt32(value);
Node* value64 = ChangeInt32ToFloat64(value32);
Label if_valueisequal(this), if_valueisnotequal(this);
Branch(Float64Equal(value, value64), &if_valueisequal, &if_valueisnotequal);
Bind(&if_valueisequal);
{
GotoUnless(Word32Equal(value32, Int32Constant(0)), &if_valueisint32);
BranchIfInt32LessThan(Float64ExtractHighWord32(value), Int32Constant(0),
&if_valueisheapnumber, &if_valueisint32);
}
Bind(&if_valueisnotequal);
Goto(&if_valueisheapnumber);
Label if_valueisint32(this), if_valueisheapnumber(this), if_join(this);
Variable var_result(this, MachineRepresentation::kTagged);
Bind(&if_valueisint32);
{
if (Is64()) {
Node* result = SmiTag(ChangeInt32ToInt64(value32));
var_result.Bind(result);
Goto(&if_join);
} else {
Node* pair = Int32AddWithOverflow(value32, value32);
Node* overflow = Projection(1, pair);
Label if_overflow(this, Label::kDeferred), if_notoverflow(this);
Branch(overflow, &if_overflow, &if_notoverflow);
Bind(&if_overflow);
Label if_valueisequal(this), if_valueisnotequal(this);
Branch(Float64Equal(value, value64), &if_valueisequal,
&if_valueisnotequal);
Bind(&if_valueisequal);
{
GotoUnless(Word32Equal(value32, Int32Constant(0)), &if_valueisint32);
BranchIfInt32LessThan(Float64ExtractHighWord32(value), Int32Constant(0),
&if_valueisheapnumber, &if_valueisint32);
}
Bind(&if_valueisnotequal);
Goto(&if_valueisheapnumber);
Bind(&if_notoverflow);
Variable var_result(this, MachineRepresentation::kTagged);
Bind(&if_valueisint32);
{
if (Is64()) {
Node* result = SmiTag(ChangeInt32ToInt64(value32));
var_result.Bind(result);
Goto(&if_join);
} else {
Node* pair = Int32AddWithOverflow(value32, value32);
Node* overflow = Projection(1, pair);
Label if_overflow(this, Label::kDeferred), if_notoverflow(this);
Branch(overflow, &if_overflow, &if_notoverflow);
Bind(&if_overflow);
Goto(&if_valueisheapnumber);
Bind(&if_notoverflow);
{
Node* result = Projection(0, pair);
var_result.Bind(result);
Goto(&if_join);
}
}
}
Bind(&if_valueisheapnumber);
{
Node* result = Projection(0, pair);
Node* result = AllocateHeapNumberWithValue(value);
var_result.Bind(result);
Goto(&if_join);
}
Bind(&if_join);
return var_result.value();
}
}
Bind(&if_valueisheapnumber);
{
Node* result = AllocateHeapNumberWithValue(value);
var_result.Bind(result);
Goto(&if_join);
}
Bind(&if_join);
return var_result.value();
UNREACHABLE();
return nullptr;
}
Node* CodeStubAssembler::ChangeInt32ToTagged(Node* value) {
......@@ -2632,12 +2643,21 @@ 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);
// Perform optional minus zero truncation.
switch (mode) {
case kNoTruncation:
break;
case kTruncateMinusZero: {
// Truncate -0.0 to 0.
GotoIf(Float64Equal(value, Float64Constant(0.0)), &return_zero);
break;
}
}
var_arg.Bind(ChangeFloat64ToTagged(value));
// Tag the {value} using Smi canonicalization, i.e. if {value} can be
// represented as a Smi, then this will produce a Smi.
var_arg.Bind(
ChangeFloat64ToTagged(value, CanonicalizationMode::kCanonicalize));
Goto(&out);
}
......
......@@ -17,6 +17,7 @@ class CallInterfaceDescriptor;
class StatsCounter;
class StubCache;
enum class CanonicalizationMode { kDontCanonicalize, kCanonicalize };
enum class PrimitiveType { kBoolean, kNumber, kString, kSymbol };
enum class UnicodeEncoding {
......@@ -427,7 +428,11 @@ class CodeStubAssembler : public compiler::CodeAssembler {
compiler::Node* TruncateHeapNumberValueToWord32(compiler::Node* object);
// Conversions.
compiler::Node* ChangeFloat64ToTagged(compiler::Node* value);
// Returns a tagged representation of the float64 {value}. Might optionally
// try to canonicalize to Smi representation if the {value} is in Smi range.
compiler::Node* ChangeFloat64ToTagged(
compiler::Node* value,
CanonicalizationMode mode = CanonicalizationMode::kDontCanonicalize);
compiler::Node* ChangeInt32ToTagged(compiler::Node* value);
compiler::Node* ChangeUint32ToTagged(compiler::Node* value);
......
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