[builtins] Migrate ToNumber to TurboFan.

Migrate ToNumber platform builtin to TurboFan. Also move
NonNumberToNumber builtin implementation to helper function.

BUG=v8:5049

Review-Url: https://codereview.chromium.org/2327703003
Cr-Commit-Position: refs/heads/master@{#39343}
This commit is contained in:
Alexander.Gilday2 2016-09-12 04:00:40 -07:00 committed by Commit bot
parent e7b7ba8edd
commit 278b9f800b
15 changed files with 144 additions and 254 deletions

View File

@ -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

View File

@ -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, &not_smi);
__ Ret();
__ Bind(&not_smi);
Label not_heap_number;
__ CompareObjectType(x0, x1, x1, HEAP_NUMBER_TYPE);
// x0: receiver
// x1: receiver instance type
__ B(ne, &not_heap_number);
__ Ret();
__ Bind(&not_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 -------------

View File

@ -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();
// 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);
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));
assembler->Return(assembler->NonNumberToNumber(context, input));
}
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);
}
// ES6 section 7.1.3 ToNumber ( argument )
void Builtins::Generate_ToNumber(CodeStubAssembler* assembler) {
typedef compiler::Node Node;
typedef TypeConversionDescriptor Descriptor;
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);
Node* input = assembler->Parameter(Descriptor::kArgument);
Node* context = assembler->Parameter(Descriptor::kContext);
// 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<Code> Builtins::OrdinaryToPrimitive(OrdinaryToPrimitiveHint hint) {

View File

@ -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 */ \

View File

@ -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, &not_smi, Label::kNear);
__ Ret();
__ bind(&not_smi);
Label not_heap_number;
__ CompareMap(eax, masm->isolate()->factory()->heap_number_map());
__ j(not_equal, &not_heap_number, Label::kNear);
__ Ret();
__ bind(&not_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

View File

@ -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, &not_smi);
__ Ret(USE_DELAY_SLOT);
__ mov(v0, a0);
__ bind(&not_smi);
Label not_heap_number;
__ GetObjectType(a0, a1, a1);
// a0: receiver
// a1: receiver instance type
__ Branch(&not_heap_number, ne, a1, Operand(HEAP_NUMBER_TYPE));
__ Ret(USE_DELAY_SLOT);
__ mov(v0, a0);
__ bind(&not_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 -------------

View File

@ -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, &not_smi);
__ Ret(USE_DELAY_SLOT);
__ mov(v0, a0);
__ bind(&not_smi);
Label not_heap_number;
__ GetObjectType(a0, a1, a1);
// a0: receiver
// a1: receiver instance type
__ Branch(&not_heap_number, ne, a1, Operand(HEAP_NUMBER_TYPE));
__ Ret(USE_DELAY_SLOT);
__ mov(v0, a0);
__ bind(&not_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 -------------

View File

@ -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

View File

@ -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

View File

@ -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, &not_smi, Label::kNear);
__ Ret();
__ bind(&not_smi);
Label not_heap_number;
__ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset),
Heap::kHeapNumberMapRootIndex);
__ j(not_equal, &not_heap_number, Label::kNear);
__ Ret();
__ bind(&not_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

View File

@ -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, &not_smi, Label::kNear);
__ Ret();
__ bind(&not_smi);
Label not_heap_number;
__ CompareMap(eax, masm->isolate()->factory()->heap_number_map());
__ j(not_equal, &not_heap_number, Label::kNear);
__ Ret();
__ bind(&not_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

View File

@ -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), &not_smi);
var_result.Bind(input);
Goto(&end);
Bind(&not_smi);
{
Label not_heap_number(this, Label::kDeferred);
Node* input_map = LoadMap(input);
GotoIf(Word32NotEqual(input_map, HeapNumberMapConstant()),
&not_heap_number);
var_result.Bind(input);
Goto(&end);
Bind(&not_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)),

View File

@ -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.

View File

@ -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

View File

@ -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();
}