| Index: src/code-stub-assembler.cc
|
| diff --git a/src/code-stub-assembler.cc b/src/code-stub-assembler.cc
|
| index 9371fdacab37d732de8f93ecb082d8c08e931ecb..943af5205df1b95d18ac6e1e4c7d859a44394102 100644
|
| --- a/src/code-stub-assembler.cc
|
| +++ b/src/code-stub-assembler.cc
|
| @@ -53,6 +53,14 @@ Node* CodeStubAssembler::NoContextConstant() {
|
| return SmiConstant(Smi::FromInt(0));
|
| }
|
|
|
| +Node* CodeStubAssembler::MinusZeroConstant() {
|
| + return LoadRoot(Heap::kMinusZeroValueRootIndex);
|
| +}
|
| +
|
| +Node* CodeStubAssembler::NanConstant() {
|
| + return LoadRoot(Heap::kNanValueRootIndex);
|
| +}
|
| +
|
| Node* CodeStubAssembler::NullConstant() {
|
| return LoadRoot(Heap::kNullValueRootIndex);
|
| }
|
| @@ -330,6 +338,69 @@ Node* CodeStubAssembler::SmiMin(Node* a, Node* b) {
|
| return min.value();
|
| }
|
|
|
| +Node* CodeStubAssembler::SmiMod(Node* a, Node* b) {
|
| + Variable var_result(this, MachineRepresentation::kTagged);
|
| + Label return_result(this, &var_result),
|
| + return_minuszero(this, Label::kDeferred),
|
| + return_nan(this, Label::kDeferred);
|
| +
|
| + // Untag {a} and {b}.
|
| + a = SmiToWord32(a);
|
| + b = SmiToWord32(b);
|
| +
|
| + // Return NaN if {b} is zero.
|
| + GotoIf(Word32Equal(b, Int32Constant(0)), &return_nan);
|
| +
|
| + // Check if {a} is non-negative.
|
| + Label if_aisnotnegative(this), if_aisnegative(this, Label::kDeferred);
|
| + Branch(Int32LessThanOrEqual(Int32Constant(0), a), &if_aisnotnegative,
|
| + &if_aisnegative);
|
| +
|
| + Bind(&if_aisnotnegative);
|
| + {
|
| + // Fast case, don't need to check any other edge cases.
|
| + Node* r = Int32Mod(a, b);
|
| + var_result.Bind(SmiFromWord32(r));
|
| + Goto(&return_result);
|
| + }
|
| +
|
| + Bind(&if_aisnegative);
|
| + {
|
| + if (SmiValuesAre32Bits()) {
|
| + // Check if {a} is kMinInt and {b} is -1 (only relevant if the
|
| + // kMinInt is actually representable as a Smi).
|
| + Label join(this);
|
| + GotoUnless(Word32Equal(a, Int32Constant(kMinInt)), &join);
|
| + GotoIf(Word32Equal(b, Int32Constant(-1)), &return_minuszero);
|
| + Goto(&join);
|
| + Bind(&join);
|
| + }
|
| +
|
| + // Perform the integer modulus operation.
|
| + Node* r = Int32Mod(a, b);
|
| +
|
| + // Check if {r} is zero, and if so return -0, because we have to
|
| + // take the sign of the left hand side {a}, which is negative.
|
| + GotoIf(Word32Equal(r, Int32Constant(0)), &return_minuszero);
|
| +
|
| + // The remainder {r} can be outside the valid Smi range on 32bit
|
| + // architectures, so we cannot just say SmiFromWord32(r) here.
|
| + var_result.Bind(ChangeInt32ToTagged(r));
|
| + Goto(&return_result);
|
| + }
|
| +
|
| + Bind(&return_minuszero);
|
| + var_result.Bind(MinusZeroConstant());
|
| + Goto(&return_result);
|
| +
|
| + Bind(&return_nan);
|
| + var_result.Bind(NanConstant());
|
| + Goto(&return_result);
|
| +
|
| + Bind(&return_result);
|
| + return var_result.value();
|
| +}
|
| +
|
| Node* CodeStubAssembler::WordIsSmi(Node* a) {
|
| return WordEqual(WordAnd(a, IntPtrConstant(kSmiTagMask)), IntPtrConstant(0));
|
| }
|
|
|