| Index: src/builtins/builtins.cc
|
| diff --git a/src/builtins/builtins.cc b/src/builtins/builtins.cc
|
| index e57091311a77d97b090c10a92f334340e7915c4f..71aacb6affe519e18f70dfaa743491fbb912c1ce 100644
|
| --- a/src/builtins/builtins.cc
|
| +++ b/src/builtins/builtins.cc
|
| @@ -6272,6 +6272,104 @@ void Generate_NonPrimitiveToPrimitive_String(CodeStubAssembler* assembler) {
|
| Generate_NonPrimitiveToPrimitive(assembler, ToPrimitiveHint::kString);
|
| }
|
|
|
| +// ES6 section 7.1.3 ToNumber ( argument )
|
| +void Generate_NonNumberToNumber(CodeStubAssembler* assembler) {
|
| + typedef CodeStubAssembler::Label Label;
|
| + typedef compiler::Node Node;
|
| + typedef CodeStubAssembler::Variable Variable;
|
| +
|
| + Node* input = assembler->Parameter(0);
|
| + Node* context = assembler->Parameter(1);
|
| +
|
| + // 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.
|
| + // TODO(bmeurer): Consider inlining the StringToNumber logic here.
|
| + Callable callable = CodeFactory::StringToNumber(assembler->isolate());
|
| + assembler->TailCallStub(callable, 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);
|
| + }
|
| +
|
| + 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);
|
| + }
|
| + }
|
| +}
|
| +
|
| void Generate_KeyedStoreIC_Slow(MacroAssembler* masm) {
|
| ElementHandlerCompiler::GenerateStoreSlow(masm);
|
| }
|
|
|