5 #include "src/builtins/builtins-utils-gen.h" 6 #include "src/builtins/builtins.h" 7 #include "src/code-factory.h" 8 #include "src/code-stub-assembler.h" 9 #include "src/objects-inl.h" 20 void Generate_NonPrimitiveToPrimitive(
Node* context,
Node* input,
21 ToPrimitiveHint hint);
23 void Generate_OrdinaryToPrimitive(
Node* context,
Node* input,
24 OrdinaryToPrimitiveHint hint);
28 void ConversionBuiltinsAssembler::Generate_NonPrimitiveToPrimitive(
29 Node* context,
Node* input, ToPrimitiveHint hint) {
31 Node* exotic_to_prim =
32 GetProperty(context, input, factory()->to_primitive_symbol());
35 Label ordinary_to_primitive(
this);
36 GotoIf(IsNullOrUndefined(exotic_to_prim), &ordinary_to_primitive);
41 CodeFactory::Call(isolate(), ConvertReceiverMode::kNotNullOrUndefined);
42 Node* hint_string = HeapConstant(factory()->ToPrimitiveHintString(hint));
44 CallJS(callable, context, exotic_to_prim, input, hint_string);
47 Label if_resultisprimitive(
this),
48 if_resultisnotprimitive(
this, Label::kDeferred);
49 GotoIf(TaggedIsSmi(result), &if_resultisprimitive);
50 Node* result_instance_type = LoadInstanceType(result);
51 Branch(IsPrimitiveInstanceType(result_instance_type), &if_resultisprimitive,
52 &if_resultisnotprimitive);
54 BIND(&if_resultisprimitive);
60 BIND(&if_resultisnotprimitive);
63 ThrowTypeError(context, MessageTemplate::kCannotConvertToPrimitive);
68 BIND(&ordinary_to_primitive);
70 Callable callable = CodeFactory::OrdinaryToPrimitive(
71 isolate(), (hint == ToPrimitiveHint::kString)
72 ? OrdinaryToPrimitiveHint::kString
73 : OrdinaryToPrimitiveHint::kNumber);
74 TailCallStub(callable, context, input);
78 TF_BUILTIN(NonPrimitiveToPrimitive_Default, ConversionBuiltinsAssembler) {
79 Node* context = Parameter(Descriptor::kContext);
80 Node* input = Parameter(Descriptor::kArgument);
82 Generate_NonPrimitiveToPrimitive(context, input, ToPrimitiveHint::kDefault);
85 TF_BUILTIN(NonPrimitiveToPrimitive_Number, ConversionBuiltinsAssembler) {
86 Node* context = Parameter(Descriptor::kContext);
87 Node* input = Parameter(Descriptor::kArgument);
89 Generate_NonPrimitiveToPrimitive(context, input, ToPrimitiveHint::kNumber);
92 TF_BUILTIN(NonPrimitiveToPrimitive_String, ConversionBuiltinsAssembler) {
93 Node* context = Parameter(Descriptor::kContext);
94 Node* input = Parameter(Descriptor::kArgument);
96 Generate_NonPrimitiveToPrimitive(context, input, ToPrimitiveHint::kString);
99 TF_BUILTIN(StringToNumber, CodeStubAssembler) {
100 TNode<String> input = CAST(Parameter(Descriptor::kArgument));
102 Return(StringToNumber(input));
105 TF_BUILTIN(ToName, CodeStubAssembler) {
106 Node* context = Parameter(Descriptor::kContext);
107 Node* input = Parameter(Descriptor::kArgument);
109 VARIABLE(var_input, MachineRepresentation::kTagged, input);
110 Label loop(
this, &var_input);
115 Node* input = var_input.value();
118 Label if_inputisbigint(
this), if_inputisname(
this), if_inputisnumber(
this),
119 if_inputisoddball(
this), if_inputisreceiver(
this, Label::kDeferred);
120 GotoIf(TaggedIsSmi(input), &if_inputisnumber);
121 Node* input_instance_type = LoadInstanceType(input);
122 STATIC_ASSERT(FIRST_NAME_TYPE == FIRST_TYPE);
123 GotoIf(IsNameInstanceType(input_instance_type), &if_inputisname);
124 GotoIf(IsJSReceiverInstanceType(input_instance_type), &if_inputisreceiver);
125 GotoIf(IsHeapNumberInstanceType(input_instance_type), &if_inputisnumber);
126 Branch(IsBigIntInstanceType(input_instance_type), &if_inputisbigint,
129 BIND(&if_inputisbigint);
133 TailCallRuntime(Runtime::kToString, context, input);
136 BIND(&if_inputisname);
142 BIND(&if_inputisnumber);
145 TailCallBuiltin(Builtins::kNumberToString, context, input);
148 BIND(&if_inputisoddball);
151 CSA_ASSERT(
this, IsOddballInstanceType(input_instance_type));
152 Return(LoadObjectField(input, Oddball::kToStringOffset));
155 BIND(&if_inputisreceiver);
160 var_input.Bind(CallBuiltin(Builtins::kNonPrimitiveToPrimitive_String,
167 TF_BUILTIN(NonNumberToNumber, CodeStubAssembler) {
168 Node* context = Parameter(Descriptor::kContext);
169 Node* input = Parameter(Descriptor::kArgument);
171 Return(NonNumberToNumber(context, input));
174 TF_BUILTIN(NonNumberToNumeric, CodeStubAssembler) {
175 Node* context = Parameter(Descriptor::kContext);
176 Node* input = Parameter(Descriptor::kArgument);
178 Return(NonNumberToNumeric(context, input));
181 TF_BUILTIN(ToNumeric, CodeStubAssembler) {
182 TNode<Context> context = CAST(Parameter(Descriptor::kContext));
183 TNode<Object> input = CAST(Parameter(Descriptor::kArgument));
185 Return(Select<Numeric>(
186 IsNumber(input), [=] {
return CAST(input); },
187 [=] {
return NonNumberToNumeric(context, CAST(input)); }));
191 TF_BUILTIN(ToNumber, CodeStubAssembler) {
192 Node* context = Parameter(Descriptor::kContext);
193 Node* input = Parameter(Descriptor::kArgument);
195 Return(ToNumber(context, input));
199 TF_BUILTIN(ToNumberConvertBigInt, CodeStubAssembler) {
200 Node* context = Parameter(Descriptor::kContext);
201 Node* input = Parameter(Descriptor::kArgument);
203 Return(ToNumber(context, input, BigIntHandling::kConvertToNumber));
207 TF_BUILTIN(NumberToString, CodeStubAssembler) {
208 TNode<Number> input = CAST(Parameter(Descriptor::kArgument));
210 Return(NumberToString(input));
214 TF_BUILTIN(ToString, CodeStubAssembler) {
215 Node* context = Parameter(Descriptor::kContext);
216 Node* input = Parameter(Descriptor::kArgument);
218 Return(ToString(context, input));
222 void ConversionBuiltinsAssembler::Generate_OrdinaryToPrimitive(
223 Node* context, Node* input, OrdinaryToPrimitiveHint hint) {
224 VARIABLE(var_result, MachineRepresentation::kTagged);
225 Label return_result(
this, &var_result);
227 Handle<String> method_names[2];
229 case OrdinaryToPrimitiveHint::kNumber:
230 method_names[0] = factory()->valueOf_string();
231 method_names[1] = factory()->toString_string();
233 case OrdinaryToPrimitiveHint::kString:
234 method_names[0] = factory()->toString_string();
235 method_names[1] = factory()->valueOf_string();
238 for (Handle<String> name : method_names) {
240 Node* method = GetProperty(context, input, name);
243 Label if_methodiscallable(
this),
244 if_methodisnotcallable(
this, Label::kDeferred);
245 GotoIf(TaggedIsSmi(method), &if_methodisnotcallable);
246 Node* method_map = LoadMap(method);
247 Branch(IsCallableMap(method_map), &if_methodiscallable,
248 &if_methodisnotcallable);
250 BIND(&if_methodiscallable);
253 Callable callable = CodeFactory::Call(
254 isolate(), ConvertReceiverMode::kNotNullOrUndefined);
255 Node* result = CallJS(callable, context, method, input);
256 var_result.Bind(result);
259 GotoIf(TaggedIsSmi(result), &return_result);
260 Node* result_instance_type = LoadInstanceType(result);
261 GotoIf(IsPrimitiveInstanceType(result_instance_type), &return_result);
265 Goto(&if_methodisnotcallable);
266 BIND(&if_methodisnotcallable);
269 ThrowTypeError(context, MessageTemplate::kCannotConvertToPrimitive);
271 BIND(&return_result);
272 Return(var_result.value());
275 TF_BUILTIN(OrdinaryToPrimitive_Number, ConversionBuiltinsAssembler) {
276 Node* context = Parameter(Descriptor::kContext);
277 Node* input = Parameter(Descriptor::kArgument);
278 Generate_OrdinaryToPrimitive(context, input,
279 OrdinaryToPrimitiveHint::kNumber);
282 TF_BUILTIN(OrdinaryToPrimitive_String, ConversionBuiltinsAssembler) {
283 Node* context = Parameter(Descriptor::kContext);
284 Node* input = Parameter(Descriptor::kArgument);
285 Generate_OrdinaryToPrimitive(context, input,
286 OrdinaryToPrimitiveHint::kString);
290 TF_BUILTIN(ToBoolean, CodeStubAssembler) {
291 Node* value = Parameter(Descriptor::kArgument);
293 Label return_true(
this), return_false(
this);
294 BranchIfToBooleanIsTrue(value, &return_true, &return_false);
297 Return(TrueConstant());
300 Return(FalseConstant());
306 TF_BUILTIN(ToBooleanLazyDeoptContinuation, CodeStubAssembler) {
307 Node* value = Parameter(Descriptor::kArgument);
309 Label return_true(
this), return_false(
this);
310 BranchIfToBooleanIsTrue(value, &return_true, &return_false);
313 Return(TrueConstant());
316 Return(FalseConstant());
319 TF_BUILTIN(ToLength, CodeStubAssembler) {
320 Node* context = Parameter(Descriptor::kContext);
323 VARIABLE(var_len, MachineRepresentation::kTagged,
324 Parameter(Descriptor::kArgument));
325 Label loop(
this, &var_len);
330 Label return_len(
this), return_two53minus1(
this, Label::kDeferred),
331 return_zero(
this, Label::kDeferred);
334 Node* len = var_len.value();
337 GotoIf(TaggedIsPositiveSmi(len), &return_len);
340 GotoIf(TaggedIsSmi(len), &return_zero);
343 Label if_lenisheapnumber(
this),
344 if_lenisnotheapnumber(
this, Label::kDeferred);
345 Branch(IsHeapNumber(len), &if_lenisheapnumber, &if_lenisnotheapnumber);
347 BIND(&if_lenisheapnumber);
350 Node* len_value = LoadHeapNumberValue(len);
353 GotoIfNot(Float64GreaterThan(len_value, Float64Constant(0.0)),
357 GotoIf(Float64GreaterThanOrEqual(len_value,
358 Float64Constant(kMaxSafeInteger)),
359 &return_two53minus1);
362 Node* value = Float64Floor(len_value);
363 Node* result = ChangeFloat64ToTagged(value);
367 BIND(&if_lenisnotheapnumber);
370 var_len.Bind(CallBuiltin(Builtins::kNonNumberToNumber, context, len));
375 Return(var_len.value());
377 BIND(&return_two53minus1);
378 Return(NumberConstant(kMaxSafeInteger));
381 Return(SmiConstant(0));
385 TF_BUILTIN(ToInteger, CodeStubAssembler) {
386 Node* context = Parameter(Descriptor::kContext);
387 Node* input = Parameter(Descriptor::kArgument);
389 Return(ToInteger(context, input, kNoTruncation));
392 TF_BUILTIN(ToInteger_TruncateMinusZero, CodeStubAssembler) {
393 Node* context = Parameter(Descriptor::kContext);
394 Node* input = Parameter(Descriptor::kArgument);
396 Return(ToInteger(context, input, kTruncateMinusZero));
400 TF_BUILTIN(ToObject, CodeStubAssembler) {
401 Label if_smi(
this, Label::kDeferred), if_jsreceiver(
this),
402 if_noconstructor(
this, Label::kDeferred), if_wrapjsvalue(
this);
404 Node* context = Parameter(Descriptor::kContext);
405 Node*
object = Parameter(Descriptor::kArgument);
407 VARIABLE(constructor_function_index_var,
408 MachineType::PointerRepresentation());
410 GotoIf(TaggedIsSmi(
object), &if_smi);
412 Node* map = LoadMap(
object);
413 Node* instance_type = LoadMapInstanceType(map);
414 GotoIf(IsJSReceiverInstanceType(instance_type), &if_jsreceiver);
416 Node* constructor_function_index = LoadMapConstructorFunctionIndex(map);
417 GotoIf(WordEqual(constructor_function_index,
418 IntPtrConstant(Map::kNoConstructorFunctionIndex)),
420 constructor_function_index_var.Bind(constructor_function_index);
421 Goto(&if_wrapjsvalue);
424 constructor_function_index_var.Bind(
425 IntPtrConstant(Context::NUMBER_FUNCTION_INDEX));
426 Goto(&if_wrapjsvalue);
428 BIND(&if_wrapjsvalue);
429 TNode<Context> native_context = LoadNativeContext(context);
430 Node* constructor = LoadContextElement(
431 native_context, constructor_function_index_var.value());
433 LoadObjectField(constructor, JSFunction::kPrototypeOrInitialMapOffset);
434 Node* js_value = Allocate(JSValue::kSize);
435 StoreMapNoWriteBarrier(js_value, initial_map);
436 StoreObjectFieldRoot(js_value, JSValue::kPropertiesOrHashOffset,
437 RootIndex::kEmptyFixedArray);
438 StoreObjectFieldRoot(js_value, JSObject::kElementsOffset,
439 RootIndex::kEmptyFixedArray);
440 StoreObjectField(js_value, JSValue::kValueOffset,
object);
443 BIND(&if_noconstructor);
444 ThrowTypeError(context, MessageTemplate::kUndefinedOrNullToObject,
447 BIND(&if_jsreceiver);
452 TF_BUILTIN(Typeof, CodeStubAssembler) {
453 Node*
object = Parameter(Descriptor::kObject);
455 Return(Typeof(
object));