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