Changeset 95230 in webkit
- Timestamp:
- Sep 15, 2011 2:41:41 PM (13 years ago)
- Location:
- trunk/Source/JavaScriptCore
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/ChangeLog
r95229 r95230 1 2011-09-15 Filip Pizlo <fpizlo@apple.com> 2 3 All of the functionality in the non-speculative JIT should be 4 available to the speculative JIT via helper methods 5 https://bugs.webkit.org/show_bug.cgi?id=68186 6 7 Reviewed by Oliver Hunt. 8 9 Stole all of the goodness from NonSpeculativeJIT and placed it 10 in JITCodeGenerator. Left all of the badness (i.e. subtle code 11 duplication with SpeculativeJIT, etc). This is in preparation 12 for removing the NonSpeculativeJIT entirely, but having its 13 goodness available for reuse in the SpeculativeJIT if necessary. 14 15 * dfg/DFGJITCodeGenerator.cpp: 16 (JSC::DFG::JITCodeGenerator::nonSpeculativeValueToNumber): 17 (JSC::DFG::JITCodeGenerator::nonSpeculativeValueToInt32): 18 (JSC::DFG::JITCodeGenerator::nonSpeculativeUInt32ToNumber): 19 (JSC::DFG::JITCodeGenerator::nonSpeculativeKnownConstantArithOp): 20 (JSC::DFG::JITCodeGenerator::nonSpeculativeBasicArithOp): 21 (JSC::DFG::JITCodeGenerator::nonSpeculativeArithMod): 22 (JSC::DFG::JITCodeGenerator::nonSpeculativeCheckHasInstance): 23 (JSC::DFG::JITCodeGenerator::nonSpeculativeInstanceOf): 24 * dfg/DFGJITCodeGenerator.h: 25 (JSC::DFG::JITCodeGenerator::nonSpeculativeAdd): 26 (JSC::DFG::JITCodeGenerator::nonSpeculativeArithSub): 27 * dfg/DFGNonSpeculativeJIT.cpp: 28 (JSC::DFG::NonSpeculativeJIT::compile): 29 * dfg/DFGNonSpeculativeJIT.h: 30 1 31 2011-09-15 Sheriff Bot <webkit.review.bot@gmail.com> 2 32 -
trunk/Source/JavaScriptCore/dfg/DFGJITCodeGenerator.cpp
r95170 r95230 35 35 namespace JSC { namespace DFG { 36 36 37 const double twoToThe32 = (double)0x100000000ull; 38 37 39 void JITCodeGenerator::clearGenerationInfo() 38 40 { … … 430 432 431 433 return info.isJSBoolean(); 434 } 435 436 void JITCodeGenerator::nonSpeculativeValueToNumber(Node& node) 437 { 438 if (isKnownNumeric(node.child1())) { 439 JSValueOperand op1(this, node.child1()); 440 GPRTemporary result(this, op1); 441 m_jit.move(op1.gpr(), result.gpr()); 442 jsValueResult(result.gpr(), m_compileIndex); 443 return; 444 } 445 446 JSValueOperand op1(this, node.child1()); 447 GPRTemporary result(this); 448 449 ASSERT(!isInt32Constant(node.child1())); 450 ASSERT(!isNumberConstant(node.child1())); 451 452 GPRReg jsValueGpr = op1.gpr(); 453 GPRReg gpr = result.gpr(); 454 op1.use(); 455 456 JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, jsValueGpr, GPRInfo::tagTypeNumberRegister); 457 JITCompiler::Jump nonNumeric = m_jit.branchTestPtr(MacroAssembler::Zero, jsValueGpr, GPRInfo::tagTypeNumberRegister); 458 459 // First, if we get here we have a double encoded as a JSValue 460 m_jit.move(jsValueGpr, gpr); 461 JITCompiler::Jump hasUnboxedDouble = m_jit.jump(); 462 463 // Next handle cells (& other JS immediates) 464 nonNumeric.link(&m_jit); 465 silentSpillAllRegisters(gpr); 466 m_jit.move(jsValueGpr, GPRInfo::argumentGPR1); 467 m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); 468 appendCallWithExceptionCheck(dfgConvertJSValueToNumber); 469 boxDouble(FPRInfo::returnValueFPR, gpr); 470 silentFillAllRegisters(gpr); 471 JITCompiler::Jump hasCalledToNumber = m_jit.jump(); 472 473 // Finally, handle integers. 474 isInteger.link(&m_jit); 475 m_jit.orPtr(GPRInfo::tagTypeNumberRegister, jsValueGpr, gpr); 476 hasUnboxedDouble.link(&m_jit); 477 hasCalledToNumber.link(&m_jit); 478 479 jsValueResult(result.gpr(), m_compileIndex, UseChildrenCalledExplicitly); 480 } 481 482 void JITCodeGenerator::nonSpeculativeValueToInt32(Node& node) 483 { 484 ASSERT(!isInt32Constant(node.child1())); 485 486 if (isKnownInteger(node.child1())) { 487 IntegerOperand op1(this, node.child1()); 488 GPRTemporary result(this, op1); 489 m_jit.move(op1.gpr(), result.gpr()); 490 integerResult(result.gpr(), m_compileIndex); 491 return; 492 } 493 494 GenerationInfo& childInfo = m_generationInfo[m_jit.graph()[node.child1()].virtualRegister()]; 495 if (isJSDouble(childInfo.registerFormat())) { 496 DoubleOperand op1(this, node.child1()); 497 GPRTemporary result(this); 498 FPRReg fpr = op1.fpr(); 499 GPRReg gpr = result.gpr(); 500 op1.use(); 501 JITCompiler::Jump truncatedToInteger = m_jit.branchTruncateDoubleToInt32(fpr, gpr, JITCompiler::BranchIfTruncateSuccessful); 502 503 silentSpillAllRegisters(gpr); 504 505 m_jit.moveDouble(fpr, FPRInfo::argumentFPR0); 506 appendCallWithExceptionCheck(toInt32); 507 m_jit.zeroExtend32ToPtr(GPRInfo::returnValueGPR, gpr); 508 509 silentFillAllRegisters(gpr); 510 511 truncatedToInteger.link(&m_jit); 512 integerResult(gpr, m_compileIndex, UseChildrenCalledExplicitly); 513 return; 514 } 515 516 JSValueOperand op1(this, node.child1()); 517 GPRTemporary result(this, op1); 518 GPRReg jsValueGpr = op1.gpr(); 519 GPRReg resultGPR = result.gpr(); 520 op1.use(); 521 522 JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, jsValueGpr, GPRInfo::tagTypeNumberRegister); 523 524 // First handle non-integers 525 silentSpillAllRegisters(resultGPR); 526 m_jit.move(jsValueGpr, GPRInfo::argumentGPR1); 527 m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); 528 appendCallWithExceptionCheck(dfgConvertJSValueToInt32); 529 m_jit.zeroExtend32ToPtr(GPRInfo::returnValueGPR, resultGPR); 530 silentFillAllRegisters(resultGPR); 531 JITCompiler::Jump hasCalledToInt32 = m_jit.jump(); 532 533 // Then handle integers. 534 isInteger.link(&m_jit); 535 m_jit.zeroExtend32ToPtr(jsValueGpr, resultGPR); 536 hasCalledToInt32.link(&m_jit); 537 integerResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly); 538 } 539 540 void JITCodeGenerator::nonSpeculativeUInt32ToNumber(Node& node) 541 { 542 IntegerOperand op1(this, node.child1()); 543 FPRTemporary boxer(this); 544 GPRTemporary result(this, op1); 545 546 JITCompiler::Jump positive = m_jit.branch32(MacroAssembler::GreaterThanOrEqual, op1.gpr(), TrustedImm32(0)); 547 548 m_jit.convertInt32ToDouble(op1.gpr(), boxer.fpr()); 549 m_jit.addDouble(JITCompiler::AbsoluteAddress(&twoToThe32), boxer.fpr()); 550 551 boxDouble(boxer.fpr(), result.gpr()); 552 553 JITCompiler::Jump done = m_jit.jump(); 554 555 positive.link(&m_jit); 556 557 m_jit.orPtr(GPRInfo::tagTypeNumberRegister, op1.gpr(), result.gpr()); 558 559 done.link(&m_jit); 560 561 jsValueResult(result.gpr(), m_compileIndex); 562 } 563 564 void JITCodeGenerator::nonSpeculativeKnownConstantArithOp(NodeType op, NodeIndex regChild, NodeIndex immChild, bool commute) 565 { 566 JSValueOperand regArg(this, regChild); 567 GPRReg regArgGPR = regArg.gpr(); 568 GPRTemporary result(this); 569 GPRReg resultGPR = result.gpr(); 570 FPRTemporary tmp1(this); 571 FPRTemporary tmp2(this); 572 FPRReg tmp1FPR = tmp1.fpr(); 573 FPRReg tmp2FPR = tmp2.fpr(); 574 575 regArg.use(); 576 use(immChild); 577 578 JITCompiler::Jump notInt; 579 580 int32_t imm = valueOfInt32Constant(immChild); 581 582 if (!isKnownInteger(regChild)) 583 notInt = m_jit.branchPtr(MacroAssembler::Below, regArgGPR, GPRInfo::tagTypeNumberRegister); 584 585 JITCompiler::Jump overflow; 586 587 switch (op) { 588 case ValueAdd: 589 case ArithAdd: 590 overflow = m_jit.branchAdd32(MacroAssembler::Overflow, regArgGPR, Imm32(imm), resultGPR); 591 break; 592 593 case ArithSub: 594 overflow = m_jit.branchSub32(MacroAssembler::Overflow, regArgGPR, Imm32(imm), resultGPR); 595 break; 596 597 default: 598 ASSERT_NOT_REACHED(); 599 } 600 601 m_jit.orPtr(GPRInfo::tagTypeNumberRegister, resultGPR); 602 603 JITCompiler::Jump done = m_jit.jump(); 604 605 overflow.link(&m_jit); 606 607 JITCompiler::Jump notNumber; 608 609 // first deal with overflow case 610 m_jit.convertInt32ToDouble(regArgGPR, tmp2FPR); 611 612 // now deal with not-int case, if applicable 613 if (!isKnownInteger(regChild)) { 614 JITCompiler::Jump haveValue = m_jit.jump(); 615 616 notInt.link(&m_jit); 617 618 if (!isKnownNumeric(regChild)) { 619 ASSERT(op == ValueAdd); 620 notNumber = m_jit.branchTestPtr(MacroAssembler::Zero, regArgGPR, GPRInfo::tagTypeNumberRegister); 621 } 622 623 m_jit.move(regArgGPR, resultGPR); 624 m_jit.addPtr(GPRInfo::tagTypeNumberRegister, resultGPR); 625 m_jit.movePtrToDouble(resultGPR, tmp2FPR); 626 627 haveValue.link(&m_jit); 628 } 629 630 m_jit.move(MacroAssembler::ImmPtr(reinterpret_cast<void*>(reinterpretDoubleToIntptr(valueOfNumberConstant(immChild)))), resultGPR); 631 m_jit.movePtrToDouble(resultGPR, tmp1FPR); 632 switch (op) { 633 case ValueAdd: 634 case ArithAdd: 635 m_jit.addDouble(tmp1FPR, tmp2FPR); 636 break; 637 638 case ArithSub: 639 m_jit.subDouble(tmp1FPR, tmp2FPR); 640 break; 641 642 default: 643 ASSERT_NOT_REACHED(); 644 } 645 646 JITCompiler::Jump doneCaseConvertedToInt; 647 648 if (op == ValueAdd) { 649 JITCompiler::JumpList failureCases; 650 m_jit.branchConvertDoubleToInt32(tmp2FPR, resultGPR, failureCases, tmp1FPR); 651 m_jit.orPtr(GPRInfo::tagTypeNumberRegister, resultGPR); 652 653 doneCaseConvertedToInt = m_jit.jump(); 654 655 failureCases.link(&m_jit); 656 } 657 658 m_jit.moveDoubleToPtr(tmp2FPR, resultGPR); 659 m_jit.subPtr(GPRInfo::tagTypeNumberRegister, resultGPR); 660 661 if (!isKnownNumeric(regChild)) { 662 ASSERT(notNumber.isSet()); 663 ASSERT(op == ValueAdd); 664 665 JITCompiler::Jump doneCaseWasNumber = m_jit.jump(); 666 667 notNumber.link(&m_jit); 668 669 silentSpillAllRegisters(resultGPR); 670 if (commute) { 671 m_jit.move(regArgGPR, GPRInfo::argumentGPR2); 672 m_jit.move(MacroAssembler::ImmPtr(static_cast<const void*>(JSValue::encode(jsNumber(imm)))), GPRInfo::argumentGPR1); 673 } else { 674 m_jit.move(regArgGPR, GPRInfo::argumentGPR1); 675 m_jit.move(MacroAssembler::ImmPtr(static_cast<const void*>(JSValue::encode(jsNumber(imm)))), GPRInfo::argumentGPR2); 676 } 677 m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); 678 appendCallWithExceptionCheck(operationValueAddNotNumber); 679 m_jit.move(GPRInfo::returnValueGPR, resultGPR); 680 silentFillAllRegisters(resultGPR); 681 682 doneCaseWasNumber.link(&m_jit); 683 } 684 685 done.link(&m_jit); 686 if (doneCaseConvertedToInt.isSet()) 687 doneCaseConvertedToInt.link(&m_jit); 688 689 jsValueResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly); 690 } 691 692 void JITCodeGenerator::nonSpeculativeBasicArithOp(NodeType op, Node &node) 693 { 694 JSValueOperand arg1(this, node.child1()); 695 JSValueOperand arg2(this, node.child2()); 696 697 FPRTemporary tmp1(this); 698 FPRTemporary tmp2(this); 699 FPRReg tmp1FPR = tmp1.fpr(); 700 FPRReg tmp2FPR = tmp2.fpr(); 701 702 GPRTemporary result(this); 703 704 GPRReg arg1GPR = arg1.gpr(); 705 GPRReg arg2GPR = arg2.gpr(); 706 707 GPRReg resultGPR = result.gpr(); 708 709 arg1.use(); 710 arg2.use(); 711 712 JITCompiler::Jump child1NotInt; 713 JITCompiler::Jump child2NotInt; 714 JITCompiler::JumpList overflow; 715 716 if (!isKnownInteger(node.child1())) 717 child1NotInt = m_jit.branchPtr(MacroAssembler::Below, arg1GPR, GPRInfo::tagTypeNumberRegister); 718 if (!isKnownInteger(node.child2())) 719 child2NotInt = m_jit.branchPtr(MacroAssembler::Below, arg2GPR, GPRInfo::tagTypeNumberRegister); 720 721 switch (op) { 722 case ValueAdd: 723 case ArithAdd: { 724 overflow.append(m_jit.branchAdd32(MacroAssembler::Overflow, arg1GPR, arg2GPR, resultGPR)); 725 break; 726 } 727 728 case ArithSub: { 729 overflow.append(m_jit.branchSub32(MacroAssembler::Overflow, arg1GPR, arg2GPR, resultGPR)); 730 break; 731 } 732 733 case ArithMul: { 734 overflow.append(m_jit.branchMul32(MacroAssembler::Overflow, arg1GPR, arg2GPR, resultGPR)); 735 overflow.append(m_jit.branchTest32(MacroAssembler::Zero, resultGPR)); 736 break; 737 } 738 739 default: 740 ASSERT_NOT_REACHED(); 741 } 742 743 m_jit.orPtr(GPRInfo::tagTypeNumberRegister, resultGPR); 744 745 JITCompiler::Jump done = m_jit.jump(); 746 747 JITCompiler::JumpList haveFPRArguments; 748 749 overflow.link(&m_jit); 750 751 // both arguments are integers 752 m_jit.convertInt32ToDouble(arg1GPR, tmp1FPR); 753 m_jit.convertInt32ToDouble(arg2GPR, tmp2FPR); 754 755 haveFPRArguments.append(m_jit.jump()); 756 757 JITCompiler::JumpList notNumbers; 758 759 JITCompiler::Jump child2NotInt2; 760 761 if (!isKnownInteger(node.child1())) { 762 child1NotInt.link(&m_jit); 763 764 if (!isKnownNumeric(node.child1())) { 765 ASSERT(op == ValueAdd); 766 notNumbers.append(m_jit.branchTestPtr(MacroAssembler::Zero, arg1GPR, GPRInfo::tagTypeNumberRegister)); 767 } 768 769 m_jit.move(arg1GPR, resultGPR); 770 unboxDouble(resultGPR, tmp1FPR); 771 772 // child1 is converted to a double; child2 may either be an int or 773 // a boxed double 774 775 if (!isKnownInteger(node.child2())) { 776 if (isKnownNumeric(node.child2())) 777 child2NotInt2 = m_jit.branchPtr(MacroAssembler::Below, arg2GPR, GPRInfo::tagTypeNumberRegister); 778 else { 779 ASSERT(op == ValueAdd); 780 JITCompiler::Jump child2IsInt = m_jit.branchPtr(MacroAssembler::AboveOrEqual, arg2GPR, GPRInfo::tagTypeNumberRegister); 781 notNumbers.append(m_jit.branchTestPtr(MacroAssembler::Zero, arg2GPR, GPRInfo::tagTypeNumberRegister)); 782 child2NotInt2 = m_jit.jump(); 783 child2IsInt.link(&m_jit); 784 } 785 } 786 787 // child 2 is definitely an integer 788 m_jit.convertInt32ToDouble(arg2GPR, tmp2FPR); 789 790 haveFPRArguments.append(m_jit.jump()); 791 } 792 793 if (!isKnownInteger(node.child2())) { 794 child2NotInt.link(&m_jit); 795 796 if (!isKnownNumeric(node.child2())) { 797 ASSERT(op == ValueAdd); 798 notNumbers.append(m_jit.branchTestPtr(MacroAssembler::Zero, arg2GPR, GPRInfo::tagTypeNumberRegister)); 799 } 800 801 // child1 is definitely an integer, and child 2 is definitely not 802 803 m_jit.convertInt32ToDouble(arg1GPR, tmp1FPR); 804 805 if (child2NotInt2.isSet()) 806 child2NotInt2.link(&m_jit); 807 808 m_jit.move(arg2GPR, resultGPR); 809 unboxDouble(resultGPR, tmp2FPR); 810 } 811 812 haveFPRArguments.link(&m_jit); 813 814 switch (op) { 815 case ValueAdd: 816 case ArithAdd: 817 m_jit.addDouble(tmp2FPR, tmp1FPR); 818 break; 819 820 case ArithSub: 821 m_jit.subDouble(tmp2FPR, tmp1FPR); 822 break; 823 824 case ArithMul: 825 m_jit.mulDouble(tmp2FPR, tmp1FPR); 826 break; 827 828 default: 829 ASSERT_NOT_REACHED(); 830 } 831 832 JITCompiler::Jump doneCaseConvertedToInt; 833 834 if (op == ValueAdd) { 835 JITCompiler::JumpList failureCases; 836 m_jit.branchConvertDoubleToInt32(tmp1FPR, resultGPR, failureCases, tmp2FPR); 837 m_jit.orPtr(GPRInfo::tagTypeNumberRegister, resultGPR); 838 839 doneCaseConvertedToInt = m_jit.jump(); 840 841 failureCases.link(&m_jit); 842 } 843 844 boxDouble(tmp1FPR, resultGPR); 845 846 if (!notNumbers.empty()) { 847 ASSERT(op == ValueAdd); 848 849 JITCompiler::Jump doneCaseWasNumber = m_jit.jump(); 850 851 notNumbers.link(&m_jit); 852 853 silentSpillAllRegisters(resultGPR); 854 setupStubArguments(arg1GPR, arg2GPR); 855 m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); 856 appendCallWithExceptionCheck(operationValueAddNotNumber); 857 m_jit.move(GPRInfo::returnValueGPR, resultGPR); 858 silentFillAllRegisters(resultGPR); 859 860 doneCaseWasNumber.link(&m_jit); 861 } 862 863 done.link(&m_jit); 864 if (doneCaseConvertedToInt.isSet()) 865 doneCaseConvertedToInt.link(&m_jit); 866 867 jsValueResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly); 868 } 869 870 void JITCodeGenerator::nonSpeculativeArithMod(Node& node) 871 { 872 JSValueOperand op1(this, node.child1()); 873 JSValueOperand op2(this, node.child2()); 874 GPRTemporary eax(this, X86Registers::eax); 875 GPRTemporary edx(this, X86Registers::edx); 876 877 FPRTemporary op1Double(this); 878 FPRTemporary op2Double(this); 879 880 GPRReg op1GPR = op1.gpr(); 881 GPRReg op2GPR = op2.gpr(); 882 883 FPRReg op1FPR = op1Double.fpr(); 884 FPRReg op2FPR = op2Double.fpr(); 885 886 op1.use(); 887 op2.use(); 888 889 GPRReg temp2 = InvalidGPRReg; 890 GPRReg unboxGPR; 891 if (op2GPR == X86Registers::eax || op2GPR == X86Registers::edx) { 892 temp2 = allocate(); 893 m_jit.move(op2GPR, temp2); 894 op2GPR = temp2; 895 unboxGPR = temp2; 896 } else if (op1GPR == X86Registers::eax) 897 unboxGPR = X86Registers::edx; 898 else 899 unboxGPR = X86Registers::eax; 900 ASSERT(unboxGPR != op1.gpr()); 901 ASSERT(unboxGPR != op2.gpr()); 902 903 JITCompiler::Jump firstOpNotInt; 904 JITCompiler::Jump secondOpNotInt; 905 JITCompiler::JumpList done; 906 JITCompiler::Jump modByZero; 907 908 if (!isKnownInteger(node.child1())) 909 firstOpNotInt = m_jit.branchPtr(MacroAssembler::Below, op1GPR, GPRInfo::tagTypeNumberRegister); 910 if (!isKnownInteger(node.child2())) 911 secondOpNotInt = m_jit.branchPtr(MacroAssembler::Below, op2GPR, GPRInfo::tagTypeNumberRegister); 912 913 modByZero = m_jit.branchTest32(MacroAssembler::Zero, op2GPR); 914 915 m_jit.move(op1GPR, eax.gpr()); 916 m_jit.assembler().cdq(); 917 m_jit.assembler().idivl_r(op2GPR); 918 919 m_jit.orPtr(GPRInfo::tagTypeNumberRegister, X86Registers::edx); 920 921 done.append(m_jit.jump()); 922 923 JITCompiler::Jump gotDoubleArgs; 924 925 modByZero.link(&m_jit); 926 927 m_jit.move(MacroAssembler::TrustedImmPtr(JSValue::encode(jsNumber(std::numeric_limits<double>::quiet_NaN()))), X86Registers::edx); 928 done.append(m_jit.jump()); 929 930 if (!isKnownInteger(node.child1())) { 931 firstOpNotInt.link(&m_jit); 932 933 JITCompiler::Jump secondOpNotInt2; 934 935 if (!isKnownInteger(node.child2())) 936 secondOpNotInt2 = m_jit.branchPtr(MacroAssembler::Below, op2GPR, GPRInfo::tagTypeNumberRegister); 937 938 // first op is a double, second op is an int. 939 m_jit.convertInt32ToDouble(op2GPR, op2FPR); 940 941 if (!isKnownInteger(node.child2())) { 942 JITCompiler::Jump gotSecondOp = m_jit.jump(); 943 944 secondOpNotInt2.link(&m_jit); 945 946 // first op is a double, second op is a double. 947 m_jit.move(op2GPR, unboxGPR); 948 unboxDouble(unboxGPR, op2FPR); 949 950 gotSecondOp.link(&m_jit); 951 } 952 953 m_jit.move(op1GPR, unboxGPR); 954 unboxDouble(unboxGPR, op1FPR); 955 956 gotDoubleArgs = m_jit.jump(); 957 } 958 959 if (!isKnownInteger(node.child2())) { 960 secondOpNotInt.link(&m_jit); 961 962 // we know that the first op is an int, and the second is a double 963 m_jit.convertInt32ToDouble(op1GPR, op1FPR); 964 m_jit.move(op2GPR, unboxGPR); 965 unboxDouble(unboxGPR, op2FPR); 966 } 967 968 if (!isKnownInteger(node.child1())) 969 gotDoubleArgs.link(&m_jit); 970 971 if (!isKnownInteger(node.child1()) || !isKnownInteger(node.child2())) { 972 silentSpillAllRegisters(X86Registers::edx); 973 setupTwoStubArgs<FPRInfo::argumentFPR0, FPRInfo::argumentFPR1>(op1FPR, op2FPR); 974 m_jit.appendCall(fmod); 975 boxDouble(FPRInfo::returnValueFPR, X86Registers::edx); 976 silentFillAllRegisters(X86Registers::edx); 977 } 978 979 done.link(&m_jit); 980 981 if (temp2 != InvalidGPRReg) 982 unlock(temp2); 983 984 jsValueResult(X86Registers::edx, m_compileIndex, UseChildrenCalledExplicitly); 985 } 986 987 void JITCodeGenerator::nonSpeculativeCheckHasInstance(Node& node) 988 { 989 JSValueOperand base(this, node.child1()); 990 GPRTemporary structure(this); 991 992 GPRReg baseReg = base.gpr(); 993 GPRReg structureReg = structure.gpr(); 994 995 // Check that base is a cell. 996 MacroAssembler::Jump baseNotCell = m_jit.branchTestPtr(MacroAssembler::NonZero, baseReg, GPRInfo::tagMaskRegister); 997 998 // Check that base 'ImplementsHasInstance'. 999 m_jit.loadPtr(MacroAssembler::Address(baseReg, JSCell::structureOffset()), structureReg); 1000 MacroAssembler::Jump implementsHasInstance = m_jit.branchTest8(MacroAssembler::NonZero, MacroAssembler::Address(structureReg, Structure::typeInfoFlagsOffset()), MacroAssembler::TrustedImm32(ImplementsHasInstance)); 1001 1002 // At this point we always throw, so no need to preserve registers. 1003 baseNotCell.link(&m_jit); 1004 m_jit.move(baseReg, GPRInfo::argumentGPR1); 1005 m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); 1006 // At some point we could optimize this to plant a direct jump, rather then checking 1007 // for an exception (operationThrowHasInstanceError always throws). Probably not worth 1008 // adding the extra interface to do this now, but we may also want this for op_throw. 1009 appendCallWithExceptionCheck(operationThrowHasInstanceError); 1010 1011 implementsHasInstance.link(&m_jit); 1012 noResult(m_compileIndex); 1013 } 1014 1015 void JITCodeGenerator::nonSpeculativeInstanceOf(Node& node) 1016 { 1017 JSValueOperand value(this, node.child1()); 1018 JSValueOperand base(this, node.child2()); 1019 JSValueOperand prototype(this, node.child3()); 1020 GPRTemporary scratch(this, base); 1021 1022 GPRReg valueReg = value.gpr(); 1023 GPRReg baseReg = base.gpr(); 1024 GPRReg prototypeReg = prototype.gpr(); 1025 GPRReg scratchReg = scratch.gpr(); 1026 1027 value.use(); 1028 base.use(); 1029 prototype.use(); 1030 1031 // Check that operands are cells (base is checked by CheckHasInstance, so we can just assert). 1032 MacroAssembler::Jump valueNotCell = m_jit.branchTestPtr(MacroAssembler::NonZero, valueReg, GPRInfo::tagMaskRegister); 1033 m_jit.jitAssertIsCell(baseReg); 1034 MacroAssembler::Jump prototypeNotCell = m_jit.branchTestPtr(MacroAssembler::NonZero, prototypeReg, GPRInfo::tagMaskRegister); 1035 1036 // Check that baseVal 'ImplementsDefaultHasInstance'. 1037 m_jit.loadPtr(MacroAssembler::Address(baseReg, JSCell::structureOffset()), scratchReg); 1038 MacroAssembler::Jump notDefaultHasInstance = m_jit.branchTest8(MacroAssembler::Zero, MacroAssembler::Address(scratchReg, Structure::typeInfoFlagsOffset()), TrustedImm32(ImplementsDefaultHasInstance)); 1039 1040 // Check that prototype is an object 1041 m_jit.loadPtr(MacroAssembler::Address(prototypeReg, JSCell::structureOffset()), scratchReg); 1042 MacroAssembler::Jump protoNotObject = m_jit.branchIfNotObject(scratchReg); 1043 1044 // Initialize scratchReg with the value being checked. 1045 m_jit.move(valueReg, scratchReg); 1046 1047 // Walk up the prototype chain of the value (in scratchReg), comparing to prototypeReg. 1048 MacroAssembler::Label loop(&m_jit); 1049 m_jit.loadPtr(MacroAssembler::Address(scratchReg, JSCell::structureOffset()), scratchReg); 1050 m_jit.loadPtr(MacroAssembler::Address(scratchReg, Structure::prototypeOffset()), scratchReg); 1051 MacroAssembler::Jump isInstance = m_jit.branchPtr(MacroAssembler::Equal, scratchReg, prototypeReg); 1052 m_jit.branchTestPtr(MacroAssembler::Zero, scratchReg, GPRInfo::tagMaskRegister).linkTo(loop, &m_jit); 1053 1054 // No match - result is false. 1055 m_jit.move(MacroAssembler::TrustedImmPtr(JSValue::encode(jsBoolean(false))), scratchReg); 1056 MacroAssembler::Jump wasNotInstance = m_jit.jump(); 1057 1058 // Link to here if any checks fail that require us to try calling out to an operation to help, 1059 // e.g. for an API overridden HasInstance. 1060 valueNotCell.link(&m_jit); 1061 prototypeNotCell.link(&m_jit); 1062 notDefaultHasInstance.link(&m_jit); 1063 protoNotObject.link(&m_jit); 1064 1065 silentSpillAllRegisters(scratchReg); 1066 setupStubArguments(valueReg, baseReg, prototypeReg); 1067 m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); 1068 appendCallWithExceptionCheck(operationInstanceOf); 1069 m_jit.move(GPRInfo::returnValueGPR, scratchReg); 1070 silentFillAllRegisters(scratchReg); 1071 1072 MacroAssembler::Jump wasNotDefaultHasInstance = m_jit.jump(); 1073 1074 isInstance.link(&m_jit); 1075 m_jit.move(MacroAssembler::TrustedImmPtr(JSValue::encode(jsBoolean(true))), scratchReg); 1076 1077 wasNotInstance.link(&m_jit); 1078 wasNotDefaultHasInstance.link(&m_jit); 1079 jsValueResult(scratchReg, m_compileIndex, UseChildrenCalledExplicitly); 432 1080 } 433 1081 -
trunk/Source/JavaScriptCore/dfg/DFGJITCodeGenerator.h
r95170 r95230 563 563 return lastNode.op == Branch && lastNode.child1() == m_compileIndex ? lastNodeIndex : NoNode; 564 564 } 565 566 void nonSpeculativeValueToNumber(Node&); 567 void nonSpeculativeValueToInt32(Node&); 568 void nonSpeculativeUInt32ToNumber(Node&); 569 570 void nonSpeculativeKnownConstantArithOp(NodeType op, NodeIndex regChild, NodeIndex immChild, bool commute); 571 void nonSpeculativeBasicArithOp(NodeType op, Node&); 572 573 // Handles both ValueAdd and ArithAdd. 574 void nonSpeculativeAdd(NodeType op, Node& node) 575 { 576 if (isInt32Constant(node.child1())) { 577 nonSpeculativeKnownConstantArithOp(op, node.child2(), node.child1(), true); 578 return; 579 } 580 581 if (isInt32Constant(node.child2())) { 582 nonSpeculativeKnownConstantArithOp(op, node.child1(), node.child2(), false); 583 return; 584 } 585 586 nonSpeculativeBasicArithOp(op, node); 587 } 588 589 void nonSpeculativeArithSub(Node& node) 590 { 591 if (isInt32Constant(node.child2())) { 592 nonSpeculativeKnownConstantArithOp(ArithSub, node.child1(), node.child2(), false); 593 return; 594 } 595 596 nonSpeculativeBasicArithOp(ArithSub, node); 597 } 598 599 void nonSpeculativeArithMod(Node&); 600 void nonSpeculativeCheckHasInstance(Node&); 601 void nonSpeculativeInstanceOf(Node&); 565 602 566 603 JITCompiler::Call cachedGetById(GPRReg baseGPR, GPRReg resultGPR, GPRReg scratchGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget = JITCompiler::Jump(), NodeType = GetById); -
trunk/Source/JavaScriptCore/dfg/DFGNonSpeculativeJIT.cpp
r95147 r95230 33 33 namespace JSC { namespace DFG { 34 34 35 const double twoToThe32 = (double)0x100000000ull;36 37 35 EntryLocation::EntryLocation(MacroAssembler::Label entry, NonSpeculativeJIT* jit) 38 36 : m_entry(entry) … … 61 59 } 62 60 63 void NonSpeculativeJIT::valueToNumber(JSValueOperand& operand, GPRReg gpr)64 {65 GPRReg jsValueGpr = operand.gpr();66 operand.use();67 68 JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, jsValueGpr, GPRInfo::tagTypeNumberRegister);69 JITCompiler::Jump nonNumeric = m_jit.branchTestPtr(MacroAssembler::Zero, jsValueGpr, GPRInfo::tagTypeNumberRegister);70 71 // First, if we get here we have a double encoded as a JSValue72 m_jit.move(jsValueGpr, gpr);73 JITCompiler::Jump hasUnboxedDouble = m_jit.jump();74 75 // Next handle cells (& other JS immediates)76 nonNumeric.link(&m_jit);77 silentSpillAllRegisters(gpr);78 m_jit.move(jsValueGpr, GPRInfo::argumentGPR1);79 m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);80 appendCallWithExceptionCheck(dfgConvertJSValueToNumber);81 boxDouble(FPRInfo::returnValueFPR, gpr);82 silentFillAllRegisters(gpr);83 JITCompiler::Jump hasCalledToNumber = m_jit.jump();84 85 // Finally, handle integers.86 isInteger.link(&m_jit);87 m_jit.orPtr(GPRInfo::tagTypeNumberRegister, jsValueGpr, gpr);88 hasUnboxedDouble.link(&m_jit);89 hasCalledToNumber.link(&m_jit);90 }91 92 void NonSpeculativeJIT::valueToInt32(JSValueOperand& operand, GPRReg result)93 {94 GPRReg jsValueGpr = operand.gpr();95 operand.use();96 97 JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, jsValueGpr, GPRInfo::tagTypeNumberRegister);98 99 // First handle non-integers100 silentSpillAllRegisters(result);101 m_jit.move(jsValueGpr, GPRInfo::argumentGPR1);102 m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);103 appendCallWithExceptionCheck(dfgConvertJSValueToInt32);104 m_jit.zeroExtend32ToPtr(GPRInfo::returnValueGPR, result);105 silentFillAllRegisters(result);106 JITCompiler::Jump hasCalledToInt32 = m_jit.jump();107 108 // Then handle integers.109 isInteger.link(&m_jit);110 m_jit.zeroExtend32ToPtr(jsValueGpr, result);111 hasCalledToInt32.link(&m_jit);112 }113 114 void NonSpeculativeJIT::numberToInt32(FPRReg fpr, GPRReg gpr)115 {116 JITCompiler::Jump truncatedToInteger = m_jit.branchTruncateDoubleToInt32(fpr, gpr, JITCompiler::BranchIfTruncateSuccessful);117 118 silentSpillAllRegisters(gpr);119 120 m_jit.moveDouble(fpr, FPRInfo::argumentFPR0);121 appendCallWithExceptionCheck(toInt32);122 m_jit.zeroExtend32ToPtr(GPRInfo::returnValueGPR, gpr);123 124 silentFillAllRegisters(gpr);125 126 truncatedToInteger.link(&m_jit);127 }128 129 void NonSpeculativeJIT::knownConstantArithOp(NodeType op, NodeIndex regChild, NodeIndex immChild, bool commute)130 {131 JSValueOperand regArg(this, regChild);132 GPRReg regArgGPR = regArg.gpr();133 GPRTemporary result(this);134 GPRReg resultGPR = result.gpr();135 FPRTemporary tmp1(this);136 FPRTemporary tmp2(this);137 FPRReg tmp1FPR = tmp1.fpr();138 FPRReg tmp2FPR = tmp2.fpr();139 140 regArg.use();141 use(immChild);142 143 JITCompiler::Jump notInt;144 145 int32_t imm = valueOfInt32Constant(immChild);146 147 if (!isKnownInteger(regChild))148 notInt = m_jit.branchPtr(MacroAssembler::Below, regArgGPR, GPRInfo::tagTypeNumberRegister);149 150 JITCompiler::Jump overflow;151 152 switch (op) {153 case ValueAdd:154 case ArithAdd:155 overflow = m_jit.branchAdd32(MacroAssembler::Overflow, regArgGPR, Imm32(imm), resultGPR);156 break;157 158 case ArithSub:159 overflow = m_jit.branchSub32(MacroAssembler::Overflow, regArgGPR, Imm32(imm), resultGPR);160 break;161 162 default:163 ASSERT_NOT_REACHED();164 }165 166 m_jit.orPtr(GPRInfo::tagTypeNumberRegister, resultGPR);167 168 JITCompiler::Jump done = m_jit.jump();169 170 overflow.link(&m_jit);171 172 JITCompiler::Jump notNumber;173 174 // first deal with overflow case175 m_jit.convertInt32ToDouble(regArgGPR, tmp2FPR);176 177 // now deal with not-int case, if applicable178 if (!isKnownInteger(regChild)) {179 JITCompiler::Jump haveValue = m_jit.jump();180 181 notInt.link(&m_jit);182 183 if (!isKnownNumeric(regChild)) {184 ASSERT(op == ValueAdd);185 notNumber = m_jit.branchTestPtr(MacroAssembler::Zero, regArgGPR, GPRInfo::tagTypeNumberRegister);186 }187 188 m_jit.move(regArgGPR, resultGPR);189 m_jit.addPtr(GPRInfo::tagTypeNumberRegister, resultGPR);190 m_jit.movePtrToDouble(resultGPR, tmp2FPR);191 192 haveValue.link(&m_jit);193 }194 195 m_jit.move(MacroAssembler::ImmPtr(reinterpret_cast<void*>(reinterpretDoubleToIntptr(valueOfNumberConstant(immChild)))), resultGPR);196 m_jit.movePtrToDouble(resultGPR, tmp1FPR);197 switch (op) {198 case ValueAdd:199 case ArithAdd:200 m_jit.addDouble(tmp1FPR, tmp2FPR);201 break;202 203 case ArithSub:204 m_jit.subDouble(tmp1FPR, tmp2FPR);205 break;206 207 default:208 ASSERT_NOT_REACHED();209 }210 211 JITCompiler::Jump doneCaseConvertedToInt;212 213 if (op == ValueAdd) {214 JITCompiler::JumpList failureCases;215 m_jit.branchConvertDoubleToInt32(tmp2FPR, resultGPR, failureCases, tmp1FPR);216 m_jit.orPtr(GPRInfo::tagTypeNumberRegister, resultGPR);217 218 doneCaseConvertedToInt = m_jit.jump();219 220 failureCases.link(&m_jit);221 }222 223 m_jit.moveDoubleToPtr(tmp2FPR, resultGPR);224 m_jit.subPtr(GPRInfo::tagTypeNumberRegister, resultGPR);225 226 if (!isKnownNumeric(regChild)) {227 ASSERT(notNumber.isSet());228 ASSERT(op == ValueAdd);229 230 JITCompiler::Jump doneCaseWasNumber = m_jit.jump();231 232 notNumber.link(&m_jit);233 234 silentSpillAllRegisters(resultGPR);235 if (commute) {236 m_jit.move(regArgGPR, GPRInfo::argumentGPR2);237 m_jit.move(MacroAssembler::ImmPtr(static_cast<const void*>(JSValue::encode(jsNumber(imm)))), GPRInfo::argumentGPR1);238 } else {239 m_jit.move(regArgGPR, GPRInfo::argumentGPR1);240 m_jit.move(MacroAssembler::ImmPtr(static_cast<const void*>(JSValue::encode(jsNumber(imm)))), GPRInfo::argumentGPR2);241 }242 m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);243 appendCallWithExceptionCheck(operationValueAddNotNumber);244 m_jit.move(GPRInfo::returnValueGPR, resultGPR);245 silentFillAllRegisters(resultGPR);246 247 doneCaseWasNumber.link(&m_jit);248 }249 250 done.link(&m_jit);251 if (doneCaseConvertedToInt.isSet())252 doneCaseConvertedToInt.link(&m_jit);253 254 jsValueResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);255 }256 257 void NonSpeculativeJIT::basicArithOp(NodeType op, Node &node)258 {259 JSValueOperand arg1(this, node.child1());260 JSValueOperand arg2(this, node.child2());261 262 FPRTemporary tmp1(this);263 FPRTemporary tmp2(this);264 FPRReg tmp1FPR = tmp1.fpr();265 FPRReg tmp2FPR = tmp2.fpr();266 267 GPRTemporary result(this);268 269 GPRReg arg1GPR = arg1.gpr();270 GPRReg arg2GPR = arg2.gpr();271 272 GPRReg resultGPR = result.gpr();273 274 arg1.use();275 arg2.use();276 277 JITCompiler::Jump child1NotInt;278 JITCompiler::Jump child2NotInt;279 JITCompiler::JumpList overflow;280 281 if (!isKnownInteger(node.child1()))282 child1NotInt = m_jit.branchPtr(MacroAssembler::Below, arg1GPR, GPRInfo::tagTypeNumberRegister);283 if (!isKnownInteger(node.child2()))284 child2NotInt = m_jit.branchPtr(MacroAssembler::Below, arg2GPR, GPRInfo::tagTypeNumberRegister);285 286 switch (op) {287 case ValueAdd:288 case ArithAdd: {289 overflow.append(m_jit.branchAdd32(MacroAssembler::Overflow, arg1GPR, arg2GPR, resultGPR));290 break;291 }292 293 case ArithSub: {294 overflow.append(m_jit.branchSub32(MacroAssembler::Overflow, arg1GPR, arg2GPR, resultGPR));295 break;296 }297 298 case ArithMul: {299 overflow.append(m_jit.branchMul32(MacroAssembler::Overflow, arg1GPR, arg2GPR, resultGPR));300 overflow.append(m_jit.branchTest32(MacroAssembler::Zero, resultGPR));301 break;302 }303 304 default:305 ASSERT_NOT_REACHED();306 }307 308 m_jit.orPtr(GPRInfo::tagTypeNumberRegister, resultGPR);309 310 JITCompiler::Jump done = m_jit.jump();311 312 JITCompiler::JumpList haveFPRArguments;313 314 overflow.link(&m_jit);315 316 // both arguments are integers317 m_jit.convertInt32ToDouble(arg1GPR, tmp1FPR);318 m_jit.convertInt32ToDouble(arg2GPR, tmp2FPR);319 320 haveFPRArguments.append(m_jit.jump());321 322 JITCompiler::JumpList notNumbers;323 324 JITCompiler::Jump child2NotInt2;325 326 if (!isKnownInteger(node.child1())) {327 child1NotInt.link(&m_jit);328 329 if (!isKnownNumeric(node.child1())) {330 ASSERT(op == ValueAdd);331 notNumbers.append(m_jit.branchTestPtr(MacroAssembler::Zero, arg1GPR, GPRInfo::tagTypeNumberRegister));332 }333 334 m_jit.move(arg1GPR, resultGPR);335 unboxDouble(resultGPR, tmp1FPR);336 337 // child1 is converted to a double; child2 may either be an int or338 // a boxed double339 340 if (!isKnownInteger(node.child2())) {341 if (isKnownNumeric(node.child2()))342 child2NotInt2 = m_jit.branchPtr(MacroAssembler::Below, arg2GPR, GPRInfo::tagTypeNumberRegister);343 else {344 ASSERT(op == ValueAdd);345 JITCompiler::Jump child2IsInt = m_jit.branchPtr(MacroAssembler::AboveOrEqual, arg2GPR, GPRInfo::tagTypeNumberRegister);346 notNumbers.append(m_jit.branchTestPtr(MacroAssembler::Zero, arg2GPR, GPRInfo::tagTypeNumberRegister));347 child2NotInt2 = m_jit.jump();348 child2IsInt.link(&m_jit);349 }350 }351 352 // child 2 is definitely an integer353 m_jit.convertInt32ToDouble(arg2GPR, tmp2FPR);354 355 haveFPRArguments.append(m_jit.jump());356 }357 358 if (!isKnownInteger(node.child2())) {359 child2NotInt.link(&m_jit);360 361 if (!isKnownNumeric(node.child2())) {362 ASSERT(op == ValueAdd);363 notNumbers.append(m_jit.branchTestPtr(MacroAssembler::Zero, arg2GPR, GPRInfo::tagTypeNumberRegister));364 }365 366 // child1 is definitely an integer, and child 2 is definitely not367 368 m_jit.convertInt32ToDouble(arg1GPR, tmp1FPR);369 370 if (child2NotInt2.isSet())371 child2NotInt2.link(&m_jit);372 373 m_jit.move(arg2GPR, resultGPR);374 unboxDouble(resultGPR, tmp2FPR);375 }376 377 haveFPRArguments.link(&m_jit);378 379 switch (op) {380 case ValueAdd:381 case ArithAdd:382 m_jit.addDouble(tmp2FPR, tmp1FPR);383 break;384 385 case ArithSub:386 m_jit.subDouble(tmp2FPR, tmp1FPR);387 break;388 389 case ArithMul:390 m_jit.mulDouble(tmp2FPR, tmp1FPR);391 break;392 393 default:394 ASSERT_NOT_REACHED();395 }396 397 JITCompiler::Jump doneCaseConvertedToInt;398 399 if (op == ValueAdd) {400 JITCompiler::JumpList failureCases;401 m_jit.branchConvertDoubleToInt32(tmp1FPR, resultGPR, failureCases, tmp2FPR);402 m_jit.orPtr(GPRInfo::tagTypeNumberRegister, resultGPR);403 404 doneCaseConvertedToInt = m_jit.jump();405 406 failureCases.link(&m_jit);407 }408 409 boxDouble(tmp1FPR, resultGPR);410 411 if (!notNumbers.empty()) {412 ASSERT(op == ValueAdd);413 414 JITCompiler::Jump doneCaseWasNumber = m_jit.jump();415 416 notNumbers.link(&m_jit);417 418 silentSpillAllRegisters(resultGPR);419 setupStubArguments(arg1GPR, arg2GPR);420 m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0);421 appendCallWithExceptionCheck(operationValueAddNotNumber);422 m_jit.move(GPRInfo::returnValueGPR, resultGPR);423 silentFillAllRegisters(resultGPR);424 425 doneCaseWasNumber.link(&m_jit);426 }427 428 done.link(&m_jit);429 if (doneCaseConvertedToInt.isSet())430 doneCaseConvertedToInt.link(&m_jit);431 432 jsValueResult(resultGPR, m_compileIndex, UseChildrenCalledExplicitly);433 }434 435 61 void NonSpeculativeJIT::compile(SpeculationCheckIndexIterator& checkIterator, Node& node) 436 62 { … … 543 169 544 170 case UInt32ToNumber: { 545 IntegerOperand op1(this, node.child1()); 546 FPRTemporary boxer(this); 547 GPRTemporary result(this, op1); 548 549 JITCompiler::Jump positive = m_jit.branch32(MacroAssembler::GreaterThanOrEqual, op1.gpr(), TrustedImm32(0)); 550 551 m_jit.convertInt32ToDouble(op1.gpr(), boxer.fpr()); 552 m_jit.addDouble(JITCompiler::AbsoluteAddress(&twoToThe32), boxer.fpr()); 553 554 boxDouble(boxer.fpr(), result.gpr()); 555 556 JITCompiler::Jump done = m_jit.jump(); 557 558 positive.link(&m_jit); 559 560 m_jit.orPtr(GPRInfo::tagTypeNumberRegister, op1.gpr(), result.gpr()); 561 562 done.link(&m_jit); 563 564 jsValueResult(result.gpr(), m_compileIndex); 171 nonSpeculativeUInt32ToNumber(node); 565 172 break; 566 173 } 567 174 568 175 case ValueToInt32: { 569 ASSERT(!isInt32Constant(node.child1())); 570 571 if (isKnownInteger(node.child1())) { 572 IntegerOperand op1(this, node.child1()); 573 GPRTemporary result(this, op1); 574 m_jit.move(op1.gpr(), result.gpr()); 575 integerResult(result.gpr(), m_compileIndex); 576 break; 577 } 578 579 GenerationInfo& childInfo = m_generationInfo[m_jit.graph()[node.child1()].virtualRegister()]; 580 if (isJSDouble(childInfo.registerFormat())) { 581 DoubleOperand op1(this, node.child1()); 582 GPRTemporary result(this); 583 FPRReg fpr = op1.fpr(); 584 GPRReg gpr = result.gpr(); 585 op1.use(); 586 numberToInt32(fpr, gpr); 587 integerResult(gpr, m_compileIndex, UseChildrenCalledExplicitly); 588 break; 589 } 590 591 JSValueOperand op1(this, node.child1()); 592 GPRTemporary result(this, op1); 593 valueToInt32(op1, result.gpr()); 594 integerResult(result.gpr(), m_compileIndex, UseChildrenCalledExplicitly); 176 nonSpeculativeValueToInt32(node); 595 177 break; 596 178 } … … 598 180 case ValueToNumber: 599 181 case ValueToDouble: { 600 ASSERT(!isInt32Constant(node.child1())); 601 ASSERT(!isNumberConstant(node.child1())); 602 603 if (isKnownNumeric(node.child1())) { 604 JSValueOperand op1(this, node.child1()); 605 GPRTemporary result(this, op1); 606 m_jit.move(op1.gpr(), result.gpr()); 607 jsValueResult(result.gpr(), m_compileIndex); 608 break; 609 } 610 611 JSValueOperand op1(this, node.child1()); 612 GPRTemporary result(this); 613 valueToNumber(op1, result.gpr()); 614 jsValueResult(result.gpr(), m_compileIndex, UseChildrenCalledExplicitly); 182 nonSpeculativeValueToNumber(node); 615 183 break; 616 184 } … … 618 186 case ValueAdd: 619 187 case ArithAdd: { 620 if (isInt32Constant(node.child1())) { 621 knownConstantArithOp(op, node.child2(), node.child1(), true); 622 break; 623 } 624 625 if (isInt32Constant(node.child2())) { 626 knownConstantArithOp(op, node.child1(), node.child2(), false); 627 break; 628 } 629 630 basicArithOp(op, node); 188 nonSpeculativeAdd(op, node); 631 189 break; 632 190 } 633 191 634 192 case ArithSub: { 635 if (isInt32Constant(node.child2())) { 636 knownConstantArithOp(ArithSub, node.child1(), node.child2(), false); 637 break; 638 } 639 640 basicArithOp(ArithSub, node); 193 nonSpeculativeArithSub(node); 641 194 break; 642 195 } 643 196 644 197 case ArithMul: { 645 basicArithOp(ArithMul, node);198 nonSpeculativeBasicArithOp(ArithMul, node); 646 199 break; 647 200 } … … 662 215 663 216 case ArithMod: { 664 JSValueOperand op1(this, node.child1()); 665 JSValueOperand op2(this, node.child2()); 666 GPRTemporary eax(this, X86Registers::eax); 667 GPRTemporary edx(this, X86Registers::edx); 668 669 FPRTemporary op1Double(this); 670 FPRTemporary op2Double(this); 671 672 GPRReg op1GPR = op1.gpr(); 673 GPRReg op2GPR = op2.gpr(); 674 675 FPRReg op1FPR = op1Double.fpr(); 676 FPRReg op2FPR = op2Double.fpr(); 677 678 op1.use(); 679 op2.use(); 680 681 GPRReg temp2 = InvalidGPRReg; 682 GPRReg unboxGPR; 683 if (op2GPR == X86Registers::eax || op2GPR == X86Registers::edx) { 684 temp2 = allocate(); 685 m_jit.move(op2GPR, temp2); 686 op2GPR = temp2; 687 unboxGPR = temp2; 688 } else if (op1GPR == X86Registers::eax) 689 unboxGPR = X86Registers::edx; 690 else 691 unboxGPR = X86Registers::eax; 692 ASSERT(unboxGPR != op1.gpr()); 693 ASSERT(unboxGPR != op2.gpr()); 694 695 JITCompiler::Jump firstOpNotInt; 696 JITCompiler::Jump secondOpNotInt; 697 JITCompiler::JumpList done; 698 JITCompiler::Jump modByZero; 699 700 if (!isKnownInteger(node.child1())) 701 firstOpNotInt = m_jit.branchPtr(MacroAssembler::Below, op1GPR, GPRInfo::tagTypeNumberRegister); 702 if (!isKnownInteger(node.child2())) 703 secondOpNotInt = m_jit.branchPtr(MacroAssembler::Below, op2GPR, GPRInfo::tagTypeNumberRegister); 704 705 modByZero = m_jit.branchTest32(MacroAssembler::Zero, op2GPR); 706 707 m_jit.move(op1GPR, eax.gpr()); 708 m_jit.assembler().cdq(); 709 m_jit.assembler().idivl_r(op2GPR); 710 711 m_jit.orPtr(GPRInfo::tagTypeNumberRegister, X86Registers::edx); 712 713 done.append(m_jit.jump()); 714 715 JITCompiler::Jump gotDoubleArgs; 716 717 modByZero.link(&m_jit); 718 719 m_jit.move(MacroAssembler::TrustedImmPtr(JSValue::encode(jsNumber(std::numeric_limits<double>::quiet_NaN()))), X86Registers::edx); 720 done.append(m_jit.jump()); 721 722 if (!isKnownInteger(node.child1())) { 723 firstOpNotInt.link(&m_jit); 724 725 JITCompiler::Jump secondOpNotInt2; 726 727 if (!isKnownInteger(node.child2())) 728 secondOpNotInt2 = m_jit.branchPtr(MacroAssembler::Below, op2GPR, GPRInfo::tagTypeNumberRegister); 729 730 // first op is a double, second op is an int. 731 m_jit.convertInt32ToDouble(op2GPR, op2FPR); 732 733 if (!isKnownInteger(node.child2())) { 734 JITCompiler::Jump gotSecondOp = m_jit.jump(); 735 736 secondOpNotInt2.link(&m_jit); 737 738 // first op is a double, second op is a double. 739 m_jit.move(op2GPR, unboxGPR); 740 unboxDouble(unboxGPR, op2FPR); 741 742 gotSecondOp.link(&m_jit); 743 } 744 745 m_jit.move(op1GPR, unboxGPR); 746 unboxDouble(unboxGPR, op1FPR); 747 748 gotDoubleArgs = m_jit.jump(); 749 } 750 751 if (!isKnownInteger(node.child2())) { 752 secondOpNotInt.link(&m_jit); 753 754 // we know that the first op is an int, and the second is a double 755 m_jit.convertInt32ToDouble(op1GPR, op1FPR); 756 m_jit.move(op2GPR, unboxGPR); 757 unboxDouble(unboxGPR, op2FPR); 758 } 759 760 if (!isKnownInteger(node.child1())) 761 gotDoubleArgs.link(&m_jit); 762 763 if (!isKnownInteger(node.child1()) || !isKnownInteger(node.child2())) { 764 silentSpillAllRegisters(X86Registers::edx); 765 setupTwoStubArgs<FPRInfo::argumentFPR0, FPRInfo::argumentFPR1>(op1FPR, op2FPR); 766 m_jit.appendCall(fmod); 767 boxDouble(FPRInfo::returnValueFPR, X86Registers::edx); 768 silentFillAllRegisters(X86Registers::edx); 769 } 770 771 done.link(&m_jit); 772 773 if (temp2 != InvalidGPRReg) 774 unlock(temp2); 775 776 jsValueResult(X86Registers::edx, m_compileIndex, UseChildrenCalledExplicitly); 217 nonSpeculativeArithMod(node); 777 218 break; 778 219 } … … 1092 533 1093 534 case CheckHasInstance: { 1094 JSValueOperand base(this, node.child1()); 1095 GPRTemporary structure(this); 1096 1097 GPRReg baseReg = base.gpr(); 1098 GPRReg structureReg = structure.gpr(); 1099 1100 // Check that base is a cell. 1101 MacroAssembler::Jump baseNotCell = m_jit.branchTestPtr(MacroAssembler::NonZero, baseReg, GPRInfo::tagMaskRegister); 1102 1103 // Check that base 'ImplementsHasInstance'. 1104 m_jit.loadPtr(MacroAssembler::Address(baseReg, JSCell::structureOffset()), structureReg); 1105 MacroAssembler::Jump implementsHasInstance = m_jit.branchTest8(MacroAssembler::NonZero, MacroAssembler::Address(structureReg, Structure::typeInfoFlagsOffset()), MacroAssembler::TrustedImm32(ImplementsHasInstance)); 1106 1107 // At this point we always throw, so no need to preserve registers. 1108 baseNotCell.link(&m_jit); 1109 m_jit.move(baseReg, GPRInfo::argumentGPR1); 1110 m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); 1111 // At some point we could optimize this to plant a direct jump, rather then checking 1112 // for an exception (operationThrowHasInstanceError always throws). Probably not worth 1113 // adding the extra interface to do this now, but we may also want this for op_throw. 1114 appendCallWithExceptionCheck(operationThrowHasInstanceError); 1115 1116 implementsHasInstance.link(&m_jit); 1117 noResult(m_compileIndex); 535 nonSpeculativeCheckHasInstance(node); 1118 536 break; 1119 537 } 1120 538 1121 539 case InstanceOf: { 1122 JSValueOperand value(this, node.child1()); 1123 JSValueOperand base(this, node.child2()); 1124 JSValueOperand prototype(this, node.child3()); 1125 GPRTemporary scratch(this, base); 1126 1127 GPRReg valueReg = value.gpr(); 1128 GPRReg baseReg = base.gpr(); 1129 GPRReg prototypeReg = prototype.gpr(); 1130 GPRReg scratchReg = scratch.gpr(); 1131 1132 value.use(); 1133 base.use(); 1134 prototype.use(); 1135 1136 // Check that operands are cells (base is checked by CheckHasInstance, so we can just assert). 1137 MacroAssembler::Jump valueNotCell = m_jit.branchTestPtr(MacroAssembler::NonZero, valueReg, GPRInfo::tagMaskRegister); 1138 m_jit.jitAssertIsCell(baseReg); 1139 MacroAssembler::Jump prototypeNotCell = m_jit.branchTestPtr(MacroAssembler::NonZero, prototypeReg, GPRInfo::tagMaskRegister); 1140 1141 // Check that baseVal 'ImplementsDefaultHasInstance'. 1142 m_jit.loadPtr(MacroAssembler::Address(baseReg, JSCell::structureOffset()), scratchReg); 1143 MacroAssembler::Jump notDefaultHasInstance = m_jit.branchTest8(MacroAssembler::Zero, MacroAssembler::Address(scratchReg, Structure::typeInfoFlagsOffset()), TrustedImm32(ImplementsDefaultHasInstance)); 1144 1145 // Check that prototype is an object 1146 m_jit.loadPtr(MacroAssembler::Address(prototypeReg, JSCell::structureOffset()), scratchReg); 1147 MacroAssembler::Jump protoNotObject = m_jit.branchIfNotObject(scratchReg); 1148 1149 // Initialize scratchReg with the value being checked. 1150 m_jit.move(valueReg, scratchReg); 1151 1152 // Walk up the prototype chain of the value (in scratchReg), comparing to prototypeReg. 1153 MacroAssembler::Label loop(&m_jit); 1154 m_jit.loadPtr(MacroAssembler::Address(scratchReg, JSCell::structureOffset()), scratchReg); 1155 m_jit.loadPtr(MacroAssembler::Address(scratchReg, Structure::prototypeOffset()), scratchReg); 1156 MacroAssembler::Jump isInstance = m_jit.branchPtr(MacroAssembler::Equal, scratchReg, prototypeReg); 1157 m_jit.branchTestPtr(MacroAssembler::Zero, scratchReg, GPRInfo::tagMaskRegister).linkTo(loop, &m_jit); 1158 1159 // No match - result is false. 1160 m_jit.move(MacroAssembler::TrustedImmPtr(JSValue::encode(jsBoolean(false))), scratchReg); 1161 MacroAssembler::Jump wasNotInstance = m_jit.jump(); 1162 1163 // Link to here if any checks fail that require us to try calling out to an operation to help, 1164 // e.g. for an API overridden HasInstance. 1165 valueNotCell.link(&m_jit); 1166 prototypeNotCell.link(&m_jit); 1167 notDefaultHasInstance.link(&m_jit); 1168 protoNotObject.link(&m_jit); 1169 1170 silentSpillAllRegisters(scratchReg); 1171 setupStubArguments(valueReg, baseReg, prototypeReg); 1172 m_jit.move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); 1173 appendCallWithExceptionCheck(operationInstanceOf); 1174 m_jit.move(GPRInfo::returnValueGPR, scratchReg); 1175 silentFillAllRegisters(scratchReg); 1176 1177 MacroAssembler::Jump wasNotDefaultHasInstance = m_jit.jump(); 1178 1179 isInstance.link(&m_jit); 1180 m_jit.move(MacroAssembler::TrustedImmPtr(JSValue::encode(jsBoolean(true))), scratchReg); 1181 1182 wasNotInstance.link(&m_jit); 1183 wasNotDefaultHasInstance.link(&m_jit); 1184 jsValueResult(scratchReg, m_compileIndex, UseChildrenCalledExplicitly); 540 nonSpeculativeInstanceOf(node); 1185 541 break; 1186 542 } -
trunk/Source/JavaScriptCore/dfg/DFGNonSpeculativeJIT.h
r91804 r95230 86 86 // These methods are used to plant calls out to C++ 87 87 // helper routines to convert between types. 88 void valueToNumber(JSValueOperand&, GPRReg result);89 void valueToInt32(JSValueOperand&, GPRReg result);90 void numberToInt32(FPRReg, GPRReg result);91 88 92 89 // Record an entry location into the non-speculative code path; … … 98 95 } 99 96 100 // internal helpers for add/sub/mul operations101 void knownConstantArithOp(NodeType op, NodeIndex regChild, NodeIndex immChild, bool commute);102 void basicArithOp(NodeType op, Node&);103 104 97 EntryLocationVector m_entryLocations; 105 98 };
Note: See TracChangeset
for help on using the changeset viewer.