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), ÷nd_is_smi, ÷nd_is_not_smi); 1223c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 122462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(÷nd_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)), ÷nd_is_zero, 124062ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch ÷nd_is_not_zero); 1241c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 124262ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(÷nd_is_zero); 1243c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch { 124462ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch GotoIf(SmiLessThan(divisor, SmiConstant(0)), &bailout); 124562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Goto(÷nd_is_not_zero); 1246c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch } 124762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(÷nd_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(÷nd_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), ÷nd_is_number, 132562ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch ÷nd_is_not_number); 1326c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 132762ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(÷nd_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(÷nd_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), ÷nd_is_smi, ÷nd_is_not_smi); 1420c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 142162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(÷nd_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(÷nd_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), ÷nd_is_number, 147162ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch ÷nd_is_not_number); 1472c8c1d9e03f4babd16833b0f8ccf6aab5fa6e8c7aBen Murdoch 147362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch Bind(÷nd_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(÷nd_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