diff --git a/src/builtins/arm/builtins-arm.cc b/src/builtins/arm/builtins-arm.cc index d3ed62ac1b..49d2e9120b 100644 --- a/src/builtins/arm/builtins-arm.cc +++ b/src/builtins/arm/builtins-arm.cc @@ -2836,21 +2836,6 @@ void Builtins::Generate_Abort(MacroAssembler* masm) { __ TailCallRuntime(Runtime::kAbort); } -void Builtins::Generate_ToNumber(MacroAssembler* masm) { - // The ToNumber stub takes one argument in r0. - STATIC_ASSERT(kSmiTag == 0); - __ tst(r0, Operand(kSmiTagMask)); - __ Ret(eq); - - __ CompareObjectType(r0, r1, r1, HEAP_NUMBER_TYPE); - // r0: receiver - // r1: receiver instance type - __ Ret(eq); - - __ Jump(masm->isolate()->builtins()->NonNumberToNumber(), - RelocInfo::CODE_TARGET); -} - void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { // ----------- S t a t e ------------- // -- r0 : actual number of arguments diff --git a/src/builtins/arm64/builtins-arm64.cc b/src/builtins/arm64/builtins-arm64.cc index 4ec14f1b4e..c82b6f344c 100644 --- a/src/builtins/arm64/builtins-arm64.cc +++ b/src/builtins/arm64/builtins-arm64.cc @@ -2916,26 +2916,6 @@ void Builtins::Generate_Abort(MacroAssembler* masm) { __ TailCallRuntime(Runtime::kAbort); } -// static -void Builtins::Generate_ToNumber(MacroAssembler* masm) { - // The ToNumber stub takes one argument in x0. - Label not_smi; - __ JumpIfNotSmi(x0, ¬_smi); - __ Ret(); - __ Bind(¬_smi); - - Label not_heap_number; - __ CompareObjectType(x0, x1, x1, HEAP_NUMBER_TYPE); - // x0: receiver - // x1: receiver instance type - __ B(ne, ¬_heap_number); - __ Ret(); - __ Bind(¬_heap_number); - - __ Jump(masm->isolate()->builtins()->NonNumberToNumber(), - RelocInfo::CODE_TARGET); -} - void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { ASM_LOCATION("Builtins::Generate_ArgumentsAdaptorTrampoline"); // ----------- S t a t e ------------- diff --git a/src/builtins/builtins-conversion.cc b/src/builtins/builtins-conversion.cc index 1797b2ece8..77a3e2f2eb 100644 --- a/src/builtins/builtins-conversion.cc +++ b/src/builtins/builtins-conversion.cc @@ -129,101 +129,26 @@ void Builtins::Generate_ToName(CodeStubAssembler* assembler) { assembler->Return(assembler->ToName(context, input)); } -// ES6 section 7.1.3 ToNumber ( argument ) +// static void Builtins::Generate_NonNumberToNumber(CodeStubAssembler* assembler) { - typedef CodeStubAssembler::Label Label; typedef compiler::Node Node; - typedef CodeStubAssembler::Variable Variable; typedef TypeConversionDescriptor Descriptor; Node* input = assembler->Parameter(Descriptor::kArgument); Node* context = assembler->Parameter(Descriptor::kContext); - // We might need to loop once here due to ToPrimitive conversions. - Variable var_input(assembler, MachineRepresentation::kTagged); - Label loop(assembler, &var_input); - var_input.Bind(input); - assembler->Goto(&loop); - assembler->Bind(&loop); - { - // Load the current {input} value (known to be a HeapObject). - Node* input = var_input.value(); + assembler->Return(assembler->NonNumberToNumber(context, input)); +} - // Dispatch on the {input} instance type. - Node* input_instance_type = assembler->LoadInstanceType(input); - Label if_inputisstring(assembler), if_inputisoddball(assembler), - if_inputisreceiver(assembler, Label::kDeferred), - if_inputisother(assembler, Label::kDeferred); - assembler->GotoIf(assembler->Int32LessThan( - input_instance_type, - assembler->Int32Constant(FIRST_NONSTRING_TYPE)), - &if_inputisstring); - assembler->GotoIf( - assembler->Word32Equal(input_instance_type, - assembler->Int32Constant(ODDBALL_TYPE)), - &if_inputisoddball); - STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); - assembler->Branch(assembler->Int32GreaterThanOrEqual( - input_instance_type, - assembler->Int32Constant(FIRST_JS_RECEIVER_TYPE)), - &if_inputisreceiver, &if_inputisother); +// ES6 section 7.1.3 ToNumber ( argument ) +void Builtins::Generate_ToNumber(CodeStubAssembler* assembler) { + typedef compiler::Node Node; + typedef TypeConversionDescriptor Descriptor; - assembler->Bind(&if_inputisstring); - { - // The {input} is a String, use the fast stub to convert it to a Number. - assembler->Return(assembler->StringToNumber(context, input)); - } + Node* input = assembler->Parameter(Descriptor::kArgument); + Node* context = assembler->Parameter(Descriptor::kContext); - assembler->Bind(&if_inputisoddball); - { - // The {input} is an Oddball, we just need to the Number value of it. - Node* result = - assembler->LoadObjectField(input, Oddball::kToNumberOffset); - assembler->Return(result); - } - - assembler->Bind(&if_inputisreceiver); - { - // The {input} is a JSReceiver, we need to convert it to a Primitive first - // using the ToPrimitive type conversion, preferably yielding a Number. - Callable callable = CodeFactory::NonPrimitiveToPrimitive( - assembler->isolate(), ToPrimitiveHint::kNumber); - Node* result = assembler->CallStub(callable, context, input); - - // Check if the {result} is already a Number. - Label if_resultisnumber(assembler), if_resultisnotnumber(assembler); - assembler->GotoIf(assembler->WordIsSmi(result), &if_resultisnumber); - Node* result_map = assembler->LoadMap(result); - assembler->Branch( - assembler->WordEqual(result_map, assembler->HeapNumberMapConstant()), - &if_resultisnumber, &if_resultisnotnumber); - - assembler->Bind(&if_resultisnumber); - { - // The ToPrimitive conversion already gave us a Number, so we're done. - assembler->Return(result); - } - - assembler->Bind(&if_resultisnotnumber); - { - // We now have a Primitive {result}, but it's not yet a Number. - var_input.Bind(result); - assembler->Goto(&loop); - } - } - - assembler->Bind(&if_inputisother); - { - // The {input} is something else (i.e. Symbol or Simd128Value), let the - // runtime figure out the correct exception. - // Note: We cannot tail call to the runtime here, as js-to-wasm - // trampolines also use this code currently, and they declare all - // outgoing parameters as untagged, while we would push a tagged - // object here. - Node* result = assembler->CallRuntime(Runtime::kToNumber, context, input); - assembler->Return(result); - } - } + assembler->Return(assembler->ToNumber(context, input)); } Handle Builtins::OrdinaryToPrimitive(OrdinaryToPrimitiveHint hint) { diff --git a/src/builtins/builtins.h b/src/builtins/builtins.h index 4b6f252506..6d8e2e0e48 100644 --- a/src/builtins/builtins.h +++ b/src/builtins/builtins.h @@ -185,7 +185,7 @@ namespace internal { TFS(StringToNumber, BUILTIN, kNoExtraICState, TypeConversion) \ TFS(ToName, BUILTIN, kNoExtraICState, TypeConversion) \ TFS(NonNumberToNumber, BUILTIN, kNoExtraICState, TypeConversion) \ - ASM(ToNumber) \ + TFS(ToNumber, BUILTIN, kNoExtraICState, TypeConversion) \ \ /* Built-in functions for Javascript */ \ /* Special internal builtins */ \ diff --git a/src/builtins/ia32/builtins-ia32.cc b/src/builtins/ia32/builtins-ia32.cc index 00edd35cdc..2215870ab4 100644 --- a/src/builtins/ia32/builtins-ia32.cc +++ b/src/builtins/ia32/builtins-ia32.cc @@ -2884,24 +2884,6 @@ void Builtins::Generate_Abort(MacroAssembler* masm) { __ TailCallRuntime(Runtime::kAbort); } -// static -void Builtins::Generate_ToNumber(MacroAssembler* masm) { - // The ToNumber stub takes one argument in eax. - Label not_smi; - __ JumpIfNotSmi(eax, ¬_smi, Label::kNear); - __ Ret(); - __ bind(¬_smi); - - Label not_heap_number; - __ CompareMap(eax, masm->isolate()->factory()->heap_number_map()); - __ j(not_equal, ¬_heap_number, Label::kNear); - __ Ret(); - __ bind(¬_heap_number); - - __ Jump(masm->isolate()->builtins()->NonNumberToNumber(), - RelocInfo::CODE_TARGET); -} - void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { // ----------- S t a t e ------------- // -- eax : actual number of arguments diff --git a/src/builtins/mips/builtins-mips.cc b/src/builtins/mips/builtins-mips.cc index 9a1c10ad1c..8e696b276d 100644 --- a/src/builtins/mips/builtins-mips.cc +++ b/src/builtins/mips/builtins-mips.cc @@ -2901,28 +2901,6 @@ void Builtins::Generate_Abort(MacroAssembler* masm) { __ TailCallRuntime(Runtime::kAbort); } -// static -void Builtins::Generate_ToNumber(MacroAssembler* masm) { - // The ToNumber stub takes one argument in a0. - Label not_smi; - __ JumpIfNotSmi(a0, ¬_smi); - __ Ret(USE_DELAY_SLOT); - __ mov(v0, a0); - __ bind(¬_smi); - - Label not_heap_number; - __ GetObjectType(a0, a1, a1); - // a0: receiver - // a1: receiver instance type - __ Branch(¬_heap_number, ne, a1, Operand(HEAP_NUMBER_TYPE)); - __ Ret(USE_DELAY_SLOT); - __ mov(v0, a0); - __ bind(¬_heap_number); - - __ Jump(masm->isolate()->builtins()->NonNumberToNumber(), - RelocInfo::CODE_TARGET); -} - void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { // State setup as expected by MacroAssembler::InvokePrologue. // ----------- S t a t e ------------- diff --git a/src/builtins/mips64/builtins-mips64.cc b/src/builtins/mips64/builtins-mips64.cc index 818ae2b054..4284ebe498 100644 --- a/src/builtins/mips64/builtins-mips64.cc +++ b/src/builtins/mips64/builtins-mips64.cc @@ -2894,28 +2894,6 @@ void Builtins::Generate_Abort(MacroAssembler* masm) { __ TailCallRuntime(Runtime::kAbort); } -// static -void Builtins::Generate_ToNumber(MacroAssembler* masm) { - // The ToNumber stub takes one argument in a0. - Label not_smi; - __ JumpIfNotSmi(a0, ¬_smi); - __ Ret(USE_DELAY_SLOT); - __ mov(v0, a0); - __ bind(¬_smi); - - Label not_heap_number; - __ GetObjectType(a0, a1, a1); - // a0: receiver - // a1: receiver instance type - __ Branch(¬_heap_number, ne, a1, Operand(HEAP_NUMBER_TYPE)); - __ Ret(USE_DELAY_SLOT); - __ mov(v0, a0); - __ bind(¬_heap_number); - - __ Jump(masm->isolate()->builtins()->NonNumberToNumber(), - RelocInfo::CODE_TARGET); -} - void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { // State setup as expected by MacroAssembler::InvokePrologue. // ----------- S t a t e ------------- diff --git a/src/builtins/ppc/builtins-ppc.cc b/src/builtins/ppc/builtins-ppc.cc index e420ce12c1..7223e5e110 100644 --- a/src/builtins/ppc/builtins-ppc.cc +++ b/src/builtins/ppc/builtins-ppc.cc @@ -2915,22 +2915,6 @@ void Builtins::Generate_Abort(MacroAssembler* masm) { __ TailCallRuntime(Runtime::kAbort); } -// static -void Builtins::Generate_ToNumber(MacroAssembler* masm) { - // The ToNumber stub takes one argument in r3. - STATIC_ASSERT(kSmiTag == 0); - __ TestIfSmi(r3, r0); - __ Ret(eq, cr0); - - __ CompareObjectType(r3, r4, r4, HEAP_NUMBER_TYPE); - // r3: receiver - // r4: receiver instance type - __ Ret(eq); - - __ Jump(masm->isolate()->builtins()->NonNumberToNumber(), - RelocInfo::CODE_TARGET); -} - void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { // ----------- S t a t e ------------- // -- r3 : actual number of arguments diff --git a/src/builtins/s390/builtins-s390.cc b/src/builtins/s390/builtins-s390.cc index 293ff2e4e2..69f5634f24 100644 --- a/src/builtins/s390/builtins-s390.cc +++ b/src/builtins/s390/builtins-s390.cc @@ -2927,22 +2927,6 @@ void Builtins::Generate_Abort(MacroAssembler* masm) { __ TailCallRuntime(Runtime::kAbort); } -// static -void Builtins::Generate_ToNumber(MacroAssembler* masm) { - // The ToNumber stub takes one argument in r2. - STATIC_ASSERT(kSmiTag == 0); - __ TestIfSmi(r2); - __ Ret(eq); - - __ CompareObjectType(r2, r3, r3, HEAP_NUMBER_TYPE); - // r2: receiver - // r3: receiver instance type - __ Ret(eq); - - __ Jump(masm->isolate()->builtins()->NonNumberToNumber(), - RelocInfo::CODE_TARGET); -} - void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { // ----------- S t a t e ------------- // -- r2 : actual number of arguments diff --git a/src/builtins/x64/builtins-x64.cc b/src/builtins/x64/builtins-x64.cc index 82922239e1..ecdac09347 100644 --- a/src/builtins/x64/builtins-x64.cc +++ b/src/builtins/x64/builtins-x64.cc @@ -2217,25 +2217,6 @@ void Builtins::Generate_Abort(MacroAssembler* masm) { __ TailCallRuntime(Runtime::kAbort); } -// static -void Builtins::Generate_ToNumber(MacroAssembler* masm) { - // The ToNumber stub takes one argument in rax. - Label not_smi; - __ JumpIfNotSmi(rax, ¬_smi, Label::kNear); - __ Ret(); - __ bind(¬_smi); - - Label not_heap_number; - __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset), - Heap::kHeapNumberMapRootIndex); - __ j(not_equal, ¬_heap_number, Label::kNear); - __ Ret(); - __ bind(¬_heap_number); - - __ Jump(masm->isolate()->builtins()->NonNumberToNumber(), - RelocInfo::CODE_TARGET); -} - void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { // ----------- S t a t e ------------- // -- rax : actual number of arguments diff --git a/src/builtins/x87/builtins-x87.cc b/src/builtins/x87/builtins-x87.cc index 169b9f2ac5..98a70be6b5 100644 --- a/src/builtins/x87/builtins-x87.cc +++ b/src/builtins/x87/builtins-x87.cc @@ -2908,24 +2908,6 @@ void Builtins::Generate_Abort(MacroAssembler* masm) { __ TailCallRuntime(Runtime::kAbort); } -// static -void Builtins::Generate_ToNumber(MacroAssembler* masm) { - // The ToNumber stub takes one argument in eax. - Label not_smi; - __ JumpIfNotSmi(eax, ¬_smi, Label::kNear); - __ Ret(); - __ bind(¬_smi); - - Label not_heap_number; - __ CompareMap(eax, masm->isolate()->factory()->heap_number_map()); - __ j(not_equal, ¬_heap_number, Label::kNear); - __ Ret(); - __ bind(¬_heap_number); - - __ Jump(masm->isolate()->builtins()->NonNumberToNumber(), - RelocInfo::CODE_TARGET); -} - void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { // ----------- S t a t e ------------- // -- eax : actual number of arguments diff --git a/src/code-stub-assembler.cc b/src/code-stub-assembler.cc index 07d8d5c34a..73fe8a9227 100644 --- a/src/code-stub-assembler.cc +++ b/src/code-stub-assembler.cc @@ -2439,6 +2439,129 @@ Node* CodeStubAssembler::ToName(Node* context, Node* value) { return var_result.value(); } +Node* CodeStubAssembler::NonNumberToNumber(Node* context, Node* input) { + // Assert input is a HeapObject (not smi or heap number) + Assert(Word32BinaryNot(WordIsSmi(input))); + Assert(Word32NotEqual(LoadMap(input), HeapNumberMapConstant())); + + // We might need to loop once here due to ToPrimitive conversions. + Variable var_input(this, MachineRepresentation::kTagged); + Variable var_result(this, MachineRepresentation::kTagged); + Label loop(this, &var_input); + Label end(this); + var_input.Bind(input); + Goto(&loop); + Bind(&loop); + { + // Load the current {input} value (known to be a HeapObject). + Node* input = var_input.value(); + + // Dispatch on the {input} instance type. + Node* input_instance_type = LoadInstanceType(input); + Label if_inputisstring(this), if_inputisoddball(this), + if_inputisreceiver(this, Label::kDeferred), + if_inputisother(this, Label::kDeferred); + GotoIf( + Int32LessThan(input_instance_type, Int32Constant(FIRST_NONSTRING_TYPE)), + &if_inputisstring); + GotoIf(Word32Equal(input_instance_type, Int32Constant(ODDBALL_TYPE)), + &if_inputisoddball); + STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); + Branch(Int32GreaterThanOrEqual(input_instance_type, + Int32Constant(FIRST_JS_RECEIVER_TYPE)), + &if_inputisreceiver, &if_inputisother); + + Bind(&if_inputisstring); + { + // The {input} is a String, use the fast stub to convert it to a Number. + var_result.Bind(StringToNumber(context, input)); + Goto(&end); + } + + Bind(&if_inputisoddball); + { + // The {input} is an Oddball, we just need to load the Number value of it. + var_result.Bind(LoadObjectField(input, Oddball::kToNumberOffset)); + Goto(&end); + } + + Bind(&if_inputisreceiver); + { + // The {input} is a JSReceiver, we need to convert it to a Primitive first + // using the ToPrimitive type conversion, preferably yielding a Number. + Callable callable = CodeFactory::NonPrimitiveToPrimitive( + isolate(), ToPrimitiveHint::kNumber); + Node* result = CallStub(callable, context, input); + + // Check if the {result} is already a Number. + Label if_resultisnumber(this), if_resultisnotnumber(this); + GotoIf(WordIsSmi(result), &if_resultisnumber); + Node* result_map = LoadMap(result); + Branch(WordEqual(result_map, HeapNumberMapConstant()), &if_resultisnumber, + &if_resultisnotnumber); + + Bind(&if_resultisnumber); + { + // The ToPrimitive conversion already gave us a Number, so we're done. + var_result.Bind(result); + Goto(&end); + } + + Bind(&if_resultisnotnumber); + { + // We now have a Primitive {result}, but it's not yet a Number. + var_input.Bind(result); + Goto(&loop); + } + } + + Bind(&if_inputisother); + { + // The {input} is something else (i.e. Symbol or Simd128Value), let the + // runtime figure out the correct exception. + // Note: We cannot tail call to the runtime here, as js-to-wasm + // trampolines also use this code currently, and they declare all + // outgoing parameters as untagged, while we would push a tagged + // object here. + var_result.Bind(CallRuntime(Runtime::kToNumber, context, input)); + Goto(&end); + } + } + + Bind(&end); + return var_result.value(); +} + +Node* CodeStubAssembler::ToNumber(Node* context, Node* input) { + Variable var_result(this, MachineRepresentation::kTagged); + Label end(this); + + Label not_smi(this, Label::kDeferred); + GotoUnless(WordIsSmi(input), ¬_smi); + var_result.Bind(input); + Goto(&end); + + Bind(¬_smi); + { + Label not_heap_number(this, Label::kDeferred); + Node* input_map = LoadMap(input); + GotoIf(Word32NotEqual(input_map, HeapNumberMapConstant()), + ¬_heap_number); + + var_result.Bind(input); + Goto(&end); + + Bind(¬_heap_number); + { + var_result.Bind(NonNumberToNumber(context, input)); + Goto(&end); + } + } + + Bind(&end); + return var_result.value(); +} + Node* CodeStubAssembler::BitFieldDecode(Node* word32, uint32_t shift, uint32_t mask) { return Word32Shr(Word32And(word32, Int32Constant(mask)), diff --git a/src/code-stub-assembler.h b/src/code-stub-assembler.h index b217353f7d..7252a1dcbb 100644 --- a/src/code-stub-assembler.h +++ b/src/code-stub-assembler.h @@ -431,6 +431,11 @@ class CodeStubAssembler : public compiler::CodeAssembler { compiler::Node* input); // Convert an object to a name. compiler::Node* ToName(compiler::Node* context, compiler::Node* input); + // Convert a Non-Number object to a Number. + compiler::Node* NonNumberToNumber(compiler::Node* context, + compiler::Node* input); + // Convert any object to a Number. + compiler::Node* ToNumber(compiler::Node* context, compiler::Node* input); // Returns a node that contains a decoded (unsigned!) value of a bit // field |T| in |word32|. Returns result as an uint32 node. diff --git a/src/compiler/code-assembler.h b/src/compiler/code-assembler.h index 3ee3bb2430..fa81533618 100644 --- a/src/compiler/code-assembler.h +++ b/src/compiler/code-assembler.h @@ -148,7 +148,8 @@ class RawMachineLabel; V(Float64RoundDown) \ V(Float64RoundUp) \ V(Float64RoundTruncate) \ - V(Word32Clz) + V(Word32Clz) \ + V(Word32BinaryNot) // A "public" interface used by components outside of compiler directory to // create code objects with TurboFan's backend. This class is mostly a thin shim diff --git a/src/interpreter/interpreter.cc b/src/interpreter/interpreter.cc index 69d7a90c9a..7a38a63e12 100644 --- a/src/interpreter/interpreter.cc +++ b/src/interpreter/interpreter.cc @@ -1314,7 +1314,9 @@ void Interpreter::DoToName(InterpreterAssembler* assembler) { // // Convert the object referenced by the accumulator to a number. void Interpreter::DoToNumber(InterpreterAssembler* assembler) { - Node* result = BuildUnaryOp(CodeFactory::ToNumber(isolate_), assembler); + Node* object = __ GetAccumulator(); + Node* context = __ GetContext(); + Node* result = __ ToNumber(context, object); __ StoreRegister(result, __ BytecodeOperandReg(0)); __ Dispatch(); }