| Index: src/compiler/code-stub-assembler.cc
|
| diff --git a/src/compiler/code-stub-assembler.cc b/src/compiler/code-stub-assembler.cc
|
| index 2df4a910ae4b938890f302f60dd01067fd9f1bba..2327ac66b9a2c75104ca387c6938169623431bc0 100644
|
| --- a/src/compiler/code-stub-assembler.cc
|
| +++ b/src/compiler/code-stub-assembler.cc
|
| @@ -152,6 +152,113 @@ Node* CodeStubAssembler::SmiShiftBitsConstant() {
|
| return IntPtrConstant(kSmiShiftSize + kSmiTagSize);
|
| }
|
|
|
| +Node* CodeStubAssembler::Float64Floor(Node* x) {
|
| + if (raw_assembler_->machine()->Float64RoundDown().IsSupported()) {
|
| + return raw_assembler_->Float64RoundDown(x);
|
| + }
|
| +
|
| + Node* two_52 = Float64Constant(4503599627370496.0E0);
|
| + Node* minus_two_52 = Float64Constant(-4503599627370496.0E0);
|
| +
|
| + Variable var_x(this, MachineRepresentation::kFloat64);
|
| + var_x.Bind(x);
|
| +
|
| + Label return_x(this);
|
| +
|
| + // Check if {x} is a large positive integer.
|
| + Label if_xlargeposint(this), if_xnotlargeposint(this);
|
| + Branch(Float64GreaterThanOrEqual(x, two_52), &if_xlargeposint,
|
| + &if_xnotlargeposint);
|
| +
|
| + Bind(&if_xlargeposint);
|
| + {
|
| + // The {x} is already an even integer.
|
| + Goto(&return_x);
|
| + }
|
| +
|
| + Bind(&if_xnotlargeposint);
|
| + {
|
| + // Check if {x} is negative.
|
| + Label if_xnegative(this), if_xpositive(this);
|
| + Branch(Float64LessThan(x, Float64Constant(0.0)), &if_xnegative,
|
| + &if_xpositive);
|
| +
|
| + Bind(&if_xnegative);
|
| + {
|
| + // Check if {x} is a large negative integer.
|
| + Label if_xlargenegint(this), if_xnotlargenegint(this);
|
| + Branch(Float64LessThanOrEqual(x, minus_two_52), &if_xlargenegint,
|
| + &if_xnotlargenegint);
|
| +
|
| + Bind(&if_xlargenegint);
|
| + {
|
| + // The {x} is already an even integer.
|
| + Goto(&return_x);
|
| + }
|
| +
|
| + Bind(&if_xnotlargenegint);
|
| + {
|
| + // Round negative {x} towards -Infinity.
|
| + Node* z = Float64Sub(Float64Constant(-0.0), x);
|
| + Node* y = Float64Sub(Float64Add(two_52, z), two_52);
|
| +
|
| + // Check if we need to adjust {y}.
|
| + Label if_adjust(this), if_notadjust(this);
|
| + Branch(Float64GreaterThan(z, y), &if_adjust, &if_notadjust);
|
| +
|
| + Bind(&if_adjust);
|
| + {
|
| + var_x.Bind(Float64Sub(Float64Constant(-1.0), y));
|
| + Goto(&return_x);
|
| + }
|
| +
|
| + Bind(&if_notadjust);
|
| + {
|
| + var_x.Bind(Float64Sub(Float64Constant(-0.0), y));
|
| + Goto(&return_x);
|
| + }
|
| + }
|
| + }
|
| +
|
| + Bind(&if_xpositive);
|
| + {
|
| + // Check if {x} is zero (either positive or negative).
|
| + Label if_xzero(this), if_xnotzero(this);
|
| + Branch(Float64Equal(x, Float64Constant(0.0)), &if_xzero, &if_xnotzero);
|
| +
|
| + Bind(&if_xzero);
|
| + {
|
| + // We have to return both 0.0 and -0.0 as is.
|
| + Goto(&return_x);
|
| + }
|
| +
|
| + Bind(&if_xnotzero);
|
| + {
|
| + // Round positive {x} towards -Infinity.
|
| + Node* y = Float64Sub(Float64Add(two_52, x), two_52);
|
| +
|
| + // Check if we need to adjust {y}.
|
| + Label if_adjust(this), if_notadjust(this);
|
| + Branch(Float64LessThan(x, y), &if_adjust, &if_notadjust);
|
| +
|
| + Bind(&if_adjust);
|
| + {
|
| + var_x.Bind(Float64Sub(y, Float64Constant(1.0)));
|
| + Goto(&return_x);
|
| + }
|
| +
|
| + Bind(&if_notadjust);
|
| + {
|
| + var_x.Bind(y);
|
| + Goto(&return_x);
|
| + }
|
| + }
|
| + }
|
| + }
|
| +
|
| + Bind(&return_x);
|
| + return var_x.value();
|
| +}
|
|
|
| Node* CodeStubAssembler::SmiTag(Node* value) {
|
| return raw_assembler_->WordShl(value, SmiShiftBitsConstant());
|
| @@ -510,6 +617,65 @@ Node* CodeStubAssembler::BitFieldDecode(Node* word32, uint32_t shift,
|
| raw_assembler_->Int32Constant(shift));
|
| }
|
|
|
| +Node* CodeStubAssembler::ChangeFloat64ToTagged(Node* value) {
|
| + Node* value32 = raw_assembler_->TruncateFloat64ToInt32(
|
| + TruncationMode::kRoundToZero, value);
|
| + Node* value64 = ChangeInt32ToFloat64(value32);
|
| +
|
| + Label if_valueisint32(this), if_valueisheapnumber(this), if_join(this);
|
| +
|
| + Label if_valueisequal(this), if_valueisnotequal(this);
|
| + Branch(Float64Equal(value, value64), &if_valueisequal, &if_valueisnotequal);
|
| + Bind(&if_valueisequal);
|
| + {
|
| + Label if_valueiszero(this), if_valueisnotzero(this);
|
| + Branch(Float64Equal(value, Float64Constant(0.0)), &if_valueiszero,
|
| + &if_valueisnotzero);
|
| +
|
| + Bind(&if_valueiszero);
|
| + BranchIfInt32LessThan(raw_assembler_->Float64ExtractHighWord32(value),
|
| + Int32Constant(0), &if_valueisheapnumber,
|
| + &if_valueisint32);
|
| +
|
| + Bind(&if_valueisnotzero);
|
| + Goto(&if_valueisint32);
|
| + }
|
| + Bind(&if_valueisnotequal);
|
| + Goto(&if_valueisheapnumber);
|
| +
|
| + Variable var_result(this, MachineRepresentation::kTagged);
|
| + Bind(&if_valueisint32);
|
| + {
|
| + if (raw_assembler_->machine()->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),
|
| + if_join(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 = AllocateHeapNumberWithValue(value);
|
| + var_result.Bind(result);
|
| + Goto(&if_join);
|
| + }
|
| + Bind(&if_join);
|
| + return var_result.value();
|
| +}
|
| +
|
| Node* CodeStubAssembler::ChangeInt32ToTagged(Node* value) {
|
| if (raw_assembler_->machine()->Is64()) {
|
| return SmiTag(ChangeInt32ToInt64(value));
|
|
|