5 #include "src/builtins/builtins-math-gen.h" 6 #include "src/builtins/builtins-utils-gen.h" 7 #include "src/builtins/builtins.h" 8 #include "src/code-stub-assembler.h" 9 #include "src/ic/binary-op-assembler.h" 23 template <
typename Descriptor>
24 void EmitBitwiseOp(Operation op) {
25 Node* left = Parameter(Descriptor::kLeft);
26 Node* right = Parameter(Descriptor::kRight);
27 Node* context = Parameter(Descriptor::kContext);
29 VARIABLE(var_left_word32, MachineRepresentation::kWord32);
30 VARIABLE(var_right_word32, MachineRepresentation::kWord32);
31 VARIABLE(var_left_bigint, MachineRepresentation::kTagged, left);
32 VARIABLE(var_right_bigint, MachineRepresentation::kTagged);
33 Label if_left_number(
this), do_number_op(
this);
34 Label if_left_bigint(
this), do_bigint_op(
this);
36 TaggedToWord32OrBigInt(context, left, &if_left_number, &var_left_word32,
37 &if_left_bigint, &var_left_bigint);
38 BIND(&if_left_number);
39 TaggedToWord32OrBigInt(context, right, &do_number_op, &var_right_word32,
40 &do_bigint_op, &var_right_bigint);
42 Return(BitwiseOp(var_left_word32.value(), var_right_word32.value(), op));
45 BIND(&if_left_bigint);
46 TaggedToNumeric(context, right, &do_bigint_op, &var_right_bigint);
49 Return(
CallRuntime(Runtime::kBigIntBinaryOp, context,
50 var_left_bigint.value(), var_right_bigint.value(),
54 template <
typename Descriptor>
55 void RelationalComparisonBuiltin(Operation op) {
56 Node* lhs = Parameter(Descriptor::kLeft);
57 Node* rhs = Parameter(Descriptor::kRight);
58 Node* context = Parameter(Descriptor::kContext);
60 Return(RelationalComparison(op, lhs, rhs, context));
63 template <
typename Descriptor>
67 template <
typename Descriptor>
75 Node* number = Parameter(Descriptor::kNumber);
77 Label return_true(
this), return_false(
this);
80 GotoIf(TaggedIsSmi(number), &return_true);
83 GotoIfNot(IsHeapNumber(number), &return_false);
86 Node* number_value = LoadHeapNumberValue(number);
87 BranchIfFloat64IsNaN(Float64Sub(number_value, number_value), &return_false,
91 Return(TrueConstant());
94 Return(FalseConstant());
97 TF_BUILTIN(AllocateHeapNumber, CodeStubAssembler) {
98 Node* result = AllocateHeapNumber();
103 TF_BUILTIN(NumberIsInteger, CodeStubAssembler) {
104 TNode<Object> number = CAST(Parameter(Descriptor::kNumber));
105 Return(SelectBooleanConstant(IsInteger(number)));
109 TF_BUILTIN(NumberIsNaN, CodeStubAssembler) {
110 Node* number = Parameter(Descriptor::kNumber);
112 Label return_true(
this), return_false(
this);
115 GotoIf(TaggedIsSmi(number), &return_false);
118 GotoIfNot(IsHeapNumber(number), &return_false);
121 Node* number_value = LoadHeapNumberValue(number);
122 BranchIfFloat64IsNaN(number_value, &return_true, &return_false);
125 Return(TrueConstant());
128 Return(FalseConstant());
132 TF_BUILTIN(NumberIsSafeInteger, CodeStubAssembler) {
133 TNode<Object> number = CAST(Parameter(Descriptor::kNumber));
134 Return(SelectBooleanConstant(IsSafeInteger(number)));
138 TF_BUILTIN(NumberParseFloat, CodeStubAssembler) {
139 Node* context = Parameter(Descriptor::kContext);
142 VARIABLE(var_input, MachineRepresentation::kTagged,
143 Parameter(Descriptor::kString));
144 Label loop(
this, &var_input);
149 Node* input = var_input.value();
152 Label if_inputissmi(
this), if_inputisnotsmi(
this);
153 Branch(TaggedIsSmi(input), &if_inputissmi, &if_inputisnotsmi);
155 BIND(&if_inputissmi);
161 BIND(&if_inputisnotsmi);
164 Label if_inputisstring(
this), if_inputisnotstring(
this);
165 Node* input_map = LoadMap(input);
166 Node* input_instance_type = LoadMapInstanceType(input_map);
167 Branch(IsStringInstanceType(input_instance_type), &if_inputisstring,
168 &if_inputisnotstring);
170 BIND(&if_inputisstring);
174 Label if_inputcached(
this), if_inputnotcached(
this);
175 Node* input_hash = LoadNameHashField(input);
176 Branch(IsClearWord32(input_hash,
177 Name::kDoesNotContainCachedArrayIndexMask),
178 &if_inputcached, &if_inputnotcached);
180 BIND(&if_inputcached);
183 Node* input_array_index =
184 DecodeWordFromWord32<String::ArrayIndexValueBits>(input_hash);
185 Return(SmiTag(input_array_index));
188 BIND(&if_inputnotcached);
191 Return(CallRuntime(Runtime::kStringParseFloat, context, input));
195 BIND(&if_inputisnotstring);
198 Label if_inputisnumber(
this),
199 if_inputisnotnumber(
this, Label::kDeferred);
200 Branch(IsHeapNumberMap(input_map), &if_inputisnumber,
201 &if_inputisnotnumber);
203 BIND(&if_inputisnumber);
206 Label if_inputiszero(
this), if_inputisnotzero(
this);
207 Node* input_value = LoadHeapNumberValue(input);
208 Branch(Float64Equal(input_value, Float64Constant(0.0)),
209 &if_inputiszero, &if_inputisnotzero);
211 BIND(&if_inputiszero);
212 Return(SmiConstant(0));
214 BIND(&if_inputisnotzero);
218 BIND(&if_inputisnotnumber);
222 var_input.Bind(CallBuiltin(Builtins::kToString, context, input));
231 TF_BUILTIN(ParseInt, CodeStubAssembler) {
232 Node* context = Parameter(Descriptor::kContext);
233 Node* input = Parameter(Descriptor::kString);
234 Node* radix = Parameter(Descriptor::kRadix);
237 Label if_radix10(
this), if_generic(
this, Label::kDeferred);
238 GotoIf(IsUndefined(radix), &if_radix10);
239 GotoIf(WordEqual(radix, SmiConstant(10)), &if_radix10);
240 GotoIf(WordEqual(radix, SmiConstant(0)), &if_radix10);
246 Label if_inputissmi(
this), if_inputisheapnumber(
this),
247 if_inputisstring(
this);
248 GotoIf(TaggedIsSmi(input), &if_inputissmi);
249 Node* input_map = LoadMap(input);
250 GotoIf(IsHeapNumberMap(input_map), &if_inputisheapnumber);
251 Node* input_instance_type = LoadMapInstanceType(input_map);
252 Branch(IsStringInstanceType(input_instance_type), &if_inputisstring,
255 BIND(&if_inputissmi);
261 BIND(&if_inputisheapnumber);
264 Label if_inputissigned32(
this);
265 Node* input_value = LoadHeapNumberValue(input);
266 Node* input_value32 = TruncateFloat64ToWord32(input_value);
267 GotoIf(Float64Equal(input_value, ChangeInt32ToFloat64(input_value32)),
268 &if_inputissigned32);
273 Node* input_value_abs = Float64Abs(input_value);
275 GotoIfNot(Float64LessThan(input_value_abs, Float64Constant(1u << 31)),
277 Branch(Float64LessThanOrEqual(Float64Constant(1), input_value_abs),
278 &if_inputissigned32, &if_generic);
281 BIND(&if_inputissigned32);
282 Node* result = ChangeInt32ToTagged(input_value32);
286 BIND(&if_inputisstring);
289 Node* input_hash = LoadNameHashField(input);
290 GotoIf(IsSetWord32(input_hash, Name::kDoesNotContainCachedArrayIndexMask),
295 DecodeWordFromWord32<String::ArrayIndexValueBits>(input_hash);
296 Node* result = SmiTag(input_index);
303 Node* result = CallRuntime(Runtime::kStringParseInt, context, input, radix);
309 TF_BUILTIN(NumberParseInt, CodeStubAssembler) {
310 Node* context = Parameter(Descriptor::kContext);
311 Node* input = Parameter(Descriptor::kString);
312 Node* radix = Parameter(Descriptor::kRadix);
313 Return(CallBuiltin(Builtins::kParseInt, context, input, radix));
317 TF_BUILTIN(NumberPrototypeValueOf, CodeStubAssembler) {
318 Node* context = Parameter(Descriptor::kContext);
319 Node* receiver = Parameter(Descriptor::kReceiver);
321 Node* result = ToThisValue(context, receiver, PrimitiveType::kNumber,
322 "Number.prototype.valueOf");
335 Callable callable = CodeFactory::NonPrimitiveToPrimitive(isolate());
336 var_value->Bind(CallStub(callable, context, var_value->value()));
340 void ConvertNonReceiverAndLoop(
Variable* var_value,
Label* loop,
342 var_value->Bind(CallBuiltin(Builtins::kNonNumberToNumeric, context,
343 var_value->value()));
349 Label is_not_receiver(
this, Label::kDeferred);
350 GotoIfNot(IsJSReceiverInstanceType(instance_type), &is_not_receiver);
352 ConvertReceiverAndLoop(var_value, loop, context);
354 BIND(&is_not_receiver);
355 ConvertNonReceiverAndLoop(var_value, loop, context);
360 Node* context = Parameter(Descriptor::kContext);
361 VARIABLE(var_left, MachineRepresentation::kTagged,
362 Parameter(Descriptor::kLeft));
363 VARIABLE(var_right, MachineRepresentation::kTagged,
364 Parameter(Descriptor::kRight));
367 Label do_double_add(
this);
368 VARIABLE(var_left_double, MachineRepresentation::kFloat64);
369 VARIABLE(var_right_double, MachineRepresentation::kFloat64);
373 VARIABLE(var_result, MachineRepresentation::kTagged);
374 Variable* loop_vars[2] = {&var_left, &var_right};
375 Label loop(
this, 2, loop_vars),
376 string_add_convert_left(
this, Label::kDeferred),
377 string_add_convert_right(
this, Label::kDeferred),
378 do_bigint_add(
this, Label::kDeferred);
382 Node* left = var_left.value();
383 Node* right = var_right.value();
385 Label if_left_smi(
this), if_left_heapobject(
this);
386 Branch(TaggedIsSmi(left), &if_left_smi, &if_left_heapobject);
390 Label if_right_smi(
this), if_right_heapobject(
this);
391 Branch(TaggedIsSmi(right), &if_right_smi, &if_right_heapobject);
395 Label if_overflow(
this);
396 TNode<Smi> result = TrySmiAdd(CAST(left), CAST(right), &if_overflow);
401 var_left_double.Bind(SmiToFloat64(left));
402 var_right_double.Bind(SmiToFloat64(right));
403 Goto(&do_double_add);
407 BIND(&if_right_heapobject);
409 Node* right_map = LoadMap(right);
411 Label if_right_not_number(
this, Label::kDeferred);
412 GotoIfNot(IsHeapNumberMap(right_map), &if_right_not_number);
415 var_left_double.Bind(SmiToFloat64(left));
416 var_right_double.Bind(LoadHeapNumberValue(right));
417 Goto(&do_double_add);
419 BIND(&if_right_not_number);
421 Node* right_instance_type = LoadMapInstanceType(right_map);
422 GotoIf(IsStringInstanceType(right_instance_type),
423 &string_add_convert_left);
424 GotoIf(IsBigIntInstanceType(right_instance_type), &do_bigint_add);
425 ConvertAndLoop(&var_right, right_instance_type, &loop, context);
430 BIND(&if_left_heapobject);
432 Node* left_map = LoadMap(left);
433 Label if_right_smi(
this), if_right_heapobject(
this);
434 Branch(TaggedIsSmi(right), &if_right_smi, &if_right_heapobject);
438 Label if_left_not_number(
this, Label::kDeferred);
439 GotoIfNot(IsHeapNumberMap(left_map), &if_left_not_number);
442 var_left_double.Bind(LoadHeapNumberValue(left));
443 var_right_double.Bind(SmiToFloat64(right));
444 Goto(&do_double_add);
446 BIND(&if_left_not_number);
448 Node* left_instance_type = LoadMapInstanceType(left_map);
449 GotoIf(IsStringInstanceType(left_instance_type),
450 &string_add_convert_right);
451 GotoIf(IsBigIntInstanceType(left_instance_type), &do_bigint_add);
453 ConvertAndLoop(&var_left, left_instance_type, &loop, context);
457 BIND(&if_right_heapobject);
459 Node* right_map = LoadMap(right);
461 Label if_left_number(
this), if_left_not_number(
this, Label::kDeferred);
462 Branch(IsHeapNumberMap(left_map), &if_left_number, &if_left_not_number);
464 BIND(&if_left_number);
466 Label if_right_not_number(
this, Label::kDeferred);
467 GotoIfNot(IsHeapNumberMap(right_map), &if_right_not_number);
470 var_left_double.Bind(LoadHeapNumberValue(left));
471 var_right_double.Bind(LoadHeapNumberValue(right));
472 Goto(&do_double_add);
474 BIND(&if_right_not_number);
476 Node* right_instance_type = LoadMapInstanceType(right_map);
477 GotoIf(IsStringInstanceType(right_instance_type),
478 &string_add_convert_left);
479 GotoIf(IsBigIntInstanceType(right_instance_type), &do_bigint_add);
481 ConvertAndLoop(&var_right, right_instance_type, &loop, context);
485 BIND(&if_left_not_number);
487 Label if_left_bigint(
this);
488 Node* left_instance_type = LoadMapInstanceType(left_map);
489 GotoIf(IsStringInstanceType(left_instance_type),
490 &string_add_convert_right);
491 Node* right_instance_type = LoadMapInstanceType(right_map);
492 GotoIf(IsStringInstanceType(right_instance_type),
493 &string_add_convert_left);
494 GotoIf(IsBigIntInstanceType(left_instance_type), &if_left_bigint);
495 Label if_left_not_receiver(
this, Label::kDeferred);
496 Label if_right_not_receiver(
this, Label::kDeferred);
497 GotoIfNot(IsJSReceiverInstanceType(left_instance_type),
498 &if_left_not_receiver);
500 ConvertReceiverAndLoop(&var_left, &loop, context);
502 BIND(&if_left_bigint);
506 GotoIf(IsBigIntInstanceType(right_instance_type), &do_bigint_add);
507 GotoIf(IsHeapNumberMap(right_map), &do_bigint_add);
508 ConvertAndLoop(&var_right, right_instance_type, &loop, context);
511 BIND(&if_left_not_receiver);
512 GotoIfNot(IsJSReceiverInstanceType(right_instance_type),
513 &if_right_not_receiver);
516 ConvertReceiverAndLoop(&var_right, &loop, context);
518 BIND(&if_right_not_receiver);
520 ConvertNonReceiverAndLoop(&var_left, &loop, context);
525 BIND(&string_add_convert_left);
528 TailCallBuiltin(Builtins::kStringAdd_ConvertLeft, context, var_left.value(),
532 BIND(&string_add_convert_right);
535 TailCallBuiltin(Builtins::kStringAdd_ConvertRight, context,
536 var_left.value(), var_right.value());
539 BIND(&do_bigint_add);
541 Return(CallRuntime(Runtime::kBigIntBinaryOp, context, var_left.value(),
542 var_right.value(), SmiConstant(Operation::kAdd)));
545 BIND(&do_double_add);
547 Node* value = Float64Add(var_left_double.value(), var_right_double.value());
548 Return(AllocateHeapNumberWithValue(value));
552 template <
typename Descriptor>
553 void NumberBuiltinsAssembler::UnaryOp(Variable* var_input, Label* do_smi,
555 Variable* var_input_double,
557 DCHECK_EQ(var_input->rep(), MachineRepresentation::kTagged);
558 DCHECK_IMPLIES(var_input_double !=
nullptr,
559 var_input_double->rep() == MachineRepresentation::kFloat64);
561 Node* context = Parameter(Descriptor::kContext);
562 var_input->Bind(Parameter(Descriptor::kValue));
565 Label loop(
this, {var_input});
568 Node* input = var_input->value();
570 Label not_number(
this);
571 GotoIf(TaggedIsSmi(input), do_smi);
572 GotoIfNot(IsHeapNumber(input), ¬_number);
573 if (var_input_double !=
nullptr) {
574 var_input_double->Bind(LoadHeapNumberValue(input));
579 GotoIf(IsBigInt(input), do_bigint);
580 var_input->Bind(CallBuiltin(Builtins::kNonNumberToNumeric, context, input));
584 template <
typename Descriptor>
585 void NumberBuiltinsAssembler::BinaryOp(Label* smis, Variable* var_left,
586 Variable* var_right, Label* doubles,
587 Variable* var_left_double,
588 Variable* var_right_double,
590 DCHECK_EQ(var_left->rep(), MachineRepresentation::kTagged);
591 DCHECK_EQ(var_right->rep(), MachineRepresentation::kTagged);
592 DCHECK_IMPLIES(var_left_double !=
nullptr,
593 var_left_double->rep() == MachineRepresentation::kFloat64);
594 DCHECK_IMPLIES(var_right_double !=
nullptr,
595 var_right_double->rep() == MachineRepresentation::kFloat64);
596 DCHECK_EQ(var_left_double ==
nullptr, var_right_double ==
nullptr);
598 Node* context = Parameter(Descriptor::kContext);
599 var_left->Bind(Parameter(Descriptor::kLeft));
600 var_right->Bind(Parameter(Descriptor::kRight));
603 Label loop(
this, {var_left, var_right});
607 Label left_not_smi(
this), right_not_smi(
this);
608 Label left_not_number(
this), right_not_number(
this);
609 GotoIfNot(TaggedIsSmi(var_left->value()), &left_not_smi);
610 GotoIf(TaggedIsSmi(var_right->value()), smis);
613 GotoIfNot(IsHeapNumber(var_right->value()), &right_not_number);
614 if (var_left_double !=
nullptr) {
615 var_left_double->Bind(SmiToFloat64(var_left->value()));
616 var_right_double->Bind(LoadHeapNumberValue(var_right->value()));
622 GotoIfNot(IsHeapNumber(var_left->value()), &left_not_number);
623 GotoIfNot(TaggedIsSmi(var_right->value()), &right_not_smi);
626 if (var_left_double !=
nullptr) {
627 var_left_double->Bind(LoadHeapNumberValue(var_left->value()));
628 var_right_double->Bind(SmiToFloat64(var_right->value()));
633 BIND(&right_not_smi);
635 GotoIfNot(IsHeapNumber(var_right->value()), &right_not_number);
636 if (var_left_double !=
nullptr) {
637 var_left_double->Bind(LoadHeapNumberValue(var_left->value()));
638 var_right_double->Bind(LoadHeapNumberValue(var_right->value()));
643 BIND(&left_not_number);
645 Label left_bigint(
this);
646 GotoIf(IsBigInt(var_left->value()), &left_bigint);
648 CallBuiltin(Builtins::kNonNumberToNumeric, context, var_left->value()));
654 GotoIf(TaggedIsSmi(var_right->value()), bigints);
655 GotoIf(IsBigInt(var_right->value()), bigints);
656 GotoIf(IsHeapNumber(var_right->value()), bigints);
657 var_right->Bind(CallBuiltin(Builtins::kNonNumberToNumeric, context,
658 var_right->value()));
663 BIND(&right_not_number);
665 GotoIf(IsBigInt(var_right->value()), bigints);
666 var_right->Bind(CallBuiltin(Builtins::kNonNumberToNumeric, context,
667 var_right->value()));
672 TF_BUILTIN(Subtract, NumberBuiltinsAssembler) {
673 VARIABLE(var_left, MachineRepresentation::kTagged);
674 VARIABLE(var_right, MachineRepresentation::kTagged);
675 VARIABLE(var_left_double, MachineRepresentation::kFloat64);
676 VARIABLE(var_right_double, MachineRepresentation::kFloat64);
677 Label do_smi_sub(
this), do_double_sub(
this), do_bigint_sub(
this);
679 BinaryOp<Descriptor>(&do_smi_sub, &var_left, &var_right, &do_double_sub,
680 &var_left_double, &var_right_double, &do_bigint_sub);
684 Label if_overflow(
this);
685 TNode<Smi> result = TrySmiSub(CAST(var_left.value()),
686 CAST(var_right.value()), &if_overflow);
691 var_left_double.Bind(SmiToFloat64(var_left.value()));
692 var_right_double.Bind(SmiToFloat64(var_right.value()));
693 Goto(&do_double_sub);
697 BIND(&do_double_sub);
699 Node* value = Float64Sub(var_left_double.value(), var_right_double.value());
700 Return(AllocateHeapNumberWithValue(value));
703 BIND(&do_bigint_sub);
705 Node* context = Parameter(Descriptor::kContext);
706 Return(CallRuntime(Runtime::kBigIntBinaryOp, context, var_left.value(),
707 var_right.value(), SmiConstant(Operation::kSubtract)));
711 TF_BUILTIN(BitwiseNot, NumberBuiltinsAssembler) {
712 Node* context = Parameter(Descriptor::kContext);
713 VARIABLE(var_input, MachineRepresentation::kTagged);
714 Label do_number(
this), do_bigint(
this);
716 UnaryOp<Descriptor>(&var_input, &do_number, &do_number,
nullptr, &do_bigint);
720 TailCallBuiltin(Builtins::kBitwiseXor, context, var_input.value(),
726 Return(CallRuntime(Runtime::kBigIntUnaryOp, context, var_input.value(),
727 SmiConstant(Operation::kBitwiseNot)));
731 TF_BUILTIN(Decrement, NumberBuiltinsAssembler) {
732 Node* context = Parameter(Descriptor::kContext);
733 VARIABLE(var_input, MachineRepresentation::kTagged);
734 Label do_number(
this), do_bigint(
this);
736 UnaryOp<Descriptor>(&var_input, &do_number, &do_number,
nullptr, &do_bigint);
740 TailCallBuiltin(Builtins::kSubtract, context, var_input.value(),
746 Return(CallRuntime(Runtime::kBigIntUnaryOp, context, var_input.value(),
747 SmiConstant(Operation::kDecrement)));
751 TF_BUILTIN(Increment, NumberBuiltinsAssembler) {
752 Node* context = Parameter(Descriptor::kContext);
753 VARIABLE(var_input, MachineRepresentation::kTagged);
754 Label do_number(
this), do_bigint(
this);
756 UnaryOp<Descriptor>(&var_input, &do_number, &do_number,
nullptr, &do_bigint);
760 TailCallBuiltin(Builtins::kAdd, context, var_input.value(), SmiConstant(1));
765 Return(CallRuntime(Runtime::kBigIntUnaryOp, context, var_input.value(),
766 SmiConstant(Operation::kIncrement)));
770 TF_BUILTIN(Negate, NumberBuiltinsAssembler) {
771 VARIABLE(var_input, MachineRepresentation::kTagged);
772 VARIABLE(var_input_double, MachineRepresentation::kFloat64);
773 Label do_smi(
this), do_double(
this), do_bigint(
this);
775 UnaryOp<Descriptor>(&var_input, &do_smi, &do_double, &var_input_double,
779 { Return(SmiMul(CAST(var_input.value()), SmiConstant(-1))); }
783 Node* value = Float64Mul(var_input_double.value(), Float64Constant(-1));
784 Return(AllocateHeapNumberWithValue(value));
789 Node* context = Parameter(Descriptor::kContext);
790 Return(CallRuntime(Runtime::kBigIntUnaryOp, context, var_input.value(),
791 SmiConstant(Operation::kNegate)));
795 TF_BUILTIN(Multiply, NumberBuiltinsAssembler) {
796 VARIABLE(var_left, MachineRepresentation::kTagged);
797 VARIABLE(var_right, MachineRepresentation::kTagged);
798 VARIABLE(var_left_double, MachineRepresentation::kFloat64);
799 VARIABLE(var_right_double, MachineRepresentation::kFloat64);
800 Label do_smi_mul(
this), do_double_mul(
this), do_bigint_mul(
this);
802 BinaryOp<Descriptor>(&do_smi_mul, &var_left, &var_right, &do_double_mul,
803 &var_left_double, &var_right_double, &do_bigint_mul);
807 Return(SmiMul(CAST(var_left.value()), CAST(var_right.value())));
809 BIND(&do_double_mul);
810 Node* value = Float64Mul(var_left_double.value(), var_right_double.value());
811 Return(AllocateHeapNumberWithValue(value));
813 BIND(&do_bigint_mul);
815 Node* context = Parameter(Descriptor::kContext);
816 Return(CallRuntime(Runtime::kBigIntBinaryOp, context, var_left.value(),
817 var_right.value(), SmiConstant(Operation::kMultiply)));
821 TF_BUILTIN(Divide, NumberBuiltinsAssembler) {
822 VARIABLE(var_left, MachineRepresentation::kTagged);
823 VARIABLE(var_right, MachineRepresentation::kTagged);
824 VARIABLE(var_left_double, MachineRepresentation::kFloat64);
825 VARIABLE(var_right_double, MachineRepresentation::kFloat64);
826 Label do_smi_div(
this), do_double_div(
this), do_bigint_div(
this);
828 BinaryOp<Descriptor>(&do_smi_div, &var_left, &var_right, &do_double_div,
829 &var_left_double, &var_right_double, &do_bigint_div);
835 TNode<Smi> dividend = CAST(var_left.value());
836 TNode<Smi> divisor = CAST(var_right.value());
839 GotoIf(SmiEqual(divisor, SmiConstant(0)), &bailout);
843 Label dividend_is_zero(
this), dividend_is_not_zero(
this);
844 Branch(SmiEqual(dividend, SmiConstant(0)), ÷nd_is_zero,
845 ÷nd_is_not_zero);
847 BIND(÷nd_is_zero);
849 GotoIf(SmiLessThan(divisor, SmiConstant(0)), &bailout);
850 Goto(÷nd_is_not_zero);
852 BIND(÷nd_is_not_zero);
854 Node* untagged_divisor = SmiToInt32(divisor);
855 Node* untagged_dividend = SmiToInt32(dividend);
859 Label divisor_is_minus_one(
this), divisor_is_not_minus_one(
this);
860 Branch(Word32Equal(untagged_divisor, Int32Constant(-1)),
861 &divisor_is_minus_one, &divisor_is_not_minus_one);
863 BIND(&divisor_is_minus_one);
867 Int32Constant(kSmiValueSize == 32 ? kMinInt : (kMinInt >> 1))),
869 Goto(&divisor_is_not_minus_one);
871 BIND(&divisor_is_not_minus_one);
875 Node* untagged_result = Int32Div(untagged_dividend, untagged_divisor);
876 Node* truncated = Int32Mul(untagged_result, untagged_divisor);
878 GotoIf(Word32NotEqual(untagged_dividend, truncated), &bailout);
879 Return(SmiFromInt32(untagged_result));
885 var_left_double.Bind(SmiToFloat64(dividend));
886 var_right_double.Bind(SmiToFloat64(divisor));
887 Goto(&do_double_div);
891 BIND(&do_double_div);
893 Node* value = Float64Div(var_left_double.value(), var_right_double.value());
894 Return(AllocateHeapNumberWithValue(value));
897 BIND(&do_bigint_div);
899 Node* context = Parameter(Descriptor::kContext);
900 Return(CallRuntime(Runtime::kBigIntBinaryOp, context, var_left.value(),
901 var_right.value(), SmiConstant(Operation::kDivide)));
905 TF_BUILTIN(Modulus, NumberBuiltinsAssembler) {
906 VARIABLE(var_left, MachineRepresentation::kTagged);
907 VARIABLE(var_right, MachineRepresentation::kTagged);
908 VARIABLE(var_left_double, MachineRepresentation::kFloat64);
909 VARIABLE(var_right_double, MachineRepresentation::kFloat64);
910 Label do_smi_mod(
this), do_double_mod(
this), do_bigint_mod(
this);
912 BinaryOp<Descriptor>(&do_smi_mod, &var_left, &var_right, &do_double_mod,
913 &var_left_double, &var_right_double, &do_bigint_mod);
916 Return(SmiMod(CAST(var_left.value()), CAST(var_right.value())));
918 BIND(&do_double_mod);
919 Node* value = Float64Mod(var_left_double.value(), var_right_double.value());
920 Return(AllocateHeapNumberWithValue(value));
922 BIND(&do_bigint_mod);
924 Node* context = Parameter(Descriptor::kContext);
925 Return(CallRuntime(Runtime::kBigIntBinaryOp, context, var_left.value(),
926 var_right.value(), SmiConstant(Operation::kModulus)));
930 TF_BUILTIN(Exponentiate, NumberBuiltinsAssembler) {
931 VARIABLE(var_left, MachineRepresentation::kTagged);
932 VARIABLE(var_right, MachineRepresentation::kTagged);
933 Label do_number_exp(
this), do_bigint_exp(
this);
934 Node* context = Parameter(Descriptor::kContext);
936 BinaryOp<Descriptor>(&do_number_exp, &var_left, &var_right, &do_number_exp,
937 nullptr,
nullptr, &do_bigint_exp);
939 BIND(&do_number_exp);
941 MathBuiltinsAssembler math_asm(state());
942 Return(math_asm.MathPow(context, var_left.value(), var_right.value()));
945 BIND(&do_bigint_exp);
946 Return(CallRuntime(Runtime::kBigIntBinaryOp, context, var_left.value(),
947 var_right.value(), SmiConstant(Operation::kExponentiate)));
950 TF_BUILTIN(ShiftLeft, NumberBuiltinsAssembler) {
951 EmitBitwiseOp<Descriptor>(Operation::kShiftLeft);
954 TF_BUILTIN(ShiftRight, NumberBuiltinsAssembler) {
955 EmitBitwiseOp<Descriptor>(Operation::kShiftRight);
958 TF_BUILTIN(ShiftRightLogical, NumberBuiltinsAssembler) {
959 EmitBitwiseOp<Descriptor>(Operation::kShiftRightLogical);
962 TF_BUILTIN(BitwiseAnd, NumberBuiltinsAssembler) {
963 EmitBitwiseOp<Descriptor>(Operation::kBitwiseAnd);
966 TF_BUILTIN(BitwiseOr, NumberBuiltinsAssembler) {
967 EmitBitwiseOp<Descriptor>(Operation::kBitwiseOr);
970 TF_BUILTIN(BitwiseXor, NumberBuiltinsAssembler) {
971 EmitBitwiseOp<Descriptor>(Operation::kBitwiseXor);
974 TF_BUILTIN(LessThan, NumberBuiltinsAssembler) {
975 RelationalComparisonBuiltin<Descriptor>(Operation::kLessThan);
978 TF_BUILTIN(LessThanOrEqual, NumberBuiltinsAssembler) {
979 RelationalComparisonBuiltin<Descriptor>(Operation::kLessThanOrEqual);
982 TF_BUILTIN(GreaterThan, NumberBuiltinsAssembler) {
983 RelationalComparisonBuiltin<Descriptor>(Operation::kGreaterThan);
986 TF_BUILTIN(GreaterThanOrEqual, NumberBuiltinsAssembler) {
987 RelationalComparisonBuiltin<Descriptor>(Operation::kGreaterThanOrEqual);
990 TF_BUILTIN(Equal, CodeStubAssembler) {
991 Node* lhs = Parameter(Descriptor::kLeft);
992 Node* rhs = Parameter(Descriptor::kRight);
993 Node* context = Parameter(Descriptor::kContext);
995 Return(Equal(lhs, rhs, context));
998 TF_BUILTIN(StrictEqual, CodeStubAssembler) {
999 Node* lhs = Parameter(Descriptor::kLeft);
1000 Node* rhs = Parameter(Descriptor::kRight);
1002 Return(StrictEqual(lhs, rhs));