1f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// Copyright 2016 the V8 project authors. All rights reserved.
2f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// found in the LICENSE file.
4f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
5f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch#include "src/builtins/builtins-utils.h"
6c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch#include "src/builtins/builtins.h"
7c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch#include "src/code-factory.h"
862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/code-stub-assembler.h"
962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/conversions.h"
1062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/counters.h"
1162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/objects-inl.h"
12f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
13f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochnamespace v8 {
14f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdochnamespace internal {
15f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
1662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdochclass NumberBuiltinsAssembler : public CodeStubAssembler {
1762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch public:
1862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  explicit NumberBuiltinsAssembler(compiler::CodeAssemblerState* state)
1962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      : CodeStubAssembler(state) {}
2062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
2162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch protected:
2262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  template <Signedness signed_result = kSigned>
2362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  void BitwiseOp(std::function<Node*(Node* lhs, Node* rhs)> body) {
2462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* left = Parameter(0);
2562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* right = Parameter(1);
2662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* context = Parameter(2);
2762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
2862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* lhs_value = TruncateTaggedToWord32(context, left);
2962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* rhs_value = TruncateTaggedToWord32(context, right);
3062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* value = body(lhs_value, rhs_value);
3162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* result = signed_result == kSigned ? ChangeInt32ToTagged(value)
3262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                            : ChangeUint32ToTagged(value);
3362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Return(result);
3462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
3562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
3662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  template <Signedness signed_result = kSigned>
3762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  void BitwiseShiftOp(std::function<Node*(Node* lhs, Node* shift_count)> body) {
3862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    BitwiseOp<signed_result>([this, body](Node* lhs, Node* rhs) {
3962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node* shift_count = Word32And(rhs, Int32Constant(0x1f));
4062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      return body(lhs, shift_count);
4162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    });
4262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
4362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
4462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  void RelationalComparisonBuiltin(RelationalComparisonMode mode) {
4562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* lhs = Parameter(0);
4662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* rhs = Parameter(1);
4762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* context = Parameter(2);
4862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
4962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Return(RelationalComparison(mode, lhs, rhs, context));
5062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  }
5162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch};
5262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
53f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// -----------------------------------------------------------------------------
54f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// ES6 section 20.1 Number Objects
55f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
56f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch// ES6 section 20.1.2.2 Number.isFinite ( number )
5762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochTF_BUILTIN(NumberIsFinite, CodeStubAssembler) {
5862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* number = Parameter(1);
59f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
6062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Label return_true(this), return_false(this);
61f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
62f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Check if {number} is a Smi.
6362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  GotoIf(TaggedIsSmi(number), &return_true);
64f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
65f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Check if {number} is a HeapNumber.
6662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  GotoIfNot(IsHeapNumberMap(LoadMap(number)), &return_false);
67f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
68f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Check if {number} contains a finite, non-NaN value.
6962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* number_value = LoadHeapNumberValue(number);
7062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  BranchIfFloat64IsNaN(Float64Sub(number_value, number_value), &return_false,
7162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                       &return_true);
72f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
7362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Bind(&return_true);
7462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Return(BooleanConstant(true));
75f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
7662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Bind(&return_false);
7762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Return(BooleanConstant(false));
78f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch}
79f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
80f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch// ES6 section 20.1.2.3 Number.isInteger ( number )
8162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochTF_BUILTIN(NumberIsInteger, CodeStubAssembler) {
8262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* number = Parameter(1);
83f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
8462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Label return_true(this), return_false(this);
85f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
86f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Check if {number} is a Smi.
8762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  GotoIf(TaggedIsSmi(number), &return_true);
88f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
89f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Check if {number} is a HeapNumber.
9062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  GotoIfNot(IsHeapNumberMap(LoadMap(number)), &return_false);
91f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
92f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Load the actual value of {number}.
9362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* number_value = LoadHeapNumberValue(number);
94f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
95f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Truncate the value of {number} to an integer (or an infinity).
9662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* integer = Float64Trunc(number_value);
97f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
98f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Check if {number}s value matches the integer (ruling out the infinities).
9962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Branch(Float64Equal(Float64Sub(number_value, integer), Float64Constant(0.0)),
10062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch         &return_true, &return_false);
101f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
10262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Bind(&return_true);
10362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Return(BooleanConstant(true));
104f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
10562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Bind(&return_false);
10662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Return(BooleanConstant(false));
107f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch}
108f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
109f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch// ES6 section 20.1.2.4 Number.isNaN ( number )
11062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochTF_BUILTIN(NumberIsNaN, CodeStubAssembler) {
11162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* number = Parameter(1);
112f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
11362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Label return_true(this), return_false(this);
114f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
115f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Check if {number} is a Smi.
11662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  GotoIf(TaggedIsSmi(number), &return_false);
117f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
118f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Check if {number} is a HeapNumber.
11962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  GotoIfNot(IsHeapNumberMap(LoadMap(number)), &return_false);
120f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
121f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Check if {number} contains a NaN value.
12262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* number_value = LoadHeapNumberValue(number);
12362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  BranchIfFloat64IsNaN(number_value, &return_true, &return_false);
124f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
12562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Bind(&return_true);
12662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Return(BooleanConstant(true));
127f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
12862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Bind(&return_false);
12962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Return(BooleanConstant(false));
130f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch}
131f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
132f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch// ES6 section 20.1.2.5 Number.isSafeInteger ( number )
13362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochTF_BUILTIN(NumberIsSafeInteger, CodeStubAssembler) {
13462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* number = Parameter(1);
135f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
13662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Label return_true(this), return_false(this);
137f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
138f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Check if {number} is a Smi.
13962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  GotoIf(TaggedIsSmi(number), &return_true);
140f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
141f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Check if {number} is a HeapNumber.
14262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  GotoIfNot(IsHeapNumberMap(LoadMap(number)), &return_false);
143f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
144f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Load the actual value of {number}.
14562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* number_value = LoadHeapNumberValue(number);
146f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
147f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Truncate the value of {number} to an integer (or an infinity).
14862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* integer = Float64Trunc(number_value);
149f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
150f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Check if {number}s value matches the integer (ruling out the infinities).
15162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  GotoIfNot(
15262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Float64Equal(Float64Sub(number_value, integer), Float64Constant(0.0)),
153f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch      &return_false);
154f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
155f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch  // Check if the {integer} value is in safe integer range.
15662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Branch(Float64LessThanOrEqual(Float64Abs(integer),
15762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                Float64Constant(kMaxSafeInteger)),
15862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch         &return_true, &return_false);
159f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
16062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Bind(&return_true);
16162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Return(BooleanConstant(true));
162f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
16362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Bind(&return_false);
16462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Return(BooleanConstant(false));
165f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch}
166f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch
167c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch// ES6 section 20.1.2.12 Number.parseFloat ( string )
16862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochTF_BUILTIN(NumberParseFloat, CodeStubAssembler) {
16962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* context = Parameter(4);
170c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
171c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // We might need to loop once for ToString conversion.
17262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Variable var_input(this, MachineRepresentation::kTagged);
17362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Label loop(this, &var_input);
17462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  var_input.Bind(Parameter(1));
17562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Goto(&loop);
17662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Bind(&loop);
177c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  {
178c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    // Load the current {input} value.
179c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Node* input = var_input.value();
180c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
181c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    // Check if the {input} is a HeapObject or a Smi.
18262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Label if_inputissmi(this), if_inputisnotsmi(this);
18362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Branch(TaggedIsSmi(input), &if_inputissmi, &if_inputisnotsmi);
184c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
18562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Bind(&if_inputissmi);
186c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    {
187c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      // The {input} is already a Number, no need to do anything.
18862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Return(input);
189c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    }
190c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
19162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Bind(&if_inputisnotsmi);
192c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    {
193c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      // The {input} is a HeapObject, check if it's already a String.
19462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Label if_inputisstring(this), if_inputisnotstring(this);
19562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node* input_map = LoadMap(input);
19662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node* input_instance_type = LoadMapInstanceType(input_map);
19762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Branch(IsStringInstanceType(input_instance_type), &if_inputisstring,
19862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch             &if_inputisnotstring);
199c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
20062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Bind(&if_inputisstring);
201c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      {
202c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        // The {input} is already a String, check if {input} contains
203c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        // a cached array index.
20462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Label if_inputcached(this), if_inputnotcached(this);
20562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Node* input_hash = LoadNameHashField(input);
20662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Node* input_bit = Word32And(
20762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            input_hash, Int32Constant(String::kContainsCachedArrayIndexMask));
20862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Branch(Word32Equal(input_bit, Int32Constant(0)), &if_inputcached,
20962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch               &if_inputnotcached);
21062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
21162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Bind(&if_inputcached);
212c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        {
213c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          // Just return the {input}s cached array index.
214c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          Node* input_array_index =
21562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              DecodeWordFromWord32<String::ArrayIndexValueBits>(input_hash);
21662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Return(SmiTag(input_array_index));
217c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        }
218c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
21962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Bind(&if_inputnotcached);
220c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        {
221c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          // Need to fall back to the runtime to convert {input} to double.
22262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Return(CallRuntime(Runtime::kStringParseFloat, context, input));
223c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        }
224c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      }
225c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
22662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Bind(&if_inputisnotstring);
227c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      {
228c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        // The {input} is neither a String nor a Smi, check for HeapNumber.
22962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Label if_inputisnumber(this),
23062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            if_inputisnotnumber(this, Label::kDeferred);
23162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Branch(IsHeapNumberMap(input_map), &if_inputisnumber,
23262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch               &if_inputisnotnumber);
233c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
23462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Bind(&if_inputisnumber);
235c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        {
236c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          // The {input} is already a Number, take care of -0.
23762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Label if_inputiszero(this), if_inputisnotzero(this);
23862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Node* input_value = LoadHeapNumberValue(input);
23962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Branch(Float64Equal(input_value, Float64Constant(0.0)),
24062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                 &if_inputiszero, &if_inputisnotzero);
241c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
24262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Bind(&if_inputiszero);
24362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Return(SmiConstant(0));
244c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
24562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Bind(&if_inputisnotzero);
24662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Return(input);
247c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        }
248c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
24962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Bind(&if_inputisnotnumber);
250c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        {
251c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          // Need to convert the {input} to String first.
252c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          // TODO(bmeurer): This could be more efficient if necessary.
25362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Callable callable = CodeFactory::ToString(isolate());
25462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          var_input.Bind(CallStub(callable, context, input));
25562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Goto(&loop);
256c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        }
257c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      }
258c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    }
259c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
260c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}
261c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
262c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch// ES6 section 20.1.2.13 Number.parseInt ( string, radix )
26362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochTF_BUILTIN(NumberParseInt, CodeStubAssembler) {
26462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* input = Parameter(1);
26562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* radix = Parameter(2);
26662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* context = Parameter(5);
267c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
268c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // Check if {radix} is treated as 10 (i.e. undefined, 0 or 10).
26962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Label if_radix10(this), if_generic(this, Label::kDeferred);
27062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  GotoIf(WordEqual(radix, UndefinedConstant()), &if_radix10);
27162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  GotoIf(WordEqual(radix, SmiConstant(Smi::FromInt(10))), &if_radix10);
27262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  GotoIf(WordEqual(radix, SmiConstant(Smi::FromInt(0))), &if_radix10);
27362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Goto(&if_generic);
27462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
27562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Bind(&if_radix10);
276c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  {
277c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    // Check if we can avoid the ToString conversion on {input}.
27862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Label if_inputissmi(this), if_inputisheapnumber(this),
27962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        if_inputisstring(this);
28062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    GotoIf(TaggedIsSmi(input), &if_inputissmi);
28162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* input_map = LoadMap(input);
28262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    GotoIf(IsHeapNumberMap(input_map), &if_inputisheapnumber);
28362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* input_instance_type = LoadMapInstanceType(input_map);
28462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Branch(IsStringInstanceType(input_instance_type), &if_inputisstring,
28562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch           &if_generic);
28662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
28762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Bind(&if_inputissmi);
288c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    {
289c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      // Just return the {input}.
29062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Return(input);
291c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    }
292c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
29362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Bind(&if_inputisheapnumber);
294c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    {
295c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      // Check if the {input} value is in Signed32 range.
29662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Label if_inputissigned32(this);
29762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node* input_value = LoadHeapNumberValue(input);
29862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node* input_value32 = TruncateFloat64ToWord32(input_value);
29962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      GotoIf(Float64Equal(input_value, ChangeInt32ToFloat64(input_value32)),
30062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch             &if_inputissigned32);
301c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
302c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      // Check if the absolute {input} value is in the ]0.01,1e9[ range.
30362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node* input_value_abs = Float64Abs(input_value);
304c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
30562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      GotoIfNot(Float64LessThan(input_value_abs, Float64Constant(1e9)),
30662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                &if_generic);
30762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Branch(Float64LessThan(Float64Constant(0.01), input_value_abs),
30862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch             &if_inputissigned32, &if_generic);
309c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
310c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      // Return the truncated int32 value, and return the tagged result.
31162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Bind(&if_inputissigned32);
31262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node* result = ChangeInt32ToTagged(input_value32);
31362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Return(result);
314c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    }
315c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
31662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Bind(&if_inputisstring);
317c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    {
318c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      // Check if the String {input} has a cached array index.
31962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node* input_hash = LoadNameHashField(input);
32062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node* input_bit = Word32And(
32162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          input_hash, Int32Constant(String::kContainsCachedArrayIndexMask));
32262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      GotoIf(Word32NotEqual(input_bit, Int32Constant(0)), &if_generic);
323c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
324c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      // Return the cached array index as result.
325c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      Node* input_index =
32662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          DecodeWordFromWord32<String::ArrayIndexValueBits>(input_hash);
32762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node* result = SmiTag(input_index);
32862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Return(result);
329c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    }
330c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
331c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
33262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Bind(&if_generic);
333c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  {
33462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* result = CallRuntime(Runtime::kStringParseInt, context, input, radix);
33562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Return(result);
336c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
337c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}
338c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
339f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// ES6 section 20.1.3.2 Number.prototype.toExponential ( fractionDigits )
340f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochBUILTIN(NumberPrototypeToExponential) {
341f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  HandleScope scope(isolate);
34262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Handle<Object> value = args.at(0);
343f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Handle<Object> fraction_digits = args.atOrUndefined(isolate, 1);
344f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
345f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Unwrap the receiver {value}.
346f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (value->IsJSValue()) {
347f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    value = handle(Handle<JSValue>::cast(value)->value(), isolate);
348f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
349f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (!value->IsNumber()) {
350f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    THROW_NEW_ERROR_RETURN_FAILURE(
351f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        isolate, NewTypeError(MessageTemplate::kNotGeneric,
352f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                              isolate->factory()->NewStringFromAsciiChecked(
353f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                  "Number.prototype.toExponential")));
354f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
355f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  double const value_number = value->Number();
356f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
357f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Convert the {fraction_digits} to an integer first.
358f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
359f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      isolate, fraction_digits, Object::ToInteger(isolate, fraction_digits));
360f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  double const fraction_digits_number = fraction_digits->Number();
361f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
362f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (std::isnan(value_number)) return isolate->heap()->nan_string();
363f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (std::isinf(value_number)) {
364f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return (value_number < 0.0) ? isolate->heap()->minus_infinity_string()
365f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                : isolate->heap()->infinity_string();
366f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
367f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (fraction_digits_number < 0.0 || fraction_digits_number > 20.0) {
368f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    THROW_NEW_ERROR_RETURN_FAILURE(
369f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        isolate, NewRangeError(MessageTemplate::kNumberFormatRange,
370f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                               isolate->factory()->NewStringFromAsciiChecked(
371f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                   "toExponential()")));
372f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
373f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  int const f = args.atOrUndefined(isolate, 1)->IsUndefined(isolate)
374f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                    ? -1
375f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                    : static_cast<int>(fraction_digits_number);
376f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  char* const str = DoubleToExponentialCString(value_number, f);
377f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(str);
378f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DeleteArray(str);
379f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  return *result;
380f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
381f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
382f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// ES6 section 20.1.3.3 Number.prototype.toFixed ( fractionDigits )
383f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochBUILTIN(NumberPrototypeToFixed) {
384f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  HandleScope scope(isolate);
38562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Handle<Object> value = args.at(0);
386f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Handle<Object> fraction_digits = args.atOrUndefined(isolate, 1);
387f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
388f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Unwrap the receiver {value}.
389f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (value->IsJSValue()) {
390f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    value = handle(Handle<JSValue>::cast(value)->value(), isolate);
391f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
392f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (!value->IsNumber()) {
393f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    THROW_NEW_ERROR_RETURN_FAILURE(
394f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        isolate, NewTypeError(MessageTemplate::kNotGeneric,
395f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                              isolate->factory()->NewStringFromAsciiChecked(
396f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                  "Number.prototype.toFixed")));
397f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
398f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  double const value_number = value->Number();
399f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
400f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Convert the {fraction_digits} to an integer first.
401f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
402f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      isolate, fraction_digits, Object::ToInteger(isolate, fraction_digits));
403f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  double const fraction_digits_number = fraction_digits->Number();
404f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
405f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Check if the {fraction_digits} are in the supported range.
406f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (fraction_digits_number < 0.0 || fraction_digits_number > 20.0) {
407f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    THROW_NEW_ERROR_RETURN_FAILURE(
408f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        isolate, NewRangeError(MessageTemplate::kNumberFormatRange,
409f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                               isolate->factory()->NewStringFromAsciiChecked(
410f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                   "toFixed() digits")));
411f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
412f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
413f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (std::isnan(value_number)) return isolate->heap()->nan_string();
414f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (std::isinf(value_number)) {
415f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return (value_number < 0.0) ? isolate->heap()->minus_infinity_string()
416f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                : isolate->heap()->infinity_string();
417f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
418f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  char* const str = DoubleToFixedCString(
419f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      value_number, static_cast<int>(fraction_digits_number));
420f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(str);
421f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DeleteArray(str);
422f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  return *result;
423f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
424f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
425f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// ES6 section 20.1.3.4 Number.prototype.toLocaleString ( [ r1 [ , r2 ] ] )
426f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochBUILTIN(NumberPrototypeToLocaleString) {
427f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  HandleScope scope(isolate);
42862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Handle<Object> value = args.at(0);
429f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
430f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Unwrap the receiver {value}.
431f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (value->IsJSValue()) {
432f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    value = handle(Handle<JSValue>::cast(value)->value(), isolate);
433f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
434f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (!value->IsNumber()) {
435f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    THROW_NEW_ERROR_RETURN_FAILURE(
436f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        isolate, NewTypeError(MessageTemplate::kNotGeneric,
437f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                              isolate->factory()->NewStringFromAsciiChecked(
438f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                  "Number.prototype.toLocaleString")));
439f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
440f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
441f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Turn the {value} into a String.
442f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  return *isolate->factory()->NumberToString(value);
443f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
444f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
445f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// ES6 section 20.1.3.5 Number.prototype.toPrecision ( precision )
446f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochBUILTIN(NumberPrototypeToPrecision) {
447f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  HandleScope scope(isolate);
44862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Handle<Object> value = args.at(0);
449f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Handle<Object> precision = args.atOrUndefined(isolate, 1);
450f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
451f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Unwrap the receiver {value}.
452f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (value->IsJSValue()) {
453f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    value = handle(Handle<JSValue>::cast(value)->value(), isolate);
454f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
455f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (!value->IsNumber()) {
456f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    THROW_NEW_ERROR_RETURN_FAILURE(
457f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        isolate, NewTypeError(MessageTemplate::kNotGeneric,
458f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                              isolate->factory()->NewStringFromAsciiChecked(
459f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                  "Number.prototype.toPrecision")));
460f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
461f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  double const value_number = value->Number();
462f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
463f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // If no {precision} was specified, just return ToString of {value}.
464f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (precision->IsUndefined(isolate)) {
465f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return *isolate->factory()->NumberToString(value);
466f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
467f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
468f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Convert the {precision} to an integer first.
469f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, precision,
470f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                     Object::ToInteger(isolate, precision));
471f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  double const precision_number = precision->Number();
472f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
473f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (std::isnan(value_number)) return isolate->heap()->nan_string();
474f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (std::isinf(value_number)) {
475f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return (value_number < 0.0) ? isolate->heap()->minus_infinity_string()
476f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                : isolate->heap()->infinity_string();
477f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
478f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (precision_number < 1.0 || precision_number > 21.0) {
479f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    THROW_NEW_ERROR_RETURN_FAILURE(
480f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        isolate, NewRangeError(MessageTemplate::kToPrecisionFormatRange));
481f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
482f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  char* const str = DoubleToPrecisionCString(
483f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      value_number, static_cast<int>(precision_number));
484f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(str);
485f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DeleteArray(str);
486f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  return *result;
487f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
488f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
489f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// ES6 section 20.1.3.6 Number.prototype.toString ( [ radix ] )
490f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen MurdochBUILTIN(NumberPrototypeToString) {
491f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  HandleScope scope(isolate);
49262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Handle<Object> value = args.at(0);
493f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Handle<Object> radix = args.atOrUndefined(isolate, 1);
494f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
495f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Unwrap the receiver {value}.
496f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (value->IsJSValue()) {
497f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    value = handle(Handle<JSValue>::cast(value)->value(), isolate);
498f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
499f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (!value->IsNumber()) {
500f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    THROW_NEW_ERROR_RETURN_FAILURE(
501f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        isolate, NewTypeError(MessageTemplate::kNotGeneric,
502f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                              isolate->factory()->NewStringFromAsciiChecked(
503f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                  "Number.prototype.toString")));
504f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
505f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  double const value_number = value->Number();
506f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
507f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // If no {radix} was specified, just return ToString of {value}.
508f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (radix->IsUndefined(isolate)) {
509f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return *isolate->factory()->NumberToString(value);
510f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
511f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
512f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Convert the {radix} to an integer first.
513f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, radix,
514f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                     Object::ToInteger(isolate, radix));
515f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  double const radix_number = radix->Number();
516f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
517f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // If {radix} is 10, just return ToString of {value}.
518f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (radix_number == 10.0) return *isolate->factory()->NumberToString(value);
519f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
520f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Make sure the {radix} is within the valid range.
521f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (radix_number < 2.0 || radix_number > 36.0) {
522f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    THROW_NEW_ERROR_RETURN_FAILURE(
523f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        isolate, NewRangeError(MessageTemplate::kToRadixFormatRange));
524f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
525f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
526f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Fast case where the result is a one character string.
52762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  if ((IsUint32Double(value_number) && value_number < radix_number) ||
52862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      value_number == -0.0) {
529f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    // Character array used for conversion.
530f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    static const char kCharTable[] = "0123456789abcdefghijklmnopqrstuvwxyz";
531f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return *isolate->factory()->LookupSingleCharacterStringFromCode(
532f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch        kCharTable[static_cast<uint32_t>(value_number)]);
533f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
534f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
535f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  // Slow case.
536f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (std::isnan(value_number)) return isolate->heap()->nan_string();
537f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  if (std::isinf(value_number)) {
538f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch    return (value_number < 0.0) ? isolate->heap()->minus_infinity_string()
539f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch                                : isolate->heap()->infinity_string();
540f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  }
541f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  char* const str =
542f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch      DoubleToRadixCString(value_number, static_cast<int>(radix_number));
543f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  Handle<String> result = isolate->factory()->NewStringFromAsciiChecked(str);
544f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  DeleteArray(str);
545f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch  return *result;
546f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
547f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
548f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch// ES6 section 20.1.3.7 Number.prototype.valueOf ( )
54962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochTF_BUILTIN(NumberPrototypeValueOf, CodeStubAssembler) {
55062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* receiver = Parameter(0);
55162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* context = Parameter(3);
552f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
55362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* result = ToThisValue(context, receiver, PrimitiveType::kNumber,
55462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                             "Number.prototype.valueOf");
55562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Return(result);
556f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}
557f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch
55862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochTF_BUILTIN(Add, CodeStubAssembler) {
55962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* left = Parameter(0);
56062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* right = Parameter(1);
56162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* context = Parameter(2);
562c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
563c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // Shared entry for floating point addition.
56462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Label do_fadd(this);
56562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Variable var_fadd_lhs(this, MachineRepresentation::kFloat64),
56662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      var_fadd_rhs(this, MachineRepresentation::kFloat64);
567c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
568c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // We might need to loop several times due to ToPrimitive, ToString and/or
569c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // ToNumber conversions.
57062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Variable var_lhs(this, MachineRepresentation::kTagged),
57162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      var_rhs(this, MachineRepresentation::kTagged),
57262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      var_result(this, MachineRepresentation::kTagged);
573c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Variable* loop_vars[2] = {&var_lhs, &var_rhs};
57462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Label loop(this, 2, loop_vars), end(this),
57562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      string_add_convert_left(this, Label::kDeferred),
57662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      string_add_convert_right(this, Label::kDeferred);
577c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  var_lhs.Bind(left);
578c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  var_rhs.Bind(right);
57962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Goto(&loop);
58062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Bind(&loop);
581c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  {
582c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    // Load the current {lhs} and {rhs} values.
583c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Node* lhs = var_lhs.value();
584c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Node* rhs = var_rhs.value();
585c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
586c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    // Check if the {lhs} is a Smi or a HeapObject.
58762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Label if_lhsissmi(this), if_lhsisnotsmi(this);
58862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Branch(TaggedIsSmi(lhs), &if_lhsissmi, &if_lhsisnotsmi);
589c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
59062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Bind(&if_lhsissmi);
591c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    {
592c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      // Check if the {rhs} is also a Smi.
59362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Label if_rhsissmi(this), if_rhsisnotsmi(this);
59462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi);
595c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
59662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Bind(&if_rhsissmi);
597c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      {
598c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        // Try fast Smi addition first.
59962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Node* pair = IntPtrAddWithOverflow(BitcastTaggedToWord(lhs),
60062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                           BitcastTaggedToWord(rhs));
60162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Node* overflow = Projection(1, pair);
602c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
603c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        // Check if the Smi additon overflowed.
60462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Label if_overflow(this), if_notoverflow(this);
60562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Branch(overflow, &if_overflow, &if_notoverflow);
606c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
60762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Bind(&if_overflow);
608c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        {
60962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          var_fadd_lhs.Bind(SmiToFloat64(lhs));
61062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          var_fadd_rhs.Bind(SmiToFloat64(rhs));
61162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Goto(&do_fadd);
612c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        }
613c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
61462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Bind(&if_notoverflow);
61562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        var_result.Bind(BitcastWordToTaggedSigned(Projection(0, pair)));
61662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Goto(&end);
617c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      }
618c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
61962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Bind(&if_rhsisnotsmi);
620c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      {
621c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        // Load the map of {rhs}.
62262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Node* rhs_map = LoadMap(rhs);
623c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
624c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        // Check if the {rhs} is a HeapNumber.
62562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Label if_rhsisnumber(this), if_rhsisnotnumber(this, Label::kDeferred);
62662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Branch(IsHeapNumberMap(rhs_map), &if_rhsisnumber, &if_rhsisnotnumber);
627c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
62862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Bind(&if_rhsisnumber);
629c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        {
63062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          var_fadd_lhs.Bind(SmiToFloat64(lhs));
63162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          var_fadd_rhs.Bind(LoadHeapNumberValue(rhs));
63262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Goto(&do_fadd);
633c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        }
634c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
63562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Bind(&if_rhsisnotnumber);
636c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        {
637c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          // Load the instance type of {rhs}.
63862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Node* rhs_instance_type = LoadMapInstanceType(rhs_map);
639c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
640c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          // Check if the {rhs} is a String.
64162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Label if_rhsisstring(this, Label::kDeferred),
64262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              if_rhsisnotstring(this, Label::kDeferred);
64362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Branch(IsStringInstanceType(rhs_instance_type), &if_rhsisstring,
64462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                 &if_rhsisnotstring);
645c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
64662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Bind(&if_rhsisstring);
647c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          {
648c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            var_lhs.Bind(lhs);
649c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            var_rhs.Bind(rhs);
65062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            Goto(&string_add_convert_left);
651c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          }
652c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
65362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Bind(&if_rhsisnotstring);
654c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          {
655c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            // Check if {rhs} is a JSReceiver.
65662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            Label if_rhsisreceiver(this, Label::kDeferred),
65762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                if_rhsisnotreceiver(this, Label::kDeferred);
65862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            Branch(IsJSReceiverInstanceType(rhs_instance_type),
65962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                   &if_rhsisreceiver, &if_rhsisnotreceiver);
660c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
66162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            Bind(&if_rhsisreceiver);
662c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            {
663c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch              // Convert {rhs} to a primitive first passing no hint.
664c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch              Callable callable =
66562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                  CodeFactory::NonPrimitiveToPrimitive(isolate());
66662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              var_rhs.Bind(CallStub(callable, context, rhs));
66762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              Goto(&loop);
668c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            }
669c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
67062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            Bind(&if_rhsisnotreceiver);
671c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            {
672c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch              // Convert {rhs} to a Number first.
67362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              Callable callable = CodeFactory::NonNumberToNumber(isolate());
67462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              var_rhs.Bind(CallStub(callable, context, rhs));
67562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              Goto(&loop);
676c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            }
677c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          }
678c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        }
679c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      }
680c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    }
681c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
68262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Bind(&if_lhsisnotsmi);
683c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    {
684c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      // Load the map and instance type of {lhs}.
68562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node* lhs_instance_type = LoadInstanceType(lhs);
686c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
687c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      // Check if {lhs} is a String.
68862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Label if_lhsisstring(this), if_lhsisnotstring(this);
68962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Branch(IsStringInstanceType(lhs_instance_type), &if_lhsisstring,
69062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch             &if_lhsisnotstring);
691c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
69262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Bind(&if_lhsisstring);
693c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      {
694c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        var_lhs.Bind(lhs);
695c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        var_rhs.Bind(rhs);
69662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Goto(&string_add_convert_right);
697c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      }
698c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
69962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Bind(&if_lhsisnotstring);
700c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      {
701c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        // Check if {rhs} is a Smi.
70262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Label if_rhsissmi(this), if_rhsisnotsmi(this);
70362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi);
704c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
70562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Bind(&if_rhsissmi);
706c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        {
707c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          // Check if {lhs} is a Number.
70862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Label if_lhsisnumber(this), if_lhsisnotnumber(this, Label::kDeferred);
70962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Branch(
71062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              Word32Equal(lhs_instance_type, Int32Constant(HEAP_NUMBER_TYPE)),
71162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              &if_lhsisnumber, &if_lhsisnotnumber);
71262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
71362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Bind(&if_lhsisnumber);
714c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          {
715c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            // The {lhs} is a HeapNumber, the {rhs} is a Smi, just add them.
71662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            var_fadd_lhs.Bind(LoadHeapNumberValue(lhs));
71762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            var_fadd_rhs.Bind(SmiToFloat64(rhs));
71862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            Goto(&do_fadd);
719c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          }
720c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
72162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Bind(&if_lhsisnotnumber);
722c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          {
723c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            // The {lhs} is neither a Number nor a String, and the {rhs} is a
724c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            // Smi.
72562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            Label if_lhsisreceiver(this, Label::kDeferred),
72662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                if_lhsisnotreceiver(this, Label::kDeferred);
72762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            Branch(IsJSReceiverInstanceType(lhs_instance_type),
72862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                   &if_lhsisreceiver, &if_lhsisnotreceiver);
729c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
73062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            Bind(&if_lhsisreceiver);
731c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            {
732c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch              // Convert {lhs} to a primitive first passing no hint.
733c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch              Callable callable =
73462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                  CodeFactory::NonPrimitiveToPrimitive(isolate());
73562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              var_lhs.Bind(CallStub(callable, context, lhs));
73662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              Goto(&loop);
737c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            }
738c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
73962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            Bind(&if_lhsisnotreceiver);
740c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            {
741c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch              // Convert {lhs} to a Number first.
74262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              Callable callable = CodeFactory::NonNumberToNumber(isolate());
74362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              var_lhs.Bind(CallStub(callable, context, lhs));
74462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              Goto(&loop);
745c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            }
746c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          }
747c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        }
748c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
74962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Bind(&if_rhsisnotsmi);
750c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        {
751c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          // Load the instance type of {rhs}.
75262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Node* rhs_instance_type = LoadInstanceType(rhs);
753c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
754c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          // Check if {rhs} is a String.
75562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Label if_rhsisstring(this), if_rhsisnotstring(this);
75662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Branch(IsStringInstanceType(rhs_instance_type), &if_rhsisstring,
75762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                 &if_rhsisnotstring);
758c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
75962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Bind(&if_rhsisstring);
760c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          {
761c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            var_lhs.Bind(lhs);
762c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            var_rhs.Bind(rhs);
76362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            Goto(&string_add_convert_left);
764c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          }
765c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
76662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Bind(&if_rhsisnotstring);
767c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          {
768c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            // Check if {lhs} is a HeapNumber.
76962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            Label if_lhsisnumber(this), if_lhsisnotnumber(this);
77062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            Branch(
77162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                Word32Equal(lhs_instance_type, Int32Constant(HEAP_NUMBER_TYPE)),
77262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                &if_lhsisnumber, &if_lhsisnotnumber);
773c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
77462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            Bind(&if_lhsisnumber);
775c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            {
776c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch              // Check if {rhs} is also a HeapNumber.
77762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              Label if_rhsisnumber(this),
77862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                  if_rhsisnotnumber(this, Label::kDeferred);
77962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              Branch(Word32Equal(rhs_instance_type,
78062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                 Int32Constant(HEAP_NUMBER_TYPE)),
78162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                     &if_rhsisnumber, &if_rhsisnotnumber);
78262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch
78362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              Bind(&if_rhsisnumber);
784c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch              {
785c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                // Perform a floating point addition.
78662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                var_fadd_lhs.Bind(LoadHeapNumberValue(lhs));
78762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                var_fadd_rhs.Bind(LoadHeapNumberValue(rhs));
78862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                Goto(&do_fadd);
789c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch              }
790c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
79162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              Bind(&if_rhsisnotnumber);
792c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch              {
793c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                // Check if {rhs} is a JSReceiver.
79462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                Label if_rhsisreceiver(this, Label::kDeferred),
79562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                    if_rhsisnotreceiver(this, Label::kDeferred);
79662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                Branch(IsJSReceiverInstanceType(rhs_instance_type),
79762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                       &if_rhsisreceiver, &if_rhsisnotreceiver);
798c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
79962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                Bind(&if_rhsisreceiver);
800c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                {
801c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                  // Convert {rhs} to a primitive first passing no hint.
80262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                  Callable callable =
80362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                      CodeFactory::NonPrimitiveToPrimitive(isolate());
80462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                  var_rhs.Bind(CallStub(callable, context, rhs));
80562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                  Goto(&loop);
806c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                }
807c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
80862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                Bind(&if_rhsisnotreceiver);
809c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                {
810c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                  // Convert {rhs} to a Number first.
81162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                  Callable callable = CodeFactory::NonNumberToNumber(isolate());
81262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                  var_rhs.Bind(CallStub(callable, context, rhs));
81362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                  Goto(&loop);
814c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                }
815c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch              }
816c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            }
817c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
81862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            Bind(&if_lhsisnotnumber);
819c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            {
820c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch              // Check if {lhs} is a JSReceiver.
82162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              Label if_lhsisreceiver(this, Label::kDeferred),
82262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                  if_lhsisnotreceiver(this);
82362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              Branch(IsJSReceiverInstanceType(lhs_instance_type),
82462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                     &if_lhsisreceiver, &if_lhsisnotreceiver);
825c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
82662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              Bind(&if_lhsisreceiver);
827c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch              {
828c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                // Convert {lhs} to a primitive first passing no hint.
829c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                Callable callable =
83062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                    CodeFactory::NonPrimitiveToPrimitive(isolate());
83162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                var_lhs.Bind(CallStub(callable, context, lhs));
83262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                Goto(&loop);
833c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch              }
834c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
83562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              Bind(&if_lhsisnotreceiver);
836c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch              {
837c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                // Check if {rhs} is a JSReceiver.
83862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                Label if_rhsisreceiver(this, Label::kDeferred),
83962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                    if_rhsisnotreceiver(this, Label::kDeferred);
84062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                Branch(IsJSReceiverInstanceType(rhs_instance_type),
84162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                       &if_rhsisreceiver, &if_rhsisnotreceiver);
842c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
84362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                Bind(&if_rhsisreceiver);
844c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                {
845c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                  // Convert {rhs} to a primitive first passing no hint.
84662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                  Callable callable =
84762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                      CodeFactory::NonPrimitiveToPrimitive(isolate());
84862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                  var_rhs.Bind(CallStub(callable, context, rhs));
84962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                  Goto(&loop);
850c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                }
851c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
85262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                Bind(&if_rhsisnotreceiver);
853c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                {
854c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                  // Convert {lhs} to a Number first.
85562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                  Callable callable = CodeFactory::NonNumberToNumber(isolate());
85662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                  var_lhs.Bind(CallStub(callable, context, lhs));
85762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                  Goto(&loop);
858c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch                }
859c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch              }
860c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            }
861c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          }
862c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        }
863c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      }
864c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    }
865c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
86662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Bind(&string_add_convert_left);
867c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  {
868c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    // Convert {lhs}, which is a Smi, to a String and concatenate the
869c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    // resulting string with the String {rhs}.
87062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Callable callable =
87162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        CodeFactory::StringAdd(isolate(), STRING_ADD_CONVERT_LEFT, NOT_TENURED);
87262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    var_result.Bind(
87362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        CallStub(callable, context, var_lhs.value(), var_rhs.value()));
87462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Goto(&end);
875c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
876c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
87762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Bind(&string_add_convert_right);
878c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  {
879c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    // Convert {lhs}, which is a Smi, to a String and concatenate the
880c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    // resulting string with the String {rhs}.
881c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Callable callable = CodeFactory::StringAdd(
88262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        isolate(), STRING_ADD_CONVERT_RIGHT, NOT_TENURED);
88362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    var_result.Bind(
88462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        CallStub(callable, context, var_lhs.value(), var_rhs.value()));
88562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Goto(&end);
886c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
887c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
88862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Bind(&do_fadd);
889c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  {
890c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Node* lhs_value = var_fadd_lhs.value();
891c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Node* rhs_value = var_fadd_rhs.value();
89262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* value = Float64Add(lhs_value, rhs_value);
89362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* result = AllocateHeapNumberWithValue(value);
894c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    var_result.Bind(result);
89562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Goto(&end);
896c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
89762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Bind(&end);
89862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Return(var_result.value());
899c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}
900c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
90162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochTF_BUILTIN(Subtract, CodeStubAssembler) {
90262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* left = Parameter(0);
90362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* right = Parameter(1);
90462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* context = Parameter(2);
905c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
906c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // Shared entry for floating point subtraction.
90762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Label do_fsub(this), end(this);
90862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Variable var_fsub_lhs(this, MachineRepresentation::kFloat64),
90962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      var_fsub_rhs(this, MachineRepresentation::kFloat64);
910c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
911c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // We might need to loop several times due to ToPrimitive and/or ToNumber
912c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // conversions.
91362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Variable var_lhs(this, MachineRepresentation::kTagged),
91462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      var_rhs(this, MachineRepresentation::kTagged),
91562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      var_result(this, MachineRepresentation::kTagged);
916c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Variable* loop_vars[2] = {&var_lhs, &var_rhs};
91762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Label loop(this, 2, loop_vars);
918c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  var_lhs.Bind(left);
919c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  var_rhs.Bind(right);
92062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Goto(&loop);
92162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Bind(&loop);
922c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  {
923c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    // Load the current {lhs} and {rhs} values.
924c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Node* lhs = var_lhs.value();
925c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Node* rhs = var_rhs.value();
926c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
927c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    // Check if the {lhs} is a Smi or a HeapObject.
92862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Label if_lhsissmi(this), if_lhsisnotsmi(this);
92962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Branch(TaggedIsSmi(lhs), &if_lhsissmi, &if_lhsisnotsmi);
930c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
93162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Bind(&if_lhsissmi);
932c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    {
933c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      // Check if the {rhs} is also a Smi.
93462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Label if_rhsissmi(this), if_rhsisnotsmi(this);
93562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi);
936c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
93762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Bind(&if_rhsissmi);
938c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      {
939c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        // Try a fast Smi subtraction first.
94062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Node* pair = IntPtrSubWithOverflow(BitcastTaggedToWord(lhs),
94162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                           BitcastTaggedToWord(rhs));
94262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Node* overflow = Projection(1, pair);
943c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
944c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        // Check if the Smi subtraction overflowed.
94562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Label if_overflow(this), if_notoverflow(this);
94662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Branch(overflow, &if_overflow, &if_notoverflow);
947c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
94862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Bind(&if_overflow);
949c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        {
950c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          // The result doesn't fit into Smi range.
95162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          var_fsub_lhs.Bind(SmiToFloat64(lhs));
95262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          var_fsub_rhs.Bind(SmiToFloat64(rhs));
95362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Goto(&do_fsub);
954c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        }
955c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
95662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Bind(&if_notoverflow);
95762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        var_result.Bind(BitcastWordToTaggedSigned(Projection(0, pair)));
95862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Goto(&end);
959c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      }
960c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
96162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Bind(&if_rhsisnotsmi);
962c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      {
963c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        // Load the map of the {rhs}.
96462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Node* rhs_map = LoadMap(rhs);
965c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
966c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        // Check if {rhs} is a HeapNumber.
96762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Label if_rhsisnumber(this), if_rhsisnotnumber(this, Label::kDeferred);
96862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Branch(IsHeapNumberMap(rhs_map), &if_rhsisnumber, &if_rhsisnotnumber);
969c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
97062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Bind(&if_rhsisnumber);
971c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        {
972c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          // Perform a floating point subtraction.
97362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          var_fsub_lhs.Bind(SmiToFloat64(lhs));
97462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          var_fsub_rhs.Bind(LoadHeapNumberValue(rhs));
97562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Goto(&do_fsub);
976c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        }
977c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
97862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Bind(&if_rhsisnotnumber);
979c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        {
980c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          // Convert the {rhs} to a Number first.
98162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Callable callable = CodeFactory::NonNumberToNumber(isolate());
98262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          var_rhs.Bind(CallStub(callable, context, rhs));
98362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Goto(&loop);
984c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        }
985c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      }
986c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    }
987c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
98862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Bind(&if_lhsisnotsmi);
989c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    {
990c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      // Load the map of the {lhs}.
99162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node* lhs_map = LoadMap(lhs);
992c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
993c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      // Check if the {lhs} is a HeapNumber.
99462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Label if_lhsisnumber(this), if_lhsisnotnumber(this, Label::kDeferred);
99562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Branch(IsHeapNumberMap(lhs_map), &if_lhsisnumber, &if_lhsisnotnumber);
996c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
99762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Bind(&if_lhsisnumber);
998c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      {
999c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        // Check if the {rhs} is a Smi.
100062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Label if_rhsissmi(this), if_rhsisnotsmi(this);
100162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Branch(TaggedIsSmi(rhs), &if_rhsissmi, &if_rhsisnotsmi);
1002c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
100362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Bind(&if_rhsissmi);
1004c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        {
1005c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          // Perform a floating point subtraction.
100662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          var_fsub_lhs.Bind(LoadHeapNumberValue(lhs));
100762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          var_fsub_rhs.Bind(SmiToFloat64(rhs));
100862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Goto(&do_fsub);
1009c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        }
1010c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
101162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Bind(&if_rhsisnotsmi);
1012c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        {
1013c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          // Load the map of the {rhs}.
101462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Node* rhs_map = LoadMap(rhs);
1015c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1016c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          // Check if the {rhs} is a HeapNumber.
101762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Label if_rhsisnumber(this), if_rhsisnotnumber(this, Label::kDeferred);
101862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Branch(IsHeapNumberMap(rhs_map), &if_rhsisnumber, &if_rhsisnotnumber);
1019c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
102062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Bind(&if_rhsisnumber);
1021c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          {
1022c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            // Perform a floating point subtraction.
102362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            var_fsub_lhs.Bind(LoadHeapNumberValue(lhs));
102462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            var_fsub_rhs.Bind(LoadHeapNumberValue(rhs));
102562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            Goto(&do_fsub);
1026c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          }
1027c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
102862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Bind(&if_rhsisnotnumber);
1029c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          {
1030c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            // Convert the {rhs} to a Number first.
103162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            Callable callable = CodeFactory::NonNumberToNumber(isolate());
103262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            var_rhs.Bind(CallStub(callable, context, rhs));
103362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            Goto(&loop);
1034c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          }
1035c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        }
1036c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      }
1037c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
103862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Bind(&if_lhsisnotnumber);
1039c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      {
1040c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        // Convert the {lhs} to a Number first.
104162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Callable callable = CodeFactory::NonNumberToNumber(isolate());
104262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        var_lhs.Bind(CallStub(callable, context, lhs));
104362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Goto(&loop);
1044c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      }
1045c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    }
1046c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
1047c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
104862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Bind(&do_fsub);
1049c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  {
1050c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Node* lhs_value = var_fsub_lhs.value();
1051c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Node* rhs_value = var_fsub_rhs.value();
105262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* value = Float64Sub(lhs_value, rhs_value);
105362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    var_result.Bind(AllocateHeapNumberWithValue(value));
105462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Goto(&end);
1055c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
105662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Bind(&end);
105762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Return(var_result.value());
1058c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}
1059c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
106062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochTF_BUILTIN(Multiply, CodeStubAssembler) {
106162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* left = Parameter(0);
106262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* right = Parameter(1);
106362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* context = Parameter(2);
1064c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1065c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // Shared entry point for floating point multiplication.
106662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Label do_fmul(this), return_result(this);
106762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Variable var_lhs_float64(this, MachineRepresentation::kFloat64),
106862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      var_rhs_float64(this, MachineRepresentation::kFloat64);
1069c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1070c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // We might need to loop one or two times due to ToNumber conversions.
107162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Variable var_lhs(this, MachineRepresentation::kTagged),
107262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      var_rhs(this, MachineRepresentation::kTagged),
107362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      var_result(this, MachineRepresentation::kTagged);
1074c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Variable* loop_variables[] = {&var_lhs, &var_rhs};
107562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Label loop(this, 2, loop_variables);
1076c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  var_lhs.Bind(left);
1077c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  var_rhs.Bind(right);
107862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Goto(&loop);
107962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Bind(&loop);
1080c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  {
1081c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Node* lhs = var_lhs.value();
1082c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Node* rhs = var_rhs.value();
1083c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
108462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Label lhs_is_smi(this), lhs_is_not_smi(this);
108562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Branch(TaggedIsSmi(lhs), &lhs_is_smi, &lhs_is_not_smi);
1086c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
108762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Bind(&lhs_is_smi);
1088c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    {
108962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Label rhs_is_smi(this), rhs_is_not_smi(this);
109062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Branch(TaggedIsSmi(rhs), &rhs_is_smi, &rhs_is_not_smi);
1091c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
109262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Bind(&rhs_is_smi);
1093c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      {
1094c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        // Both {lhs} and {rhs} are Smis. The result is not necessarily a smi,
1095c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        // in case of overflow.
109662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        var_result.Bind(SmiMul(lhs, rhs));
109762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Goto(&return_result);
1098c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      }
1099c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
110062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Bind(&rhs_is_not_smi);
1101c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      {
110262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Node* rhs_map = LoadMap(rhs);
1103c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1104c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        // Check if {rhs} is a HeapNumber.
110562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Label rhs_is_number(this), rhs_is_not_number(this, Label::kDeferred);
110662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Branch(IsHeapNumberMap(rhs_map), &rhs_is_number, &rhs_is_not_number);
1107c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
110862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Bind(&rhs_is_number);
1109c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        {
1110c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          // Convert {lhs} to a double and multiply it with the value of {rhs}.
111162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          var_lhs_float64.Bind(SmiToFloat64(lhs));
111262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          var_rhs_float64.Bind(LoadHeapNumberValue(rhs));
111362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Goto(&do_fmul);
1114c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        }
1115c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
111662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Bind(&rhs_is_not_number);
1117c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        {
1118c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          // Multiplication is commutative, swap {lhs} with {rhs} and loop.
1119c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          var_lhs.Bind(rhs);
1120c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          var_rhs.Bind(lhs);
112162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Goto(&loop);
1122c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        }
1123c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      }
1124c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    }
1125c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
112662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Bind(&lhs_is_not_smi);
1127c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    {
112862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node* lhs_map = LoadMap(lhs);
1129c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1130c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      // Check if {lhs} is a HeapNumber.
113162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Label lhs_is_number(this), lhs_is_not_number(this, Label::kDeferred);
113262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Branch(IsHeapNumberMap(lhs_map), &lhs_is_number, &lhs_is_not_number);
1133c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
113462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Bind(&lhs_is_number);
1135c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      {
1136c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        // Check if {rhs} is a Smi.
113762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Label rhs_is_smi(this), rhs_is_not_smi(this);
113862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Branch(TaggedIsSmi(rhs), &rhs_is_smi, &rhs_is_not_smi);
1139c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
114062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Bind(&rhs_is_smi);
1141c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        {
1142c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          // Convert {rhs} to a double and multiply it with the value of {lhs}.
114362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          var_lhs_float64.Bind(LoadHeapNumberValue(lhs));
114462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          var_rhs_float64.Bind(SmiToFloat64(rhs));
114562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Goto(&do_fmul);
1146c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        }
1147c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
114862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Bind(&rhs_is_not_smi);
1149c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        {
115062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Node* rhs_map = LoadMap(rhs);
1151c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1152c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          // Check if {rhs} is a HeapNumber.
115362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Label rhs_is_number(this), rhs_is_not_number(this, Label::kDeferred);
115462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Branch(IsHeapNumberMap(rhs_map), &rhs_is_number, &rhs_is_not_number);
1155c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
115662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Bind(&rhs_is_number);
1157c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          {
1158c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            // Both {lhs} and {rhs} are HeapNumbers. Load their values and
1159c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            // multiply them.
116062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            var_lhs_float64.Bind(LoadHeapNumberValue(lhs));
116162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            var_rhs_float64.Bind(LoadHeapNumberValue(rhs));
116262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            Goto(&do_fmul);
1163c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          }
1164c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
116562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Bind(&rhs_is_not_number);
1166c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          {
1167c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            // Multiplication is commutative, swap {lhs} with {rhs} and loop.
1168c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            var_lhs.Bind(rhs);
1169c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            var_rhs.Bind(lhs);
117062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            Goto(&loop);
1171c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          }
1172c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        }
1173c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      }
1174c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
117562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Bind(&lhs_is_not_number);
1176c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      {
1177c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        // Convert {lhs} to a Number and loop.
117862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Callable callable = CodeFactory::NonNumberToNumber(isolate());
117962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        var_lhs.Bind(CallStub(callable, context, lhs));
118062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Goto(&loop);
1181c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      }
1182c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    }
1183c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
1184c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
118562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Bind(&do_fmul);
1186c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  {
118762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* value = Float64Mul(var_lhs_float64.value(), var_rhs_float64.value());
118862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* result = AllocateHeapNumberWithValue(value);
1189c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    var_result.Bind(result);
119062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Goto(&return_result);
1191c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
1192c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
119362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Bind(&return_result);
119462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Return(var_result.value());
1195c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}
1196c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
119762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochTF_BUILTIN(Divide, CodeStubAssembler) {
119862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* left = Parameter(0);
119962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* right = Parameter(1);
120062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* context = Parameter(2);
1201c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1202c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // Shared entry point for floating point division.
120362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Label do_fdiv(this), end(this);
120462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Variable var_dividend_float64(this, MachineRepresentation::kFloat64),
120562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      var_divisor_float64(this, MachineRepresentation::kFloat64);
1206c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1207c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // We might need to loop one or two times due to ToNumber conversions.
120862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Variable var_dividend(this, MachineRepresentation::kTagged),
120962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      var_divisor(this, MachineRepresentation::kTagged),
121062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      var_result(this, MachineRepresentation::kTagged);
1211c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Variable* loop_variables[] = {&var_dividend, &var_divisor};
121262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Label loop(this, 2, loop_variables);
1213c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  var_dividend.Bind(left);
1214c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  var_divisor.Bind(right);
121562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Goto(&loop);
121662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Bind(&loop);
1217c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  {
1218c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Node* dividend = var_dividend.value();
1219c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Node* divisor = var_divisor.value();
1220c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
122162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Label dividend_is_smi(this), dividend_is_not_smi(this);
122262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Branch(TaggedIsSmi(dividend), &dividend_is_smi, &dividend_is_not_smi);
1223c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
122462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Bind(&dividend_is_smi);
1225c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    {
122662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Label divisor_is_smi(this), divisor_is_not_smi(this);
122762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Branch(TaggedIsSmi(divisor), &divisor_is_smi, &divisor_is_not_smi);
1228c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
122962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Bind(&divisor_is_smi);
1230c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      {
123162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Label bailout(this);
1232c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1233c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        // Do floating point division if {divisor} is zero.
123462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        GotoIf(SmiEqual(divisor, SmiConstant(0)), &bailout);
1235c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1236c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        // Do floating point division {dividend} is zero and {divisor} is
1237c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        // negative.
123862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Label dividend_is_zero(this), dividend_is_not_zero(this);
123962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Branch(SmiEqual(dividend, SmiConstant(0)), &dividend_is_zero,
124062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch               &dividend_is_not_zero);
1241c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
124262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Bind(&dividend_is_zero);
1243c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        {
124462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          GotoIf(SmiLessThan(divisor, SmiConstant(0)), &bailout);
124562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Goto(&dividend_is_not_zero);
1246c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        }
124762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Bind(&dividend_is_not_zero);
1248c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
124962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Node* untagged_divisor = SmiToWord32(divisor);
125062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Node* untagged_dividend = SmiToWord32(dividend);
1251c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1252c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        // Do floating point division if {dividend} is kMinInt (or kMinInt - 1
1253c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        // if the Smi size is 31) and {divisor} is -1.
125462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Label divisor_is_minus_one(this), divisor_is_not_minus_one(this);
125562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Branch(Word32Equal(untagged_divisor, Int32Constant(-1)),
125662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch               &divisor_is_minus_one, &divisor_is_not_minus_one);
1257c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
125862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Bind(&divisor_is_minus_one);
1259c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        {
126062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          GotoIf(
126162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              Word32Equal(untagged_dividend,
126262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                          Int32Constant(kSmiValueSize == 32 ? kMinInt
126362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                                                            : (kMinInt >> 1))),
1264c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch              &bailout);
126562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Goto(&divisor_is_not_minus_one);
1266c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        }
126762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Bind(&divisor_is_not_minus_one);
1268c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1269c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        // TODO(epertoso): consider adding a machine instruction that returns
1270c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        // both the result and the remainder.
127162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Node* untagged_result = Int32Div(untagged_dividend, untagged_divisor);
127262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Node* truncated = Int32Mul(untagged_result, untagged_divisor);
1273c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        // Do floating point division if the remainder is not 0.
127462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        GotoIf(Word32NotEqual(untagged_dividend, truncated), &bailout);
127562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        var_result.Bind(SmiFromWord32(untagged_result));
127662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Goto(&end);
1277c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1278c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        // Bailout: convert {dividend} and {divisor} to double and do double
1279c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        // division.
128062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Bind(&bailout);
1281c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        {
128262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          var_dividend_float64.Bind(SmiToFloat64(dividend));
128362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          var_divisor_float64.Bind(SmiToFloat64(divisor));
128462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Goto(&do_fdiv);
1285c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        }
1286c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      }
1287c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
128862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Bind(&divisor_is_not_smi);
1289c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      {
129062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Node* divisor_map = LoadMap(divisor);
1291c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1292c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        // Check if {divisor} is a HeapNumber.
129362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Label divisor_is_number(this),
129462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            divisor_is_not_number(this, Label::kDeferred);
129562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Branch(IsHeapNumberMap(divisor_map), &divisor_is_number,
129662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch               &divisor_is_not_number);
1297c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
129862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Bind(&divisor_is_number);
1299c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        {
1300c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          // Convert {dividend} to a double and divide it with the value of
1301c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          // {divisor}.
130262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          var_dividend_float64.Bind(SmiToFloat64(dividend));
130362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          var_divisor_float64.Bind(LoadHeapNumberValue(divisor));
130462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Goto(&do_fdiv);
1305c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        }
1306c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
130762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Bind(&divisor_is_not_number);
1308c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        {
1309c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          // Convert {divisor} to a number and loop.
131062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Callable callable = CodeFactory::NonNumberToNumber(isolate());
131162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          var_divisor.Bind(CallStub(callable, context, divisor));
131262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Goto(&loop);
1313c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        }
1314c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      }
1315c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    }
1316c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
131762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Bind(&dividend_is_not_smi);
1318c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    {
131962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node* dividend_map = LoadMap(dividend);
1320c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1321c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      // Check if {dividend} is a HeapNumber.
132262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Label dividend_is_number(this),
132362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          dividend_is_not_number(this, Label::kDeferred);
132462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Branch(IsHeapNumberMap(dividend_map), &dividend_is_number,
132562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch             &dividend_is_not_number);
1326c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
132762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Bind(&dividend_is_number);
1328c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      {
1329c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        // Check if {divisor} is a Smi.
133062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Label divisor_is_smi(this), divisor_is_not_smi(this);
133162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Branch(TaggedIsSmi(divisor), &divisor_is_smi, &divisor_is_not_smi);
1332c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
133362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Bind(&divisor_is_smi);
1334c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        {
1335c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          // Convert {divisor} to a double and use it for a floating point
1336c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          // division.
133762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          var_dividend_float64.Bind(LoadHeapNumberValue(dividend));
133862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          var_divisor_float64.Bind(SmiToFloat64(divisor));
133962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Goto(&do_fdiv);
1340c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        }
1341c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
134262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Bind(&divisor_is_not_smi);
1343c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        {
134462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Node* divisor_map = LoadMap(divisor);
1345c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1346c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          // Check if {divisor} is a HeapNumber.
134762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Label divisor_is_number(this),
134862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              divisor_is_not_number(this, Label::kDeferred);
134962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Branch(IsHeapNumberMap(divisor_map), &divisor_is_number,
135062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                 &divisor_is_not_number);
1351c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
135262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Bind(&divisor_is_number);
1353c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          {
1354c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            // Both {dividend} and {divisor} are HeapNumbers. Load their values
1355c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            // and divide them.
135662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            var_dividend_float64.Bind(LoadHeapNumberValue(dividend));
135762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            var_divisor_float64.Bind(LoadHeapNumberValue(divisor));
135862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            Goto(&do_fdiv);
1359c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          }
1360c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
136162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Bind(&divisor_is_not_number);
1362c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          {
1363c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            // Convert {divisor} to a number and loop.
136462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            Callable callable = CodeFactory::NonNumberToNumber(isolate());
136562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            var_divisor.Bind(CallStub(callable, context, divisor));
136662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            Goto(&loop);
1367c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          }
1368c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        }
1369c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      }
1370c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
137162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Bind(&dividend_is_not_number);
1372c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      {
1373c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        // Convert {dividend} to a Number and loop.
137462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Callable callable = CodeFactory::NonNumberToNumber(isolate());
137562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        var_dividend.Bind(CallStub(callable, context, dividend));
137662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Goto(&loop);
1377c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      }
1378c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    }
1379c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
1380c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
138162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Bind(&do_fdiv);
1382c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  {
138362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* value =
138462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Float64Div(var_dividend_float64.value(), var_divisor_float64.value());
138562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    var_result.Bind(AllocateHeapNumberWithValue(value));
138662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Goto(&end);
1387c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
138862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Bind(&end);
138962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Return(var_result.value());
1390c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}
1391c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
139262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochTF_BUILTIN(Modulus, CodeStubAssembler) {
139362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* left = Parameter(0);
139462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* right = Parameter(1);
139562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* context = Parameter(2);
1396c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
139762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Variable var_result(this, MachineRepresentation::kTagged);
139862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Label return_result(this, &var_result);
1399c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1400c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // Shared entry point for floating point modulus.
140162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Label do_fmod(this);
140262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Variable var_dividend_float64(this, MachineRepresentation::kFloat64),
140362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      var_divisor_float64(this, MachineRepresentation::kFloat64);
1404c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1405c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  // We might need to loop one or two times due to ToNumber conversions.
140662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Variable var_dividend(this, MachineRepresentation::kTagged),
140762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      var_divisor(this, MachineRepresentation::kTagged);
1408c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  Variable* loop_variables[] = {&var_dividend, &var_divisor};
140962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Label loop(this, 2, loop_variables);
1410c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  var_dividend.Bind(left);
1411c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  var_divisor.Bind(right);
141262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Goto(&loop);
141362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Bind(&loop);
1414c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  {
1415c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Node* dividend = var_dividend.value();
1416c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    Node* divisor = var_divisor.value();
1417c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
141862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Label dividend_is_smi(this), dividend_is_not_smi(this);
141962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Branch(TaggedIsSmi(dividend), &dividend_is_smi, &dividend_is_not_smi);
1420c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
142162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Bind(&dividend_is_smi);
1422c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    {
142362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Label dividend_is_not_zero(this);
142462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Label divisor_is_smi(this), divisor_is_not_smi(this);
142562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Branch(TaggedIsSmi(divisor), &divisor_is_smi, &divisor_is_not_smi);
1426c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
142762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Bind(&divisor_is_smi);
1428c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      {
1429c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        // Compute the modulus of two Smis.
143062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        var_result.Bind(SmiMod(dividend, divisor));
143162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Goto(&return_result);
1432c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      }
1433c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
143462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Bind(&divisor_is_not_smi);
1435c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      {
143662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Node* divisor_map = LoadMap(divisor);
1437c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1438c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        // Check if {divisor} is a HeapNumber.
143962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Label divisor_is_number(this),
144062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            divisor_is_not_number(this, Label::kDeferred);
144162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Branch(IsHeapNumberMap(divisor_map), &divisor_is_number,
144262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch               &divisor_is_not_number);
1443c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
144462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Bind(&divisor_is_number);
1445c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        {
1446c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          // Convert {dividend} to a double and compute its modulus with the
1447c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          // value of {dividend}.
144862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          var_dividend_float64.Bind(SmiToFloat64(dividend));
144962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          var_divisor_float64.Bind(LoadHeapNumberValue(divisor));
145062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Goto(&do_fmod);
1451c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        }
1452c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
145362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Bind(&divisor_is_not_number);
1454c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        {
1455c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          // Convert {divisor} to a number and loop.
145662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Callable callable = CodeFactory::NonNumberToNumber(isolate());
145762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          var_divisor.Bind(CallStub(callable, context, divisor));
145862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Goto(&loop);
1459c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        }
1460c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      }
1461c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    }
1462c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
146362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Bind(&dividend_is_not_smi);
1464c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    {
146562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Node* dividend_map = LoadMap(dividend);
1466c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1467c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      // Check if {dividend} is a HeapNumber.
146862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Label dividend_is_number(this),
146962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          dividend_is_not_number(this, Label::kDeferred);
147062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Branch(IsHeapNumberMap(dividend_map), &dividend_is_number,
147162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch             &dividend_is_not_number);
1472c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
147362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Bind(&dividend_is_number);
1474c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      {
1475c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        // Check if {divisor} is a Smi.
147662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Label divisor_is_smi(this), divisor_is_not_smi(this);
147762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Branch(TaggedIsSmi(divisor), &divisor_is_smi, &divisor_is_not_smi);
1478c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
147962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Bind(&divisor_is_smi);
1480c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        {
1481c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          // Convert {divisor} to a double and compute {dividend}'s modulus with
1482c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          // it.
148362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          var_dividend_float64.Bind(LoadHeapNumberValue(dividend));
148462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          var_divisor_float64.Bind(SmiToFloat64(divisor));
148562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Goto(&do_fmod);
1486c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        }
1487c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
148862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Bind(&divisor_is_not_smi);
1489c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        {
149062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Node* divisor_map = LoadMap(divisor);
1491c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1492c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          // Check if {divisor} is a HeapNumber.
149362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Label divisor_is_number(this),
149462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch              divisor_is_not_number(this, Label::kDeferred);
149562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Branch(IsHeapNumberMap(divisor_map), &divisor_is_number,
149662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch                 &divisor_is_not_number);
1497c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
149862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Bind(&divisor_is_number);
1499c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          {
1500c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            // Both {dividend} and {divisor} are HeapNumbers. Load their values
1501c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            // and compute their modulus.
150262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            var_dividend_float64.Bind(LoadHeapNumberValue(dividend));
150362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            var_divisor_float64.Bind(LoadHeapNumberValue(divisor));
150462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            Goto(&do_fmod);
1505c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          }
1506c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
150762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch          Bind(&divisor_is_not_number);
1508c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          {
1509c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch            // Convert {divisor} to a number and loop.
151062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            Callable callable = CodeFactory::NonNumberToNumber(isolate());
151162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            var_divisor.Bind(CallStub(callable, context, divisor));
151262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch            Goto(&loop);
1513c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch          }
1514c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        }
1515c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      }
1516c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
151762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch      Bind(&dividend_is_not_number);
1518c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      {
1519c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch        // Convert {dividend} to a Number and loop.
152062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Callable callable = CodeFactory::NonNumberToNumber(isolate());
152162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        var_dividend.Bind(CallStub(callable, context, dividend));
152262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Goto(&loop);
1523c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch      }
1524c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch    }
1525c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
1526c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
152762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Bind(&do_fmod);
1528c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  {
152962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Node* value =
153062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch        Float64Mod(var_dividend_float64.value(), var_divisor_float64.value());
153162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    var_result.Bind(AllocateHeapNumberWithValue(value));
153262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    Goto(&return_result);
1533c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch  }
1534c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
153562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Bind(&return_result);
153662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Return(var_result.value());
1537c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}
1538c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
153962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochTF_BUILTIN(ShiftLeft, NumberBuiltinsAssembler) {
154062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  BitwiseShiftOp([this](Node* lhs, Node* shift_count) {
154162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return Word32Shl(lhs, shift_count);
154262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  });
1543c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}
1544c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
154562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochTF_BUILTIN(ShiftRight, NumberBuiltinsAssembler) {
154662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  BitwiseShiftOp([this](Node* lhs, Node* shift_count) {
154762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return Word32Sar(lhs, shift_count);
154862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  });
1549c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}
1550c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
155162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochTF_BUILTIN(ShiftRightLogical, NumberBuiltinsAssembler) {
155262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  BitwiseShiftOp<kUnsigned>([this](Node* lhs, Node* shift_count) {
155362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch    return Word32Shr(lhs, shift_count);
155462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  });
1555c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}
1556c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
155762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochTF_BUILTIN(BitwiseAnd, NumberBuiltinsAssembler) {
155862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  BitwiseOp([this](Node* lhs, Node* rhs) { return Word32And(lhs, rhs); });
1559c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}
1560c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
156162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochTF_BUILTIN(BitwiseOr, NumberBuiltinsAssembler) {
156262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  BitwiseOp([this](Node* lhs, Node* rhs) { return Word32Or(lhs, rhs); });
1563c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}
1564c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
156562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochTF_BUILTIN(BitwiseXor, NumberBuiltinsAssembler) {
156662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  BitwiseOp([this](Node* lhs, Node* rhs) { return Word32Xor(lhs, rhs); });
1567c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}
1568c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
156962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochTF_BUILTIN(LessThan, NumberBuiltinsAssembler) {
157062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  RelationalComparisonBuiltin(kLessThan);
1571c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}
1572c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
157362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochTF_BUILTIN(LessThanOrEqual, NumberBuiltinsAssembler) {
157462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  RelationalComparisonBuiltin(kLessThanOrEqual);
1575c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}
1576c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
157762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochTF_BUILTIN(GreaterThan, NumberBuiltinsAssembler) {
157862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  RelationalComparisonBuiltin(kGreaterThan);
1579c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}
1580c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
158162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochTF_BUILTIN(GreaterThanOrEqual, NumberBuiltinsAssembler) {
158262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  RelationalComparisonBuiltin(kGreaterThanOrEqual);
1583c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}
1584c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
158562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochTF_BUILTIN(Equal, CodeStubAssembler) {
158662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* lhs = Parameter(0);
158762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* rhs = Parameter(1);
158862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* context = Parameter(2);
1589c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
159062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Return(Equal(kDontNegateResult, lhs, rhs, context));
1591c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}
1592c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
159362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochTF_BUILTIN(NotEqual, CodeStubAssembler) {
159462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* lhs = Parameter(0);
159562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* rhs = Parameter(1);
159662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* context = Parameter(2);
1597c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
159862ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Return(Equal(kNegateResult, lhs, rhs, context));
1599c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}
1600c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
160162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochTF_BUILTIN(StrictEqual, CodeStubAssembler) {
160262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* lhs = Parameter(0);
160362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* rhs = Parameter(1);
160462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* context = Parameter(2);
1605c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
160662ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Return(StrictEqual(kDontNegateResult, lhs, rhs, context));
1607c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}
1608c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
160962ed631aa0ff23db68a47fd423efa9c019ff2c9eBen MurdochTF_BUILTIN(StrictNotEqual, CodeStubAssembler) {
161062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* lhs = Parameter(0);
161162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* rhs = Parameter(1);
161262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Node* context = Parameter(2);
1613c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
161462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch  Return(StrictEqual(kNegateResult, lhs, rhs, context));
1615c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch}
1616c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch
1617f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}  // namespace internal
1618f91f0611dbaf29ca0f1d4aecb357ce243a19d2faBen Murdoch}  // namespace v8
1619