| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 | 7 |
| 8 #include "src/api-arguments.h" | 8 #include "src/api-arguments.h" |
| 9 #include "src/api-natives.h" | 9 #include "src/api-natives.h" |
| 10 #include "src/code-factory.h" | 10 #include "src/code-factory.h" |
| (...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 332 switch (tail_call_mode) { | 332 switch (tail_call_mode) { |
| 333 case TailCallMode::kDisallow: | 333 case TailCallMode::kDisallow: |
| 334 return CallBoundFunction(); | 334 return CallBoundFunction(); |
| 335 case TailCallMode::kAllow: | 335 case TailCallMode::kAllow: |
| 336 return TailCallBoundFunction(); | 336 return TailCallBoundFunction(); |
| 337 } | 337 } |
| 338 UNREACHABLE(); | 338 UNREACHABLE(); |
| 339 return Handle<Code>::null(); | 339 return Handle<Code>::null(); |
| 340 } | 340 } |
| 341 | 341 |
| 342 Handle<Code> Builtins::NonPrimitiveToPrimitive(ToPrimitiveHint hint) { | |
| 343 switch (hint) { | |
| 344 case ToPrimitiveHint::kDefault: | |
| 345 return NonPrimitiveToPrimitive_Default(); | |
| 346 case ToPrimitiveHint::kNumber: | |
| 347 return NonPrimitiveToPrimitive_Number(); | |
| 348 case ToPrimitiveHint::kString: | |
| 349 return NonPrimitiveToPrimitive_String(); | |
| 350 } | |
| 351 UNREACHABLE(); | |
| 352 return Handle<Code>::null(); | |
| 353 } | |
| 354 | |
| 355 Handle<Code> Builtins::OrdinaryToPrimitive(OrdinaryToPrimitiveHint hint) { | |
| 356 switch (hint) { | |
| 357 case OrdinaryToPrimitiveHint::kNumber: | |
| 358 return OrdinaryToPrimitive_Number(); | |
| 359 case OrdinaryToPrimitiveHint::kString: | |
| 360 return OrdinaryToPrimitive_String(); | |
| 361 } | |
| 362 UNREACHABLE(); | |
| 363 return Handle<Code>::null(); | |
| 364 } | |
| 365 | |
| 366 Handle<Code> Builtins::InterpreterPushArgsAndCall(TailCallMode tail_call_mode, | |
| 367 CallableType function_type) { | |
| 368 switch (tail_call_mode) { | |
| 369 case TailCallMode::kDisallow: | |
| 370 if (function_type == CallableType::kJSFunction) { | |
| 371 return InterpreterPushArgsAndCallFunction(); | |
| 372 } else { | |
| 373 return InterpreterPushArgsAndCall(); | |
| 374 } | |
| 375 case TailCallMode::kAllow: | |
| 376 if (function_type == CallableType::kJSFunction) { | |
| 377 return InterpreterPushArgsAndTailCallFunction(); | |
| 378 } else { | |
| 379 return InterpreterPushArgsAndTailCall(); | |
| 380 } | |
| 381 } | |
| 382 UNREACHABLE(); | |
| 383 return Handle<Code>::null(); | |
| 384 } | |
| 385 | |
| 386 namespace { | 342 namespace { |
| 387 | 343 |
| 388 class RelocatableArguments : public BuiltinArguments, public Relocatable { | 344 class RelocatableArguments : public BuiltinArguments, public Relocatable { |
| 389 public: | 345 public: |
| 390 RelocatableArguments(Isolate* isolate, int length, Object** arguments) | 346 RelocatableArguments(Isolate* isolate, int length, Object** arguments) |
| 391 : BuiltinArguments(length, arguments), Relocatable(isolate) {} | 347 : BuiltinArguments(length, arguments), Relocatable(isolate) {} |
| 392 | 348 |
| 393 virtual inline void IterateInstance(ObjectVisitor* v) { | 349 virtual inline void IterateInstance(ObjectVisitor* v) { |
| 394 if (length() == 0) return; | 350 if (length() == 0) return; |
| 395 v->VisitPointers(lowest_address(), highest_address() + 1); | 351 v->VisitPointers(lowest_address(), highest_address() + 1); |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 520 BUILTIN(HandleApiCallAsFunction) { | 476 BUILTIN(HandleApiCallAsFunction) { |
| 521 return HandleApiCallAsFunctionOrConstructor(isolate, false, args); | 477 return HandleApiCallAsFunctionOrConstructor(isolate, false, args); |
| 522 } | 478 } |
| 523 | 479 |
| 524 // Handle calls to non-function objects created through the API. This delegate | 480 // Handle calls to non-function objects created through the API. This delegate |
| 525 // function is used when the call is a construct call. | 481 // function is used when the call is a construct call. |
| 526 BUILTIN(HandleApiCallAsConstructor) { | 482 BUILTIN(HandleApiCallAsConstructor) { |
| 527 return HandleApiCallAsFunctionOrConstructor(isolate, true, args); | 483 return HandleApiCallAsFunctionOrConstructor(isolate, true, args); |
| 528 } | 484 } |
| 529 | 485 |
| 530 void Builtins::Generate_LoadIC_Miss(CodeStubAssembler* assembler) { | |
| 531 typedef compiler::Node Node; | |
| 532 | |
| 533 Node* receiver = assembler->Parameter(0); | |
| 534 Node* name = assembler->Parameter(1); | |
| 535 Node* slot = assembler->Parameter(2); | |
| 536 Node* vector = assembler->Parameter(3); | |
| 537 Node* context = assembler->Parameter(4); | |
| 538 | |
| 539 assembler->TailCallRuntime(Runtime::kLoadIC_Miss, context, receiver, name, | |
| 540 slot, vector); | |
| 541 } | |
| 542 | |
| 543 void Builtins::Generate_LoadGlobalIC_Miss(CodeStubAssembler* assembler) { | |
| 544 typedef compiler::Node Node; | |
| 545 | |
| 546 Node* slot = assembler->Parameter(0); | |
| 547 Node* vector = assembler->Parameter(1); | |
| 548 Node* context = assembler->Parameter(2); | |
| 549 | |
| 550 assembler->TailCallRuntime(Runtime::kLoadGlobalIC_Miss, context, slot, | |
| 551 vector); | |
| 552 } | |
| 553 | |
| 554 void Builtins::Generate_LoadIC_Normal(MacroAssembler* masm) { | |
| 555 LoadIC::GenerateNormal(masm); | |
| 556 } | |
| 557 | |
| 558 void Builtins::Generate_LoadIC_Getter_ForDeopt(MacroAssembler* masm) { | |
| 559 NamedLoadHandlerCompiler::GenerateLoadViaGetterForDeopt(masm); | |
| 560 } | |
| 561 | |
| 562 void Builtins::Generate_LoadIC_Slow(CodeStubAssembler* assembler) { | |
| 563 typedef compiler::Node Node; | |
| 564 | |
| 565 Node* receiver = assembler->Parameter(0); | |
| 566 Node* name = assembler->Parameter(1); | |
| 567 // Node* slot = assembler->Parameter(2); | |
| 568 // Node* vector = assembler->Parameter(3); | |
| 569 Node* context = assembler->Parameter(4); | |
| 570 | |
| 571 assembler->TailCallRuntime(Runtime::kGetProperty, context, receiver, name); | |
| 572 } | |
| 573 | |
| 574 namespace { | |
| 575 void Generate_LoadGlobalIC_Slow(CodeStubAssembler* assembler, TypeofMode mode) { | |
| 576 typedef compiler::Node Node; | |
| 577 | |
| 578 Node* slot = assembler->Parameter(0); | |
| 579 Node* vector = assembler->Parameter(1); | |
| 580 Node* context = assembler->Parameter(2); | |
| 581 Node* typeof_mode = assembler->SmiConstant(Smi::FromInt(mode)); | |
| 582 | |
| 583 assembler->TailCallRuntime(Runtime::kGetGlobal, context, slot, vector, | |
| 584 typeof_mode); | |
| 585 } | |
| 586 } // anonymous namespace | |
| 587 | |
| 588 void Builtins::Generate_LoadGlobalIC_SlowInsideTypeof( | |
| 589 CodeStubAssembler* assembler) { | |
| 590 Generate_LoadGlobalIC_Slow(assembler, INSIDE_TYPEOF); | |
| 591 } | |
| 592 | |
| 593 void Builtins::Generate_LoadGlobalIC_SlowNotInsideTypeof( | |
| 594 CodeStubAssembler* assembler) { | |
| 595 Generate_LoadGlobalIC_Slow(assembler, NOT_INSIDE_TYPEOF); | |
| 596 } | |
| 597 | |
| 598 void Builtins::Generate_KeyedLoadIC_Slow(MacroAssembler* masm) { | |
| 599 KeyedLoadIC::GenerateRuntimeGetProperty(masm); | |
| 600 } | |
| 601 | |
| 602 void Builtins::Generate_KeyedLoadIC_Miss(MacroAssembler* masm) { | |
| 603 KeyedLoadIC::GenerateMiss(masm); | |
| 604 } | |
| 605 | |
| 606 void Builtins::Generate_KeyedLoadIC_Megamorphic(MacroAssembler* masm) { | |
| 607 KeyedLoadIC::GenerateMegamorphic(masm); | |
| 608 } | |
| 609 | |
| 610 void Builtins::Generate_StoreIC_Miss(CodeStubAssembler* assembler) { | |
| 611 typedef compiler::Node Node; | |
| 612 | |
| 613 Node* receiver = assembler->Parameter(0); | |
| 614 Node* name = assembler->Parameter(1); | |
| 615 Node* value = assembler->Parameter(2); | |
| 616 Node* slot = assembler->Parameter(3); | |
| 617 Node* vector = assembler->Parameter(4); | |
| 618 Node* context = assembler->Parameter(5); | |
| 619 | |
| 620 assembler->TailCallRuntime(Runtime::kStoreIC_Miss, context, receiver, name, | |
| 621 value, slot, vector); | |
| 622 } | |
| 623 | |
| 624 void Builtins::Generate_StoreIC_Normal(MacroAssembler* masm) { | |
| 625 StoreIC::GenerateNormal(masm); | |
| 626 } | |
| 627 | |
| 628 namespace { | |
| 629 void Generate_StoreIC_Slow(CodeStubAssembler* assembler, | |
| 630 LanguageMode language_mode) { | |
| 631 typedef compiler::Node Node; | |
| 632 | |
| 633 Node* receiver = assembler->Parameter(0); | |
| 634 Node* name = assembler->Parameter(1); | |
| 635 Node* value = assembler->Parameter(2); | |
| 636 // Node* slot = assembler->Parameter(3); | |
| 637 // Node* vector = assembler->Parameter(4); | |
| 638 Node* context = assembler->Parameter(5); | |
| 639 Node* lang_mode = assembler->SmiConstant(Smi::FromInt(language_mode)); | |
| 640 | |
| 641 // The slow case calls into the runtime to complete the store without causing | |
| 642 // an IC miss that would otherwise cause a transition to the generic stub. | |
| 643 assembler->TailCallRuntime(Runtime::kSetProperty, context, receiver, name, | |
| 644 value, lang_mode); | |
| 645 } | |
| 646 } // anonymous namespace | |
| 647 | |
| 648 void Builtins::Generate_StoreIC_SlowSloppy(CodeStubAssembler* assembler) { | |
| 649 Generate_StoreIC_Slow(assembler, SLOPPY); | |
| 650 } | |
| 651 | |
| 652 void Builtins::Generate_StoreIC_SlowStrict(CodeStubAssembler* assembler) { | |
| 653 Generate_StoreIC_Slow(assembler, STRICT); | |
| 654 } | |
| 655 | |
| 656 namespace { | |
| 657 // 7.1.1.1 OrdinaryToPrimitive ( O, hint ) | |
| 658 void Generate_OrdinaryToPrimitive(CodeStubAssembler* assembler, | |
| 659 OrdinaryToPrimitiveHint hint) { | |
| 660 typedef CodeStubAssembler::Label Label; | |
| 661 typedef compiler::Node Node; | |
| 662 typedef CodeStubAssembler::Variable Variable; | |
| 663 | |
| 664 Node* input = assembler->Parameter(0); | |
| 665 Node* context = assembler->Parameter(1); | |
| 666 | |
| 667 Variable var_result(assembler, MachineRepresentation::kTagged); | |
| 668 Label return_result(assembler, &var_result); | |
| 669 | |
| 670 Handle<String> method_names[2]; | |
| 671 switch (hint) { | |
| 672 case OrdinaryToPrimitiveHint::kNumber: | |
| 673 method_names[0] = assembler->factory()->valueOf_string(); | |
| 674 method_names[1] = assembler->factory()->toString_string(); | |
| 675 break; | |
| 676 case OrdinaryToPrimitiveHint::kString: | |
| 677 method_names[0] = assembler->factory()->toString_string(); | |
| 678 method_names[1] = assembler->factory()->valueOf_string(); | |
| 679 break; | |
| 680 } | |
| 681 for (Handle<String> name : method_names) { | |
| 682 // Lookup the {name} on the {input}. | |
| 683 Callable callable = CodeFactory::GetProperty(assembler->isolate()); | |
| 684 Node* name_string = assembler->HeapConstant(name); | |
| 685 Node* method = assembler->CallStub(callable, context, input, name_string); | |
| 686 | |
| 687 // Check if the {method} is callable. | |
| 688 Label if_methodiscallable(assembler), | |
| 689 if_methodisnotcallable(assembler, Label::kDeferred); | |
| 690 assembler->GotoIf(assembler->WordIsSmi(method), &if_methodisnotcallable); | |
| 691 Node* method_map = assembler->LoadMap(method); | |
| 692 Node* method_bit_field = assembler->LoadMapBitField(method_map); | |
| 693 assembler->Branch( | |
| 694 assembler->Word32Equal( | |
| 695 assembler->Word32And(method_bit_field, assembler->Int32Constant( | |
| 696 1 << Map::kIsCallable)), | |
| 697 assembler->Int32Constant(0)), | |
| 698 &if_methodisnotcallable, &if_methodiscallable); | |
| 699 | |
| 700 assembler->Bind(&if_methodiscallable); | |
| 701 { | |
| 702 // Call the {method} on the {input}. | |
| 703 Callable callable = CodeFactory::Call(assembler->isolate()); | |
| 704 Node* result = assembler->CallJS(callable, context, method, input); | |
| 705 var_result.Bind(result); | |
| 706 | |
| 707 // Return the {result} if it is a primitive. | |
| 708 assembler->GotoIf(assembler->WordIsSmi(result), &return_result); | |
| 709 Node* result_instance_type = assembler->LoadInstanceType(result); | |
| 710 STATIC_ASSERT(FIRST_PRIMITIVE_TYPE == FIRST_TYPE); | |
| 711 assembler->GotoIf(assembler->Int32LessThanOrEqual( | |
| 712 result_instance_type, | |
| 713 assembler->Int32Constant(LAST_PRIMITIVE_TYPE)), | |
| 714 &return_result); | |
| 715 } | |
| 716 | |
| 717 // Just continue with the next {name} if the {method} is not callable. | |
| 718 assembler->Goto(&if_methodisnotcallable); | |
| 719 assembler->Bind(&if_methodisnotcallable); | |
| 720 } | |
| 721 | |
| 722 assembler->TailCallRuntime(Runtime::kThrowCannotConvertToPrimitive, context); | |
| 723 | |
| 724 assembler->Bind(&return_result); | |
| 725 assembler->Return(var_result.value()); | |
| 726 } | |
| 727 } // anonymous namespace | |
| 728 | |
| 729 void Builtins::Generate_OrdinaryToPrimitive_Number( | |
| 730 CodeStubAssembler* assembler) { | |
| 731 Generate_OrdinaryToPrimitive(assembler, OrdinaryToPrimitiveHint::kNumber); | |
| 732 } | |
| 733 | |
| 734 void Builtins::Generate_OrdinaryToPrimitive_String( | |
| 735 CodeStubAssembler* assembler) { | |
| 736 Generate_OrdinaryToPrimitive(assembler, OrdinaryToPrimitiveHint::kString); | |
| 737 } | |
| 738 | |
| 739 namespace { | |
| 740 // ES6 section 7.1.1 ToPrimitive ( input [ , PreferredType ] ) | |
| 741 void Generate_NonPrimitiveToPrimitive(CodeStubAssembler* assembler, | |
| 742 ToPrimitiveHint hint) { | |
| 743 typedef CodeStubAssembler::Label Label; | |
| 744 typedef compiler::Node Node; | |
| 745 | |
| 746 Node* input = assembler->Parameter(0); | |
| 747 Node* context = assembler->Parameter(1); | |
| 748 | |
| 749 // Lookup the @@toPrimitive property on the {input}. | |
| 750 Callable callable = CodeFactory::GetProperty(assembler->isolate()); | |
| 751 Node* to_primitive_symbol = | |
| 752 assembler->HeapConstant(assembler->factory()->to_primitive_symbol()); | |
| 753 Node* exotic_to_prim = | |
| 754 assembler->CallStub(callable, context, input, to_primitive_symbol); | |
| 755 | |
| 756 // Check if {exotic_to_prim} is neither null nor undefined. | |
| 757 Label ordinary_to_primitive(assembler); | |
| 758 assembler->GotoIf( | |
| 759 assembler->WordEqual(exotic_to_prim, assembler->NullConstant()), | |
| 760 &ordinary_to_primitive); | |
| 761 assembler->GotoIf( | |
| 762 assembler->WordEqual(exotic_to_prim, assembler->UndefinedConstant()), | |
| 763 &ordinary_to_primitive); | |
| 764 { | |
| 765 // Invoke the {exotic_to_prim} method on the {input} with a string | |
| 766 // representation of the {hint}. | |
| 767 Callable callable = CodeFactory::Call(assembler->isolate()); | |
| 768 Node* hint_string = assembler->HeapConstant( | |
| 769 assembler->factory()->ToPrimitiveHintString(hint)); | |
| 770 Node* result = assembler->CallJS(callable, context, exotic_to_prim, input, | |
| 771 hint_string); | |
| 772 | |
| 773 // Verify that the {result} is actually a primitive. | |
| 774 Label if_resultisprimitive(assembler), | |
| 775 if_resultisnotprimitive(assembler, Label::kDeferred); | |
| 776 assembler->GotoIf(assembler->WordIsSmi(result), &if_resultisprimitive); | |
| 777 Node* result_instance_type = assembler->LoadInstanceType(result); | |
| 778 STATIC_ASSERT(FIRST_PRIMITIVE_TYPE == FIRST_TYPE); | |
| 779 assembler->Branch(assembler->Int32LessThanOrEqual( | |
| 780 result_instance_type, | |
| 781 assembler->Int32Constant(LAST_PRIMITIVE_TYPE)), | |
| 782 &if_resultisprimitive, &if_resultisnotprimitive); | |
| 783 | |
| 784 assembler->Bind(&if_resultisprimitive); | |
| 785 { | |
| 786 // Just return the {result}. | |
| 787 assembler->Return(result); | |
| 788 } | |
| 789 | |
| 790 assembler->Bind(&if_resultisnotprimitive); | |
| 791 { | |
| 792 // Somehow the @@toPrimitive method on {input} didn't yield a primitive. | |
| 793 assembler->TailCallRuntime(Runtime::kThrowCannotConvertToPrimitive, | |
| 794 context); | |
| 795 } | |
| 796 } | |
| 797 | |
| 798 // Convert using the OrdinaryToPrimitive algorithm instead. | |
| 799 assembler->Bind(&ordinary_to_primitive); | |
| 800 { | |
| 801 Callable callable = CodeFactory::OrdinaryToPrimitive( | |
| 802 assembler->isolate(), (hint == ToPrimitiveHint::kString) | |
| 803 ? OrdinaryToPrimitiveHint::kString | |
| 804 : OrdinaryToPrimitiveHint::kNumber); | |
| 805 assembler->TailCallStub(callable, context, input); | |
| 806 } | |
| 807 } | |
| 808 } // anonymous namespace | |
| 809 | |
| 810 void Builtins::Generate_NonPrimitiveToPrimitive_Default( | |
| 811 CodeStubAssembler* assembler) { | |
| 812 Generate_NonPrimitiveToPrimitive(assembler, ToPrimitiveHint::kDefault); | |
| 813 } | |
| 814 | |
| 815 void Builtins::Generate_NonPrimitiveToPrimitive_Number( | |
| 816 CodeStubAssembler* assembler) { | |
| 817 Generate_NonPrimitiveToPrimitive(assembler, ToPrimitiveHint::kNumber); | |
| 818 } | |
| 819 | |
| 820 void Builtins::Generate_NonPrimitiveToPrimitive_String( | |
| 821 CodeStubAssembler* assembler) { | |
| 822 Generate_NonPrimitiveToPrimitive(assembler, ToPrimitiveHint::kString); | |
| 823 } | |
| 824 | |
| 825 // ES6 section 7.1.3 ToNumber ( argument ) | |
| 826 void Builtins::Generate_NonNumberToNumber(CodeStubAssembler* assembler) { | |
| 827 typedef CodeStubAssembler::Label Label; | |
| 828 typedef compiler::Node Node; | |
| 829 typedef CodeStubAssembler::Variable Variable; | |
| 830 | |
| 831 Node* input = assembler->Parameter(0); | |
| 832 Node* context = assembler->Parameter(1); | |
| 833 | |
| 834 // We might need to loop once here due to ToPrimitive conversions. | |
| 835 Variable var_input(assembler, MachineRepresentation::kTagged); | |
| 836 Label loop(assembler, &var_input); | |
| 837 var_input.Bind(input); | |
| 838 assembler->Goto(&loop); | |
| 839 assembler->Bind(&loop); | |
| 840 { | |
| 841 // Load the current {input} value (known to be a HeapObject). | |
| 842 Node* input = var_input.value(); | |
| 843 | |
| 844 // Dispatch on the {input} instance type. | |
| 845 Node* input_instance_type = assembler->LoadInstanceType(input); | |
| 846 Label if_inputisstring(assembler), if_inputisoddball(assembler), | |
| 847 if_inputisreceiver(assembler, Label::kDeferred), | |
| 848 if_inputisother(assembler, Label::kDeferred); | |
| 849 assembler->GotoIf(assembler->Int32LessThan( | |
| 850 input_instance_type, | |
| 851 assembler->Int32Constant(FIRST_NONSTRING_TYPE)), | |
| 852 &if_inputisstring); | |
| 853 assembler->GotoIf( | |
| 854 assembler->Word32Equal(input_instance_type, | |
| 855 assembler->Int32Constant(ODDBALL_TYPE)), | |
| 856 &if_inputisoddball); | |
| 857 STATIC_ASSERT(LAST_JS_RECEIVER_TYPE == LAST_TYPE); | |
| 858 assembler->Branch(assembler->Int32GreaterThanOrEqual( | |
| 859 input_instance_type, | |
| 860 assembler->Int32Constant(FIRST_JS_RECEIVER_TYPE)), | |
| 861 &if_inputisreceiver, &if_inputisother); | |
| 862 | |
| 863 assembler->Bind(&if_inputisstring); | |
| 864 { | |
| 865 // The {input} is a String, use the fast stub to convert it to a Number. | |
| 866 // TODO(bmeurer): Consider inlining the StringToNumber logic here. | |
| 867 Callable callable = CodeFactory::StringToNumber(assembler->isolate()); | |
| 868 assembler->TailCallStub(callable, context, input); | |
| 869 } | |
| 870 | |
| 871 assembler->Bind(&if_inputisoddball); | |
| 872 { | |
| 873 // The {input} is an Oddball, we just need to the Number value of it. | |
| 874 Node* result = | |
| 875 assembler->LoadObjectField(input, Oddball::kToNumberOffset); | |
| 876 assembler->Return(result); | |
| 877 } | |
| 878 | |
| 879 assembler->Bind(&if_inputisreceiver); | |
| 880 { | |
| 881 // The {input} is a JSReceiver, we need to convert it to a Primitive first | |
| 882 // using the ToPrimitive type conversion, preferably yielding a Number. | |
| 883 Callable callable = CodeFactory::NonPrimitiveToPrimitive( | |
| 884 assembler->isolate(), ToPrimitiveHint::kNumber); | |
| 885 Node* result = assembler->CallStub(callable, context, input); | |
| 886 | |
| 887 // Check if the {result} is already a Number. | |
| 888 Label if_resultisnumber(assembler), if_resultisnotnumber(assembler); | |
| 889 assembler->GotoIf(assembler->WordIsSmi(result), &if_resultisnumber); | |
| 890 Node* result_map = assembler->LoadMap(result); | |
| 891 assembler->Branch( | |
| 892 assembler->WordEqual(result_map, assembler->HeapNumberMapConstant()), | |
| 893 &if_resultisnumber, &if_resultisnotnumber); | |
| 894 | |
| 895 assembler->Bind(&if_resultisnumber); | |
| 896 { | |
| 897 // The ToPrimitive conversion already gave us a Number, so we're done. | |
| 898 assembler->Return(result); | |
| 899 } | |
| 900 | |
| 901 assembler->Bind(&if_resultisnotnumber); | |
| 902 { | |
| 903 // We now have a Primitive {result}, but it's not yet a Number. | |
| 904 var_input.Bind(result); | |
| 905 assembler->Goto(&loop); | |
| 906 } | |
| 907 } | |
| 908 | |
| 909 assembler->Bind(&if_inputisother); | |
| 910 { | |
| 911 // The {input} is something else (i.e. Symbol or Simd128Value), let the | |
| 912 // runtime figure out the correct exception. | |
| 913 // Note: We cannot tail call to the runtime here, as js-to-wasm | |
| 914 // trampolines also use this code currently, and they declare all | |
| 915 // outgoing parameters as untagged, while we would push a tagged | |
| 916 // object here. | |
| 917 Node* result = assembler->CallRuntime(Runtime::kToNumber, context, input); | |
| 918 assembler->Return(result); | |
| 919 } | |
| 920 } | |
| 921 } | |
| 922 | |
| 923 // ES6 section 7.1.2 ToBoolean ( argument ) | |
| 924 void Builtins::Generate_ToBoolean(CodeStubAssembler* assembler) { | |
| 925 typedef compiler::Node Node; | |
| 926 typedef CodeStubAssembler::Label Label; | |
| 927 | |
| 928 Node* value = assembler->Parameter(0); | |
| 929 | |
| 930 Label return_true(assembler), return_false(assembler); | |
| 931 assembler->BranchIfToBooleanIsTrue(value, &return_true, &return_false); | |
| 932 | |
| 933 assembler->Bind(&return_true); | |
| 934 assembler->Return(assembler->BooleanConstant(true)); | |
| 935 | |
| 936 assembler->Bind(&return_false); | |
| 937 assembler->Return(assembler->BooleanConstant(false)); | |
| 938 } | |
| 939 | |
| 940 void Builtins::Generate_KeyedStoreIC_Slow(MacroAssembler* masm) { | |
| 941 ElementHandlerCompiler::GenerateStoreSlow(masm); | |
| 942 } | |
| 943 | |
| 944 void Builtins::Generate_StoreIC_Setter_ForDeopt(MacroAssembler* masm) { | |
| 945 NamedStoreHandlerCompiler::GenerateStoreViaSetterForDeopt(masm); | |
| 946 } | |
| 947 | |
| 948 void Builtins::Generate_KeyedStoreIC_Megamorphic(MacroAssembler* masm) { | |
| 949 KeyedStoreIC::GenerateMegamorphic(masm, SLOPPY); | |
| 950 } | |
| 951 | |
| 952 void Builtins::Generate_KeyedStoreIC_Megamorphic_Strict(MacroAssembler* masm) { | |
| 953 KeyedStoreIC::GenerateMegamorphic(masm, STRICT); | |
| 954 } | |
| 955 | |
| 956 void Builtins::Generate_KeyedStoreIC_Miss(MacroAssembler* masm) { | |
| 957 KeyedStoreIC::GenerateMiss(masm); | |
| 958 } | |
| 959 | |
| 960 void Builtins::Generate_Return_DebugBreak(MacroAssembler* masm) { | |
| 961 DebugCodegen::GenerateDebugBreakStub(masm, | |
| 962 DebugCodegen::SAVE_RESULT_REGISTER); | |
| 963 } | |
| 964 | |
| 965 void Builtins::Generate_Slot_DebugBreak(MacroAssembler* masm) { | |
| 966 DebugCodegen::GenerateDebugBreakStub(masm, | |
| 967 DebugCodegen::IGNORE_RESULT_REGISTER); | |
| 968 } | |
| 969 | |
| 970 void Builtins::Generate_FrameDropper_LiveEdit(MacroAssembler* masm) { | |
| 971 DebugCodegen::GenerateFrameDropperLiveEdit(masm); | |
| 972 } | |
| 973 | |
| 974 Builtins::Builtins() : initialized_(false) { | 486 Builtins::Builtins() : initialized_(false) { |
| 975 memset(builtins_, 0, sizeof(builtins_[0]) * builtin_count); | 487 memset(builtins_, 0, sizeof(builtins_[0]) * builtin_count); |
| 976 } | 488 } |
| 977 | 489 |
| 978 Builtins::~Builtins() {} | 490 Builtins::~Builtins() {} |
| 979 | 491 |
| 980 namespace { | 492 namespace { |
| 981 void PostBuildProfileAndTracing(Isolate* isolate, Code* code, | 493 void PostBuildProfileAndTracing(Isolate* isolate, Code* code, |
| 982 const char* name) { | 494 const char* name) { |
| 983 PROFILE(isolate, CodeCreateEvent(CodeEventListener::BUILTIN_TAG, | 495 PROFILE(isolate, CodeCreateEvent(CodeEventListener::BUILTIN_TAG, |
| (...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1223 void Builtins::Generate_TailCall_ReceiverIsNotNullOrUndefined( | 735 void Builtins::Generate_TailCall_ReceiverIsNotNullOrUndefined( |
| 1224 MacroAssembler* masm) { | 736 MacroAssembler* masm) { |
| 1225 Generate_Call(masm, ConvertReceiverMode::kNotNullOrUndefined, | 737 Generate_Call(masm, ConvertReceiverMode::kNotNullOrUndefined, |
| 1226 TailCallMode::kAllow); | 738 TailCallMode::kAllow); |
| 1227 } | 739 } |
| 1228 | 740 |
| 1229 void Builtins::Generate_TailCall_ReceiverIsAny(MacroAssembler* masm) { | 741 void Builtins::Generate_TailCall_ReceiverIsAny(MacroAssembler* masm) { |
| 1230 Generate_Call(masm, ConvertReceiverMode::kAny, TailCallMode::kAllow); | 742 Generate_Call(masm, ConvertReceiverMode::kAny, TailCallMode::kAllow); |
| 1231 } | 743 } |
| 1232 | 744 |
| 1233 void Builtins::Generate_InterpreterPushArgsAndCall(MacroAssembler* masm) { | |
| 1234 return Generate_InterpreterPushArgsAndCallImpl(masm, TailCallMode::kDisallow, | |
| 1235 CallableType::kAny); | |
| 1236 } | |
| 1237 void Builtins::Generate_InterpreterPushArgsAndTailCall(MacroAssembler* masm) { | |
| 1238 return Generate_InterpreterPushArgsAndCallImpl(masm, TailCallMode::kAllow, | |
| 1239 CallableType::kAny); | |
| 1240 } | |
| 1241 | |
| 1242 void Builtins::Generate_InterpreterPushArgsAndCallFunction( | |
| 1243 MacroAssembler* masm) { | |
| 1244 return Generate_InterpreterPushArgsAndCallImpl(masm, TailCallMode::kDisallow, | |
| 1245 CallableType::kJSFunction); | |
| 1246 } | |
| 1247 | |
| 1248 void Builtins::Generate_InterpreterPushArgsAndTailCallFunction( | |
| 1249 MacroAssembler* masm) { | |
| 1250 return Generate_InterpreterPushArgsAndCallImpl(masm, TailCallMode::kAllow, | |
| 1251 CallableType::kJSFunction); | |
| 1252 } | |
| 1253 | 745 |
| 1254 #define DEFINE_BUILTIN_ACCESSOR(Name, ...) \ | 746 #define DEFINE_BUILTIN_ACCESSOR(Name, ...) \ |
| 1255 Handle<Code> Builtins::Name() { \ | 747 Handle<Code> Builtins::Name() { \ |
| 1256 Code** code_address = reinterpret_cast<Code**>(builtin_address(k##Name)); \ | 748 Code** code_address = reinterpret_cast<Code**>(builtin_address(k##Name)); \ |
| 1257 return Handle<Code>(code_address); \ | 749 return Handle<Code>(code_address); \ |
| 1258 } | 750 } |
| 1259 BUILTIN_LIST_ALL(DEFINE_BUILTIN_ACCESSOR) | 751 BUILTIN_LIST_ALL(DEFINE_BUILTIN_ACCESSOR) |
| 1260 #undef DEFINE_BUILTIN_ACCESSOR | 752 #undef DEFINE_BUILTIN_ACCESSOR |
| 1261 | 753 |
| 1262 } // namespace internal | 754 } // namespace internal |
| 1263 } // namespace v8 | 755 } // namespace v8 |
| OLD | NEW |