| OLD | NEW |
| 1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/builtins/builtins.h" | 5 #include "src/builtins/builtins.h" |
| 6 #include "src/builtins/builtins-utils.h" | 6 #include "src/builtins/builtins-utils.h" |
| 7 #include "src/code-factory.h" | 7 #include "src/code-factory.h" |
| 8 | 8 |
| 9 namespace v8 { | 9 namespace v8 { |
| 10 namespace internal { | 10 namespace internal { |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 122 void Builtins::Generate_ToName(CodeStubAssembler* assembler) { | 122 void Builtins::Generate_ToName(CodeStubAssembler* assembler) { |
| 123 typedef compiler::Node Node; | 123 typedef compiler::Node Node; |
| 124 typedef TypeConversionDescriptor Descriptor; | 124 typedef TypeConversionDescriptor Descriptor; |
| 125 | 125 |
| 126 Node* input = assembler->Parameter(Descriptor::kArgument); | 126 Node* input = assembler->Parameter(Descriptor::kArgument); |
| 127 Node* context = assembler->Parameter(Descriptor::kContext); | 127 Node* context = assembler->Parameter(Descriptor::kContext); |
| 128 | 128 |
| 129 assembler->Return(assembler->ToName(context, input)); | 129 assembler->Return(assembler->ToName(context, input)); |
| 130 } | 130 } |
| 131 | 131 |
| 132 // ES6 section 7.1.3 ToNumber ( argument ) | 132 // static |
| 133 void Builtins::Generate_NonNumberToNumber(CodeStubAssembler* assembler) { | 133 void Builtins::Generate_NonNumberToNumber(CodeStubAssembler* assembler) { |
| 134 typedef CodeStubAssembler::Label Label; | |
| 135 typedef compiler::Node Node; | 134 typedef compiler::Node Node; |
| 136 typedef CodeStubAssembler::Variable Variable; | |
| 137 typedef TypeConversionDescriptor Descriptor; | 135 typedef TypeConversionDescriptor Descriptor; |
| 138 | 136 |
| 139 Node* input = assembler->Parameter(Descriptor::kArgument); | 137 Node* input = assembler->Parameter(Descriptor::kArgument); |
| 140 Node* context = assembler->Parameter(Descriptor::kContext); | 138 Node* context = assembler->Parameter(Descriptor::kContext); |
| 141 | 139 |
| 142 // We might need to loop once here due to ToPrimitive conversions. | 140 assembler->Return(assembler->NonNumberToNumber(context, input)); |
| 143 Variable var_input(assembler, MachineRepresentation::kTagged); | 141 } |
| 144 Label loop(assembler, &var_input); | |
| 145 var_input.Bind(input); | |
| 146 assembler->Goto(&loop); | |
| 147 assembler->Bind(&loop); | |
| 148 { | |
| 149 // Load the current {input} value (known to be a HeapObject). | |
| 150 Node* input = var_input.value(); | |
| 151 | 142 |
| 152 // Dispatch on the {input} instance type. | 143 // ES6 section 7.1.3 ToNumber ( argument ) |
| 153 Node* input_instance_type = assembler->LoadInstanceType(input); | 144 void Builtins::Generate_ToNumber(CodeStubAssembler* assembler) { |
| 154 Label if_inputisstring(assembler), if_inputisoddball(assembler), | 145 typedef compiler::Node Node; |
| 155 if_inputisreceiver(assembler, Label::kDeferred), | 146 typedef TypeConversionDescriptor Descriptor; |
| 156 if_inputisother(assembler, Label::kDeferred); | |
| 157 assembler->GotoIf(assembler->Int32LessThan( | |
| 158 input_instance_type, | |
| 159 assembler->Int32Constant(FIRST_NONSTRING_TYPE)), | |
| 160 &if_inputisstring); | |
| 161 assembler->GotoIf( | |
| 162 assembler->Word32Equal(input_instance_type, | |
| 163 assembler->Int32Constant(ODDBALL_TYPE)), | |
| 164 &if_inputisoddball); | |
| 165 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); | |
| 166 assembler->Branch(assembler->Int32GreaterThanOrEqual( | |
| 167 input_instance_type, | |
| 168 assembler->Int32Constant(FIRST_JS_RECEIVER_TYPE)), | |
| 169 &if_inputisreceiver, &if_inputisother); | |
| 170 | 147 |
| 171 assembler->Bind(&if_inputisstring); | 148 Node* input = assembler->Parameter(Descriptor::kArgument); |
| 172 { | 149 Node* context = assembler->Parameter(Descriptor::kContext); |
| 173 // The {input} is a String, use the fast stub to convert it to a Number. | |
| 174 assembler->Return(assembler->StringToNumber(context, input)); | |
| 175 } | |
| 176 | 150 |
| 177 assembler->Bind(&if_inputisoddball); | 151 assembler->Return(assembler->ToNumber(context, input)); |
| 178 { | |
| 179 // The {input} is an Oddball, we just need to the Number value of it. | |
| 180 Node* result = | |
| 181 assembler->LoadObjectField(input, Oddball::kToNumberOffset); | |
| 182 assembler->Return(result); | |
| 183 } | |
| 184 | |
| 185 assembler->Bind(&if_inputisreceiver); | |
| 186 { | |
| 187 // The {input} is a JSReceiver, we need to convert it to a Primitive first | |
| 188 // using the ToPrimitive type conversion, preferably yielding a Number. | |
| 189 Callable callable = CodeFactory::NonPrimitiveToPrimitive( | |
| 190 assembler->isolate(), ToPrimitiveHint::kNumber); | |
| 191 Node* result = assembler->CallStub(callable, context, input); | |
| 192 | |
| 193 // Check if the {result} is already a Number. | |
| 194 Label if_resultisnumber(assembler), if_resultisnotnumber(assembler); | |
| 195 assembler->GotoIf(assembler->WordIsSmi(result), &if_resultisnumber); | |
| 196 Node* result_map = assembler->LoadMap(result); | |
| 197 assembler->Branch( | |
| 198 assembler->WordEqual(result_map, assembler->HeapNumberMapConstant()), | |
| 199 &if_resultisnumber, &if_resultisnotnumber); | |
| 200 | |
| 201 assembler->Bind(&if_resultisnumber); | |
| 202 { | |
| 203 // The ToPrimitive conversion already gave us a Number, so we're done. | |
| 204 assembler->Return(result); | |
| 205 } | |
| 206 | |
| 207 assembler->Bind(&if_resultisnotnumber); | |
| 208 { | |
| 209 // We now have a Primitive {result}, but it's not yet a Number. | |
| 210 var_input.Bind(result); | |
| 211 assembler->Goto(&loop); | |
| 212 } | |
| 213 } | |
| 214 | |
| 215 assembler->Bind(&if_inputisother); | |
| 216 { | |
| 217 // The {input} is something else (i.e. Symbol or Simd128Value), let the | |
| 218 // runtime figure out the correct exception. | |
| 219 // Note: We cannot tail call to the runtime here, as js-to-wasm | |
| 220 // trampolines also use this code currently, and they declare all | |
| 221 // outgoing parameters as untagged, while we would push a tagged | |
| 222 // object here. | |
| 223 Node* result = assembler->CallRuntime(Runtime::kToNumber, context, input); | |
| 224 assembler->Return(result); | |
| 225 } | |
| 226 } | |
| 227 } | 152 } |
| 228 | 153 |
| 229 Handle<Code> Builtins::OrdinaryToPrimitive(OrdinaryToPrimitiveHint hint) { | 154 Handle<Code> Builtins::OrdinaryToPrimitive(OrdinaryToPrimitiveHint hint) { |
| 230 switch (hint) { | 155 switch (hint) { |
| 231 case OrdinaryToPrimitiveHint::kNumber: | 156 case OrdinaryToPrimitiveHint::kNumber: |
| 232 return OrdinaryToPrimitive_Number(); | 157 return OrdinaryToPrimitive_Number(); |
| 233 case OrdinaryToPrimitiveHint::kString: | 158 case OrdinaryToPrimitiveHint::kString: |
| 234 return OrdinaryToPrimitive_String(); | 159 return OrdinaryToPrimitive_String(); |
| 235 } | 160 } |
| 236 UNREACHABLE(); | 161 UNREACHABLE(); |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 334 | 259 |
| 335 assembler->Bind(&return_true); | 260 assembler->Bind(&return_true); |
| 336 assembler->Return(assembler->BooleanConstant(true)); | 261 assembler->Return(assembler->BooleanConstant(true)); |
| 337 | 262 |
| 338 assembler->Bind(&return_false); | 263 assembler->Bind(&return_false); |
| 339 assembler->Return(assembler->BooleanConstant(false)); | 264 assembler->Return(assembler->BooleanConstant(false)); |
| 340 } | 265 } |
| 341 | 266 |
| 342 } // namespace internal | 267 } // namespace internal |
| 343 } // namespace v8 | 268 } // namespace v8 |
| OLD | NEW |