| OLD | NEW |
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 132 if (slots > 0) { | 132 if (slots > 0) { |
| 133 if (FLAG_debug_code) { | 133 if (FLAG_debug_code) { |
| 134 __ mov(Operand(eax), Immediate(slots)); | 134 __ mov(Operand(eax), Immediate(slots)); |
| 135 Label loop; | 135 Label loop; |
| 136 __ bind(&loop); | 136 __ bind(&loop); |
| 137 __ push(Immediate(kSlotsZapValue)); | 137 __ push(Immediate(kSlotsZapValue)); |
| 138 __ dec(eax); | 138 __ dec(eax); |
| 139 __ j(not_zero, &loop); | 139 __ j(not_zero, &loop); |
| 140 } else { | 140 } else { |
| 141 __ sub(Operand(esp), Immediate(slots * kPointerSize)); | 141 __ sub(Operand(esp), Immediate(slots * kPointerSize)); |
| 142 #ifdef _MSC_VER |
| 143 // On windows, you may not access the stack more than one page below |
| 144 // the most recently mapped page. To make the allocated area randomly |
| 145 // accessible, we write to each page in turn (the value is irrelevant). |
| 146 const int kPageSize = 4 * KB; |
| 147 for (int offset = slots * kPointerSize - kPageSize; |
| 148 offset > 0; |
| 149 offset -= kPageSize) { |
| 150 __ mov(Operand(esp, offset), eax); |
| 151 } |
| 152 #endif |
| 142 } | 153 } |
| 143 } | 154 } |
| 144 | 155 |
| 145 // Trace the call. | 156 // Trace the call. |
| 146 if (FLAG_trace) { | 157 if (FLAG_trace) { |
| 147 __ CallRuntime(Runtime::kTraceEnter, 0); | 158 __ CallRuntime(Runtime::kTraceEnter, 0); |
| 148 } | 159 } |
| 149 return !is_aborted(); | 160 return !is_aborted(); |
| 150 } | 161 } |
| 151 | 162 |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 258 // Local or spill slot. Skip the frame pointer, function, and | 269 // Local or spill slot. Skip the frame pointer, function, and |
| 259 // context in the fixed part of the frame. | 270 // context in the fixed part of the frame. |
| 260 return Operand(ebp, -(index + 3) * kPointerSize); | 271 return Operand(ebp, -(index + 3) * kPointerSize); |
| 261 } else { | 272 } else { |
| 262 // Incoming parameter. Skip the return address. | 273 // Incoming parameter. Skip the return address. |
| 263 return Operand(ebp, -(index - 1) * kPointerSize); | 274 return Operand(ebp, -(index - 1) * kPointerSize); |
| 264 } | 275 } |
| 265 } | 276 } |
| 266 | 277 |
| 267 | 278 |
| 279 Operand LCodeGen::HighOperand(LOperand* op) { |
| 280 ASSERT(op->IsDoubleStackSlot()); |
| 281 int index = op->index(); |
| 282 int offset = (index >= 0) ? index + 3 : index - 1; |
| 283 return Operand(ebp, -offset * kPointerSize); |
| 284 } |
| 285 |
| 286 |
| 268 void LCodeGen::WriteTranslation(LEnvironment* environment, | 287 void LCodeGen::WriteTranslation(LEnvironment* environment, |
| 269 Translation* translation) { | 288 Translation* translation) { |
| 270 if (environment == NULL) return; | 289 if (environment == NULL) return; |
| 271 | 290 |
| 272 // The translation includes one command per value in the environment. | 291 // The translation includes one command per value in the environment. |
| 273 int translation_size = environment->values()->length(); | 292 int translation_size = environment->values()->length(); |
| 274 // The output frame height does not include the parameters. | 293 // The output frame height does not include the parameters. |
| 275 int height = translation_size - environment->parameter_count(); | 294 int height = translation_size - environment->parameter_count(); |
| 276 | 295 |
| 277 WriteTranslation(environment->outer(), translation); | 296 WriteTranslation(environment->outer(), translation); |
| (...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 593 } else { | 612 } else { |
| 594 Comment(";;; B%d", label->block_id()); | 613 Comment(";;; B%d", label->block_id()); |
| 595 } | 614 } |
| 596 __ bind(label->label()); | 615 __ bind(label->label()); |
| 597 current_block_ = label->block_id(); | 616 current_block_ = label->block_id(); |
| 598 LCodeGen::DoGap(label); | 617 LCodeGen::DoGap(label); |
| 599 } | 618 } |
| 600 | 619 |
| 601 | 620 |
| 602 void LCodeGen::DoParallelMove(LParallelMove* move) { | 621 void LCodeGen::DoParallelMove(LParallelMove* move) { |
| 603 // xmm0 must always be a scratch register. | 622 resolver_.Resolve(move); |
| 604 XMMRegister xmm_scratch = xmm0; | |
| 605 LUnallocated marker_operand(LUnallocated::NONE); | |
| 606 | |
| 607 Register cpu_scratch = esi; | |
| 608 bool destroys_cpu_scratch = false; | |
| 609 | |
| 610 const ZoneList<LMoveOperands>* moves = | |
| 611 resolver_.Resolve(move->move_operands(), &marker_operand); | |
| 612 for (int i = moves->length() - 1; i >= 0; --i) { | |
| 613 LMoveOperands move = moves->at(i); | |
| 614 LOperand* from = move.from(); | |
| 615 LOperand* to = move.to(); | |
| 616 ASSERT(!from->IsDoubleRegister() || | |
| 617 !ToDoubleRegister(from).is(xmm_scratch)); | |
| 618 ASSERT(!to->IsDoubleRegister() || !ToDoubleRegister(to).is(xmm_scratch)); | |
| 619 ASSERT(!from->IsRegister() || !ToRegister(from).is(cpu_scratch)); | |
| 620 ASSERT(!to->IsRegister() || !ToRegister(to).is(cpu_scratch)); | |
| 621 if (from->IsConstantOperand()) { | |
| 622 __ mov(ToOperand(to), ToImmediate(from)); | |
| 623 } else if (from == &marker_operand) { | |
| 624 if (to->IsRegister() || to->IsStackSlot()) { | |
| 625 __ mov(ToOperand(to), cpu_scratch); | |
| 626 ASSERT(destroys_cpu_scratch); | |
| 627 } else { | |
| 628 ASSERT(to->IsDoubleRegister() || to->IsDoubleStackSlot()); | |
| 629 __ movdbl(ToOperand(to), xmm_scratch); | |
| 630 } | |
| 631 } else if (to == &marker_operand) { | |
| 632 if (from->IsRegister() || from->IsStackSlot()) { | |
| 633 __ mov(cpu_scratch, ToOperand(from)); | |
| 634 destroys_cpu_scratch = true; | |
| 635 } else { | |
| 636 ASSERT(from->IsDoubleRegister() || from->IsDoubleStackSlot()); | |
| 637 __ movdbl(xmm_scratch, ToOperand(from)); | |
| 638 } | |
| 639 } else if (from->IsRegister()) { | |
| 640 __ mov(ToOperand(to), ToRegister(from)); | |
| 641 } else if (to->IsRegister()) { | |
| 642 __ mov(ToRegister(to), ToOperand(from)); | |
| 643 } else if (from->IsStackSlot()) { | |
| 644 ASSERT(to->IsStackSlot()); | |
| 645 __ push(eax); | |
| 646 __ mov(eax, ToOperand(from)); | |
| 647 __ mov(ToOperand(to), eax); | |
| 648 __ pop(eax); | |
| 649 } else if (from->IsDoubleRegister()) { | |
| 650 __ movdbl(ToOperand(to), ToDoubleRegister(from)); | |
| 651 } else if (to->IsDoubleRegister()) { | |
| 652 __ movdbl(ToDoubleRegister(to), ToOperand(from)); | |
| 653 } else { | |
| 654 ASSERT(to->IsDoubleStackSlot() && from->IsDoubleStackSlot()); | |
| 655 __ movdbl(xmm_scratch, ToOperand(from)); | |
| 656 __ movdbl(ToOperand(to), xmm_scratch); | |
| 657 } | |
| 658 } | |
| 659 | |
| 660 if (destroys_cpu_scratch) { | |
| 661 __ mov(cpu_scratch, Operand(ebp, -kPointerSize)); | |
| 662 } | |
| 663 } | 623 } |
| 664 | 624 |
| 665 | 625 |
| 666 void LCodeGen::DoGap(LGap* gap) { | 626 void LCodeGen::DoGap(LGap* gap) { |
| 667 for (int i = LGap::FIRST_INNER_POSITION; | 627 for (int i = LGap::FIRST_INNER_POSITION; |
| 668 i <= LGap::LAST_INNER_POSITION; | 628 i <= LGap::LAST_INNER_POSITION; |
| 669 i++) { | 629 i++) { |
| 670 LGap::InnerPosition inner_pos = static_cast<LGap::InnerPosition>(i); | 630 LGap::InnerPosition inner_pos = static_cast<LGap::InnerPosition>(i); |
| 671 LParallelMove* move = gap->GetParallelMove(inner_pos); | 631 LParallelMove* move = gap->GetParallelMove(inner_pos); |
| 672 if (move != NULL) DoParallelMove(move); | 632 if (move != NULL) DoParallelMove(move); |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 739 } | 699 } |
| 740 } | 700 } |
| 741 | 701 |
| 742 | 702 |
| 743 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { | 703 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { |
| 744 // Nothing to do. | 704 // Nothing to do. |
| 745 } | 705 } |
| 746 | 706 |
| 747 | 707 |
| 748 void LCodeGen::DoModI(LModI* instr) { | 708 void LCodeGen::DoModI(LModI* instr) { |
| 749 LOperand* right = instr->right(); | 709 LOperand* right = instr->InputAt(1); |
| 750 ASSERT(ToRegister(instr->result()).is(edx)); | 710 ASSERT(ToRegister(instr->result()).is(edx)); |
| 751 ASSERT(ToRegister(instr->left()).is(eax)); | 711 ASSERT(ToRegister(instr->InputAt(0)).is(eax)); |
| 752 ASSERT(!ToRegister(instr->right()).is(eax)); | 712 ASSERT(!ToRegister(instr->InputAt(1)).is(eax)); |
| 753 ASSERT(!ToRegister(instr->right()).is(edx)); | 713 ASSERT(!ToRegister(instr->InputAt(1)).is(edx)); |
| 754 | 714 |
| 755 Register right_reg = ToRegister(right); | 715 Register right_reg = ToRegister(right); |
| 756 | 716 |
| 757 // Check for x % 0. | 717 // Check for x % 0. |
| 758 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { | 718 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { |
| 759 __ test(right_reg, ToOperand(right)); | 719 __ test(right_reg, ToOperand(right)); |
| 760 DeoptimizeIf(zero, instr->environment()); | 720 DeoptimizeIf(zero, instr->environment()); |
| 761 } | 721 } |
| 762 | 722 |
| 763 // Sign extend to edx. | 723 // Sign extend to edx. |
| (...skipping 15 matching lines...) Expand all Loading... |
| 779 __ bind(&positive_left); | 739 __ bind(&positive_left); |
| 780 __ idiv(right_reg); | 740 __ idiv(right_reg); |
| 781 __ bind(&done); | 741 __ bind(&done); |
| 782 } else { | 742 } else { |
| 783 __ idiv(right_reg); | 743 __ idiv(right_reg); |
| 784 } | 744 } |
| 785 } | 745 } |
| 786 | 746 |
| 787 | 747 |
| 788 void LCodeGen::DoDivI(LDivI* instr) { | 748 void LCodeGen::DoDivI(LDivI* instr) { |
| 789 LOperand* right = instr->right(); | 749 LOperand* right = instr->InputAt(1); |
| 790 ASSERT(ToRegister(instr->result()).is(eax)); | 750 ASSERT(ToRegister(instr->result()).is(eax)); |
| 791 ASSERT(ToRegister(instr->left()).is(eax)); | 751 ASSERT(ToRegister(instr->InputAt(0)).is(eax)); |
| 792 ASSERT(!ToRegister(instr->right()).is(eax)); | 752 ASSERT(!ToRegister(instr->InputAt(1)).is(eax)); |
| 793 ASSERT(!ToRegister(instr->right()).is(edx)); | 753 ASSERT(!ToRegister(instr->InputAt(1)).is(edx)); |
| 794 | 754 |
| 795 Register left_reg = eax; | 755 Register left_reg = eax; |
| 796 | 756 |
| 797 // Check for x / 0. | 757 // Check for x / 0. |
| 798 Register right_reg = ToRegister(right); | 758 Register right_reg = ToRegister(right); |
| 799 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { | 759 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { |
| 800 __ test(right_reg, ToOperand(right)); | 760 __ test(right_reg, ToOperand(right)); |
| 801 DeoptimizeIf(zero, instr->environment()); | 761 DeoptimizeIf(zero, instr->environment()); |
| 802 } | 762 } |
| 803 | 763 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 825 __ cdq(); | 785 __ cdq(); |
| 826 __ idiv(right_reg); | 786 __ idiv(right_reg); |
| 827 | 787 |
| 828 // Deoptimize if remainder is not 0. | 788 // Deoptimize if remainder is not 0. |
| 829 __ test(edx, Operand(edx)); | 789 __ test(edx, Operand(edx)); |
| 830 DeoptimizeIf(not_zero, instr->environment()); | 790 DeoptimizeIf(not_zero, instr->environment()); |
| 831 } | 791 } |
| 832 | 792 |
| 833 | 793 |
| 834 void LCodeGen::DoMulI(LMulI* instr) { | 794 void LCodeGen::DoMulI(LMulI* instr) { |
| 835 Register left = ToRegister(instr->left()); | 795 Register left = ToRegister(instr->InputAt(0)); |
| 836 LOperand* right = instr->right(); | 796 LOperand* right = instr->InputAt(1); |
| 837 | 797 |
| 838 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 798 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 839 __ mov(ToRegister(instr->temp()), left); | 799 __ mov(ToRegister(instr->TempAt(0)), left); |
| 840 } | 800 } |
| 841 | 801 |
| 842 if (right->IsConstantOperand()) { | 802 if (right->IsConstantOperand()) { |
| 843 __ imul(left, left, ToInteger32(LConstantOperand::cast(right))); | 803 __ imul(left, left, ToInteger32(LConstantOperand::cast(right))); |
| 844 } else { | 804 } else { |
| 845 __ imul(left, ToOperand(right)); | 805 __ imul(left, ToOperand(right)); |
| 846 } | 806 } |
| 847 | 807 |
| 848 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { | 808 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |
| 849 DeoptimizeIf(overflow, instr->environment()); | 809 DeoptimizeIf(overflow, instr->environment()); |
| 850 } | 810 } |
| 851 | 811 |
| 852 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 812 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 853 // Bail out if the result is supposed to be negative zero. | 813 // Bail out if the result is supposed to be negative zero. |
| 854 NearLabel done; | 814 NearLabel done; |
| 855 __ test(left, Operand(left)); | 815 __ test(left, Operand(left)); |
| 856 __ j(not_zero, &done); | 816 __ j(not_zero, &done); |
| 857 if (right->IsConstantOperand()) { | 817 if (right->IsConstantOperand()) { |
| 858 if (ToInteger32(LConstantOperand::cast(right)) < 0) { | 818 if (ToInteger32(LConstantOperand::cast(right)) < 0) { |
| 859 DeoptimizeIf(no_condition, instr->environment()); | 819 DeoptimizeIf(no_condition, instr->environment()); |
| 860 } | 820 } |
| 861 } else { | 821 } else { |
| 862 // Test the non-zero operand for negative sign. | 822 // Test the non-zero operand for negative sign. |
| 863 __ or_(ToRegister(instr->temp()), ToOperand(right)); | 823 __ or_(ToRegister(instr->TempAt(0)), ToOperand(right)); |
| 864 DeoptimizeIf(sign, instr->environment()); | 824 DeoptimizeIf(sign, instr->environment()); |
| 865 } | 825 } |
| 866 __ bind(&done); | 826 __ bind(&done); |
| 867 } | 827 } |
| 868 } | 828 } |
| 869 | 829 |
| 870 | 830 |
| 871 void LCodeGen::DoBitI(LBitI* instr) { | 831 void LCodeGen::DoBitI(LBitI* instr) { |
| 872 LOperand* left = instr->left(); | 832 LOperand* left = instr->InputAt(0); |
| 873 LOperand* right = instr->right(); | 833 LOperand* right = instr->InputAt(1); |
| 874 ASSERT(left->Equals(instr->result())); | 834 ASSERT(left->Equals(instr->result())); |
| 875 ASSERT(left->IsRegister()); | 835 ASSERT(left->IsRegister()); |
| 876 | 836 |
| 877 if (right->IsConstantOperand()) { | 837 if (right->IsConstantOperand()) { |
| 878 int right_operand = ToInteger32(LConstantOperand::cast(right)); | 838 int right_operand = ToInteger32(LConstantOperand::cast(right)); |
| 879 switch (instr->op()) { | 839 switch (instr->op()) { |
| 880 case Token::BIT_AND: | 840 case Token::BIT_AND: |
| 881 __ and_(ToRegister(left), right_operand); | 841 __ and_(ToRegister(left), right_operand); |
| 882 break; | 842 break; |
| 883 case Token::BIT_OR: | 843 case Token::BIT_OR: |
| (...skipping 19 matching lines...) Expand all Loading... |
| 903 break; | 863 break; |
| 904 default: | 864 default: |
| 905 UNREACHABLE(); | 865 UNREACHABLE(); |
| 906 break; | 866 break; |
| 907 } | 867 } |
| 908 } | 868 } |
| 909 } | 869 } |
| 910 | 870 |
| 911 | 871 |
| 912 void LCodeGen::DoShiftI(LShiftI* instr) { | 872 void LCodeGen::DoShiftI(LShiftI* instr) { |
| 913 LOperand* left = instr->left(); | 873 LOperand* left = instr->InputAt(0); |
| 914 LOperand* right = instr->right(); | 874 LOperand* right = instr->InputAt(1); |
| 915 ASSERT(left->Equals(instr->result())); | 875 ASSERT(left->Equals(instr->result())); |
| 916 ASSERT(left->IsRegister()); | 876 ASSERT(left->IsRegister()); |
| 917 if (right->IsRegister()) { | 877 if (right->IsRegister()) { |
| 918 ASSERT(ToRegister(right).is(ecx)); | 878 ASSERT(ToRegister(right).is(ecx)); |
| 919 | 879 |
| 920 switch (instr->op()) { | 880 switch (instr->op()) { |
| 921 case Token::SAR: | 881 case Token::SAR: |
| 922 __ sar_cl(ToRegister(left)); | 882 __ sar_cl(ToRegister(left)); |
| 923 break; | 883 break; |
| 924 case Token::SHR: | 884 case Token::SHR: |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 959 break; | 919 break; |
| 960 default: | 920 default: |
| 961 UNREACHABLE(); | 921 UNREACHABLE(); |
| 962 break; | 922 break; |
| 963 } | 923 } |
| 964 } | 924 } |
| 965 } | 925 } |
| 966 | 926 |
| 967 | 927 |
| 968 void LCodeGen::DoSubI(LSubI* instr) { | 928 void LCodeGen::DoSubI(LSubI* instr) { |
| 969 LOperand* left = instr->left(); | 929 LOperand* left = instr->InputAt(0); |
| 970 LOperand* right = instr->right(); | 930 LOperand* right = instr->InputAt(1); |
| 971 ASSERT(left->Equals(instr->result())); | 931 ASSERT(left->Equals(instr->result())); |
| 972 | 932 |
| 973 if (right->IsConstantOperand()) { | 933 if (right->IsConstantOperand()) { |
| 974 __ sub(ToOperand(left), ToImmediate(right)); | 934 __ sub(ToOperand(left), ToImmediate(right)); |
| 975 } else { | 935 } else { |
| 976 __ sub(ToRegister(left), ToOperand(right)); | 936 __ sub(ToRegister(left), ToOperand(right)); |
| 977 } | 937 } |
| 978 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { | 938 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |
| 979 DeoptimizeIf(overflow, instr->environment()); | 939 DeoptimizeIf(overflow, instr->environment()); |
| 980 } | 940 } |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1015 | 975 |
| 1016 | 976 |
| 1017 void LCodeGen::DoConstantT(LConstantT* instr) { | 977 void LCodeGen::DoConstantT(LConstantT* instr) { |
| 1018 ASSERT(instr->result()->IsRegister()); | 978 ASSERT(instr->result()->IsRegister()); |
| 1019 __ Set(ToRegister(instr->result()), Immediate(instr->value())); | 979 __ Set(ToRegister(instr->result()), Immediate(instr->value())); |
| 1020 } | 980 } |
| 1021 | 981 |
| 1022 | 982 |
| 1023 void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) { | 983 void LCodeGen::DoJSArrayLength(LJSArrayLength* instr) { |
| 1024 Register result = ToRegister(instr->result()); | 984 Register result = ToRegister(instr->result()); |
| 1025 Register array = ToRegister(instr->input()); | 985 Register array = ToRegister(instr->InputAt(0)); |
| 1026 __ mov(result, FieldOperand(array, JSArray::kLengthOffset)); | 986 __ mov(result, FieldOperand(array, JSArray::kLengthOffset)); |
| 1027 } | 987 } |
| 1028 | 988 |
| 1029 | 989 |
| 1030 void LCodeGen::DoFixedArrayLength(LFixedArrayLength* instr) { | 990 void LCodeGen::DoFixedArrayLength(LFixedArrayLength* instr) { |
| 1031 Register result = ToRegister(instr->result()); | 991 Register result = ToRegister(instr->result()); |
| 1032 Register array = ToRegister(instr->input()); | 992 Register array = ToRegister(instr->InputAt(0)); |
| 1033 __ mov(result, FieldOperand(array, FixedArray::kLengthOffset)); | 993 __ mov(result, FieldOperand(array, FixedArray::kLengthOffset)); |
| 1034 } | 994 } |
| 1035 | 995 |
| 1036 | 996 |
| 1037 void LCodeGen::DoValueOf(LValueOf* instr) { | 997 void LCodeGen::DoValueOf(LValueOf* instr) { |
| 1038 Register input = ToRegister(instr->input()); | 998 Register input = ToRegister(instr->InputAt(0)); |
| 1039 Register result = ToRegister(instr->result()); | 999 Register result = ToRegister(instr->result()); |
| 1040 Register map = ToRegister(instr->temporary()); | 1000 Register map = ToRegister(instr->TempAt(0)); |
| 1041 ASSERT(input.is(result)); | 1001 ASSERT(input.is(result)); |
| 1042 NearLabel done; | 1002 NearLabel done; |
| 1043 // If the object is a smi return the object. | 1003 // If the object is a smi return the object. |
| 1044 __ test(input, Immediate(kSmiTagMask)); | 1004 __ test(input, Immediate(kSmiTagMask)); |
| 1045 __ j(zero, &done); | 1005 __ j(zero, &done); |
| 1046 | 1006 |
| 1047 // If the object is not a value type, return the object. | 1007 // If the object is not a value type, return the object. |
| 1048 __ CmpObjectType(input, JS_VALUE_TYPE, map); | 1008 __ CmpObjectType(input, JS_VALUE_TYPE, map); |
| 1049 __ j(not_equal, &done); | 1009 __ j(not_equal, &done); |
| 1050 __ mov(result, FieldOperand(input, JSValue::kValueOffset)); | 1010 __ mov(result, FieldOperand(input, JSValue::kValueOffset)); |
| 1051 | 1011 |
| 1052 __ bind(&done); | 1012 __ bind(&done); |
| 1053 } | 1013 } |
| 1054 | 1014 |
| 1055 | 1015 |
| 1056 void LCodeGen::DoBitNotI(LBitNotI* instr) { | 1016 void LCodeGen::DoBitNotI(LBitNotI* instr) { |
| 1057 LOperand* input = instr->input(); | 1017 LOperand* input = instr->InputAt(0); |
| 1058 ASSERT(input->Equals(instr->result())); | 1018 ASSERT(input->Equals(instr->result())); |
| 1059 __ not_(ToRegister(input)); | 1019 __ not_(ToRegister(input)); |
| 1060 } | 1020 } |
| 1061 | 1021 |
| 1062 | 1022 |
| 1063 void LCodeGen::DoThrow(LThrow* instr) { | 1023 void LCodeGen::DoThrow(LThrow* instr) { |
| 1064 __ push(ToOperand(instr->input())); | 1024 __ push(ToOperand(instr->InputAt(0))); |
| 1065 CallRuntime(Runtime::kThrow, 1, instr); | 1025 CallRuntime(Runtime::kThrow, 1, instr); |
| 1066 | 1026 |
| 1067 if (FLAG_debug_code) { | 1027 if (FLAG_debug_code) { |
| 1068 Comment("Unreachable code."); | 1028 Comment("Unreachable code."); |
| 1069 __ int3(); | 1029 __ int3(); |
| 1070 } | 1030 } |
| 1071 } | 1031 } |
| 1072 | 1032 |
| 1073 | 1033 |
| 1074 void LCodeGen::DoAddI(LAddI* instr) { | 1034 void LCodeGen::DoAddI(LAddI* instr) { |
| 1075 LOperand* left = instr->left(); | 1035 LOperand* left = instr->InputAt(0); |
| 1076 LOperand* right = instr->right(); | 1036 LOperand* right = instr->InputAt(1); |
| 1077 ASSERT(left->Equals(instr->result())); | 1037 ASSERT(left->Equals(instr->result())); |
| 1078 | 1038 |
| 1079 if (right->IsConstantOperand()) { | 1039 if (right->IsConstantOperand()) { |
| 1080 __ add(ToOperand(left), ToImmediate(right)); | 1040 __ add(ToOperand(left), ToImmediate(right)); |
| 1081 } else { | 1041 } else { |
| 1082 __ add(ToRegister(left), ToOperand(right)); | 1042 __ add(ToRegister(left), ToOperand(right)); |
| 1083 } | 1043 } |
| 1084 | 1044 |
| 1085 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { | 1045 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |
| 1086 DeoptimizeIf(overflow, instr->environment()); | 1046 DeoptimizeIf(overflow, instr->environment()); |
| 1087 } | 1047 } |
| 1088 } | 1048 } |
| 1089 | 1049 |
| 1090 | 1050 |
| 1091 void LCodeGen::DoArithmeticD(LArithmeticD* instr) { | 1051 void LCodeGen::DoArithmeticD(LArithmeticD* instr) { |
| 1092 LOperand* left = instr->left(); | 1052 LOperand* left = instr->InputAt(0); |
| 1093 LOperand* right = instr->right(); | 1053 LOperand* right = instr->InputAt(1); |
| 1094 // Modulo uses a fixed result register. | 1054 // Modulo uses a fixed result register. |
| 1095 ASSERT(instr->op() == Token::MOD || left->Equals(instr->result())); | 1055 ASSERT(instr->op() == Token::MOD || left->Equals(instr->result())); |
| 1096 switch (instr->op()) { | 1056 switch (instr->op()) { |
| 1097 case Token::ADD: | 1057 case Token::ADD: |
| 1098 __ addsd(ToDoubleRegister(left), ToDoubleRegister(right)); | 1058 __ addsd(ToDoubleRegister(left), ToDoubleRegister(right)); |
| 1099 break; | 1059 break; |
| 1100 case Token::SUB: | 1060 case Token::SUB: |
| 1101 __ subsd(ToDoubleRegister(left), ToDoubleRegister(right)); | 1061 __ subsd(ToDoubleRegister(left), ToDoubleRegister(right)); |
| 1102 break; | 1062 break; |
| 1103 case Token::MUL: | 1063 case Token::MUL: |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1122 break; | 1082 break; |
| 1123 } | 1083 } |
| 1124 default: | 1084 default: |
| 1125 UNREACHABLE(); | 1085 UNREACHABLE(); |
| 1126 break; | 1086 break; |
| 1127 } | 1087 } |
| 1128 } | 1088 } |
| 1129 | 1089 |
| 1130 | 1090 |
| 1131 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { | 1091 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { |
| 1132 ASSERT(ToRegister(instr->left()).is(edx)); | 1092 ASSERT(ToRegister(instr->InputAt(0)).is(edx)); |
| 1133 ASSERT(ToRegister(instr->right()).is(eax)); | 1093 ASSERT(ToRegister(instr->InputAt(1)).is(eax)); |
| 1134 ASSERT(ToRegister(instr->result()).is(eax)); | 1094 ASSERT(ToRegister(instr->result()).is(eax)); |
| 1135 | 1095 |
| 1136 TypeRecordingBinaryOpStub stub(instr->op(), NO_OVERWRITE); | 1096 TypeRecordingBinaryOpStub stub(instr->op(), NO_OVERWRITE); |
| 1137 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); | 1097 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); |
| 1138 } | 1098 } |
| 1139 | 1099 |
| 1140 | 1100 |
| 1141 int LCodeGen::GetNextEmittedBlock(int block) { | 1101 int LCodeGen::GetNextEmittedBlock(int block) { |
| 1142 for (int i = block + 1; i < graph()->blocks()->length(); ++i) { | 1102 for (int i = block + 1; i < graph()->blocks()->length(); ++i) { |
| 1143 LLabel* label = chunk_->GetLabel(i); | 1103 LLabel* label = chunk_->GetLabel(i); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1164 } | 1124 } |
| 1165 } | 1125 } |
| 1166 | 1126 |
| 1167 | 1127 |
| 1168 void LCodeGen::DoBranch(LBranch* instr) { | 1128 void LCodeGen::DoBranch(LBranch* instr) { |
| 1169 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1129 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 1170 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1130 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 1171 | 1131 |
| 1172 Representation r = instr->hydrogen()->representation(); | 1132 Representation r = instr->hydrogen()->representation(); |
| 1173 if (r.IsInteger32()) { | 1133 if (r.IsInteger32()) { |
| 1174 Register reg = ToRegister(instr->input()); | 1134 Register reg = ToRegister(instr->InputAt(0)); |
| 1175 __ test(reg, Operand(reg)); | 1135 __ test(reg, Operand(reg)); |
| 1176 EmitBranch(true_block, false_block, not_zero); | 1136 EmitBranch(true_block, false_block, not_zero); |
| 1177 } else if (r.IsDouble()) { | 1137 } else if (r.IsDouble()) { |
| 1178 XMMRegister reg = ToDoubleRegister(instr->input()); | 1138 XMMRegister reg = ToDoubleRegister(instr->InputAt(0)); |
| 1179 __ xorpd(xmm0, xmm0); | 1139 __ xorpd(xmm0, xmm0); |
| 1180 __ ucomisd(reg, xmm0); | 1140 __ ucomisd(reg, xmm0); |
| 1181 EmitBranch(true_block, false_block, not_equal); | 1141 EmitBranch(true_block, false_block, not_equal); |
| 1182 } else { | 1142 } else { |
| 1183 ASSERT(r.IsTagged()); | 1143 ASSERT(r.IsTagged()); |
| 1184 Register reg = ToRegister(instr->input()); | 1144 Register reg = ToRegister(instr->InputAt(0)); |
| 1185 if (instr->hydrogen()->type().IsBoolean()) { | 1145 if (instr->hydrogen()->type().IsBoolean()) { |
| 1186 __ cmp(reg, FACTORY->true_value()); | 1146 __ cmp(reg, FACTORY->true_value()); |
| 1187 EmitBranch(true_block, false_block, equal); | 1147 EmitBranch(true_block, false_block, equal); |
| 1188 } else { | 1148 } else { |
| 1189 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 1149 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
| 1190 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1150 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
| 1191 | 1151 |
| 1192 __ cmp(reg, FACTORY->undefined_value()); | 1152 __ cmp(reg, FACTORY->undefined_value()); |
| 1193 __ j(equal, false_label); | 1153 __ j(equal, false_label); |
| 1194 __ cmp(reg, FACTORY->true_value()); | 1154 __ cmp(reg, FACTORY->true_value()); |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1302 void LCodeGen::EmitCmpI(LOperand* left, LOperand* right) { | 1262 void LCodeGen::EmitCmpI(LOperand* left, LOperand* right) { |
| 1303 if (right->IsConstantOperand()) { | 1263 if (right->IsConstantOperand()) { |
| 1304 __ cmp(ToOperand(left), ToImmediate(right)); | 1264 __ cmp(ToOperand(left), ToImmediate(right)); |
| 1305 } else { | 1265 } else { |
| 1306 __ cmp(ToRegister(left), ToOperand(right)); | 1266 __ cmp(ToRegister(left), ToOperand(right)); |
| 1307 } | 1267 } |
| 1308 } | 1268 } |
| 1309 | 1269 |
| 1310 | 1270 |
| 1311 void LCodeGen::DoCmpID(LCmpID* instr) { | 1271 void LCodeGen::DoCmpID(LCmpID* instr) { |
| 1312 LOperand* left = instr->left(); | 1272 LOperand* left = instr->InputAt(0); |
| 1313 LOperand* right = instr->right(); | 1273 LOperand* right = instr->InputAt(1); |
| 1314 LOperand* result = instr->result(); | 1274 LOperand* result = instr->result(); |
| 1315 | 1275 |
| 1316 NearLabel unordered; | 1276 NearLabel unordered; |
| 1317 if (instr->is_double()) { | 1277 if (instr->is_double()) { |
| 1318 // Don't base result on EFLAGS when a NaN is involved. Instead | 1278 // Don't base result on EFLAGS when a NaN is involved. Instead |
| 1319 // jump to the unordered case, which produces a false value. | 1279 // jump to the unordered case, which produces a false value. |
| 1320 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right)); | 1280 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right)); |
| 1321 __ j(parity_even, &unordered, not_taken); | 1281 __ j(parity_even, &unordered, not_taken); |
| 1322 } else { | 1282 } else { |
| 1323 EmitCmpI(left, right); | 1283 EmitCmpI(left, right); |
| 1324 } | 1284 } |
| 1325 | 1285 |
| 1326 NearLabel done; | 1286 NearLabel done; |
| 1327 Condition cc = TokenToCondition(instr->op(), instr->is_double()); | 1287 Condition cc = TokenToCondition(instr->op(), instr->is_double()); |
| 1328 __ mov(ToRegister(result), Handle<Object>(HEAP->true_value())); | 1288 __ mov(ToRegister(result), FACTORY->true_value()); |
| 1329 __ j(cc, &done); | 1289 __ j(cc, &done); |
| 1330 | 1290 |
| 1331 __ bind(&unordered); | 1291 __ bind(&unordered); |
| 1332 __ mov(ToRegister(result), Handle<Object>(HEAP->false_value())); | 1292 __ mov(ToRegister(result), FACTORY->false_value()); |
| 1333 __ bind(&done); | 1293 __ bind(&done); |
| 1334 } | 1294 } |
| 1335 | 1295 |
| 1336 | 1296 |
| 1337 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { | 1297 void LCodeGen::DoCmpIDAndBranch(LCmpIDAndBranch* instr) { |
| 1338 LOperand* left = instr->left(); | 1298 LOperand* left = instr->InputAt(0); |
| 1339 LOperand* right = instr->right(); | 1299 LOperand* right = instr->InputAt(1); |
| 1340 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1300 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 1341 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1301 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 1342 | 1302 |
| 1343 if (instr->is_double()) { | 1303 if (instr->is_double()) { |
| 1344 // Don't base result on EFLAGS when a NaN is involved. Instead | 1304 // Don't base result on EFLAGS when a NaN is involved. Instead |
| 1345 // jump to the false block. | 1305 // jump to the false block. |
| 1346 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right)); | 1306 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right)); |
| 1347 __ j(parity_even, chunk_->GetAssemblyLabel(false_block)); | 1307 __ j(parity_even, chunk_->GetAssemblyLabel(false_block)); |
| 1348 } else { | 1308 } else { |
| 1349 EmitCmpI(left, right); | 1309 EmitCmpI(left, right); |
| 1350 } | 1310 } |
| 1351 | 1311 |
| 1352 Condition cc = TokenToCondition(instr->op(), instr->is_double()); | 1312 Condition cc = TokenToCondition(instr->op(), instr->is_double()); |
| 1353 EmitBranch(true_block, false_block, cc); | 1313 EmitBranch(true_block, false_block, cc); |
| 1354 } | 1314 } |
| 1355 | 1315 |
| 1356 | 1316 |
| 1357 void LCodeGen::DoCmpJSObjectEq(LCmpJSObjectEq* instr) { | 1317 void LCodeGen::DoCmpJSObjectEq(LCmpJSObjectEq* instr) { |
| 1358 Register left = ToRegister(instr->left()); | 1318 Register left = ToRegister(instr->InputAt(0)); |
| 1359 Register right = ToRegister(instr->right()); | 1319 Register right = ToRegister(instr->InputAt(1)); |
| 1360 Register result = ToRegister(instr->result()); | 1320 Register result = ToRegister(instr->result()); |
| 1361 | 1321 |
| 1362 __ cmp(left, Operand(right)); | 1322 __ cmp(left, Operand(right)); |
| 1363 __ mov(result, Handle<Object>(HEAP->true_value())); | 1323 __ mov(result, FACTORY->true_value()); |
| 1364 NearLabel done; | 1324 NearLabel done; |
| 1365 __ j(equal, &done); | 1325 __ j(equal, &done); |
| 1366 __ mov(result, Handle<Object>(HEAP->false_value())); | 1326 __ mov(result, FACTORY->false_value()); |
| 1367 __ bind(&done); | 1327 __ bind(&done); |
| 1368 } | 1328 } |
| 1369 | 1329 |
| 1370 | 1330 |
| 1371 void LCodeGen::DoCmpJSObjectEqAndBranch(LCmpJSObjectEqAndBranch* instr) { | 1331 void LCodeGen::DoCmpJSObjectEqAndBranch(LCmpJSObjectEqAndBranch* instr) { |
| 1372 Register left = ToRegister(instr->left()); | 1332 Register left = ToRegister(instr->InputAt(0)); |
| 1373 Register right = ToRegister(instr->right()); | 1333 Register right = ToRegister(instr->InputAt(1)); |
| 1374 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1334 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 1375 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1335 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 1376 | 1336 |
| 1377 __ cmp(left, Operand(right)); | 1337 __ cmp(left, Operand(right)); |
| 1378 EmitBranch(true_block, false_block, equal); | 1338 EmitBranch(true_block, false_block, equal); |
| 1379 } | 1339 } |
| 1380 | 1340 |
| 1381 | 1341 |
| 1382 void LCodeGen::DoIsNull(LIsNull* instr) { | 1342 void LCodeGen::DoIsNull(LIsNull* instr) { |
| 1383 Register reg = ToRegister(instr->input()); | 1343 Register reg = ToRegister(instr->InputAt(0)); |
| 1384 Register result = ToRegister(instr->result()); | 1344 Register result = ToRegister(instr->result()); |
| 1385 | 1345 |
| 1386 // TODO(fsc): If the expression is known to be a smi, then it's | 1346 // TODO(fsc): If the expression is known to be a smi, then it's |
| 1387 // definitely not null. Materialize false. | 1347 // definitely not null. Materialize false. |
| 1388 | 1348 |
| 1389 __ cmp(reg, FACTORY->null_value()); | 1349 __ cmp(reg, FACTORY->null_value()); |
| 1390 if (instr->is_strict()) { | 1350 if (instr->is_strict()) { |
| 1391 __ mov(result, Handle<Object>(HEAP->true_value())); | 1351 __ mov(result, FACTORY->true_value()); |
| 1392 NearLabel done; | 1352 NearLabel done; |
| 1393 __ j(equal, &done); | 1353 __ j(equal, &done); |
| 1394 __ mov(result, Handle<Object>(HEAP->false_value())); | 1354 __ mov(result, FACTORY->false_value()); |
| 1395 __ bind(&done); | 1355 __ bind(&done); |
| 1396 } else { | 1356 } else { |
| 1397 NearLabel true_value, false_value, done; | 1357 NearLabel true_value, false_value, done; |
| 1398 __ j(equal, &true_value); | 1358 __ j(equal, &true_value); |
| 1399 __ cmp(reg, FACTORY->undefined_value()); | 1359 __ cmp(reg, FACTORY->undefined_value()); |
| 1400 __ j(equal, &true_value); | 1360 __ j(equal, &true_value); |
| 1401 __ test(reg, Immediate(kSmiTagMask)); | 1361 __ test(reg, Immediate(kSmiTagMask)); |
| 1402 __ j(zero, &false_value); | 1362 __ j(zero, &false_value); |
| 1403 // Check for undetectable objects by looking in the bit field in | 1363 // Check for undetectable objects by looking in the bit field in |
| 1404 // the map. The object has already been smi checked. | 1364 // the map. The object has already been smi checked. |
| 1405 Register scratch = result; | 1365 Register scratch = result; |
| 1406 __ mov(scratch, FieldOperand(reg, HeapObject::kMapOffset)); | 1366 __ mov(scratch, FieldOperand(reg, HeapObject::kMapOffset)); |
| 1407 __ movzx_b(scratch, FieldOperand(scratch, Map::kBitFieldOffset)); | 1367 __ movzx_b(scratch, FieldOperand(scratch, Map::kBitFieldOffset)); |
| 1408 __ test(scratch, Immediate(1 << Map::kIsUndetectable)); | 1368 __ test(scratch, Immediate(1 << Map::kIsUndetectable)); |
| 1409 __ j(not_zero, &true_value); | 1369 __ j(not_zero, &true_value); |
| 1410 __ bind(&false_value); | 1370 __ bind(&false_value); |
| 1411 __ mov(result, Handle<Object>(HEAP->false_value())); | 1371 __ mov(result, FACTORY->false_value()); |
| 1412 __ jmp(&done); | 1372 __ jmp(&done); |
| 1413 __ bind(&true_value); | 1373 __ bind(&true_value); |
| 1414 __ mov(result, Handle<Object>(HEAP->true_value())); | 1374 __ mov(result, FACTORY->true_value()); |
| 1415 __ bind(&done); | 1375 __ bind(&done); |
| 1416 } | 1376 } |
| 1417 } | 1377 } |
| 1418 | 1378 |
| 1419 | 1379 |
| 1420 void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) { | 1380 void LCodeGen::DoIsNullAndBranch(LIsNullAndBranch* instr) { |
| 1421 Register reg = ToRegister(instr->input()); | 1381 Register reg = ToRegister(instr->InputAt(0)); |
| 1422 | 1382 |
| 1423 // TODO(fsc): If the expression is known to be a smi, then it's | 1383 // TODO(fsc): If the expression is known to be a smi, then it's |
| 1424 // definitely not null. Jump to the false block. | 1384 // definitely not null. Jump to the false block. |
| 1425 | 1385 |
| 1426 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1386 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 1427 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1387 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 1428 | 1388 |
| 1429 __ cmp(reg, FACTORY->null_value()); | 1389 __ cmp(reg, FACTORY->null_value()); |
| 1430 if (instr->is_strict()) { | 1390 if (instr->is_strict()) { |
| 1431 EmitBranch(true_block, false_block, equal); | 1391 EmitBranch(true_block, false_block, equal); |
| 1432 } else { | 1392 } else { |
| 1433 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 1393 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
| 1434 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1394 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
| 1435 __ j(equal, true_label); | 1395 __ j(equal, true_label); |
| 1436 __ cmp(reg, FACTORY->undefined_value()); | 1396 __ cmp(reg, FACTORY->undefined_value()); |
| 1437 __ j(equal, true_label); | 1397 __ j(equal, true_label); |
| 1438 __ test(reg, Immediate(kSmiTagMask)); | 1398 __ test(reg, Immediate(kSmiTagMask)); |
| 1439 __ j(zero, false_label); | 1399 __ j(zero, false_label); |
| 1440 // Check for undetectable objects by looking in the bit field in | 1400 // Check for undetectable objects by looking in the bit field in |
| 1441 // the map. The object has already been smi checked. | 1401 // the map. The object has already been smi checked. |
| 1442 Register scratch = ToRegister(instr->temp()); | 1402 Register scratch = ToRegister(instr->TempAt(0)); |
| 1443 __ mov(scratch, FieldOperand(reg, HeapObject::kMapOffset)); | 1403 __ mov(scratch, FieldOperand(reg, HeapObject::kMapOffset)); |
| 1444 __ movzx_b(scratch, FieldOperand(scratch, Map::kBitFieldOffset)); | 1404 __ movzx_b(scratch, FieldOperand(scratch, Map::kBitFieldOffset)); |
| 1445 __ test(scratch, Immediate(1 << Map::kIsUndetectable)); | 1405 __ test(scratch, Immediate(1 << Map::kIsUndetectable)); |
| 1446 EmitBranch(true_block, false_block, not_zero); | 1406 EmitBranch(true_block, false_block, not_zero); |
| 1447 } | 1407 } |
| 1448 } | 1408 } |
| 1449 | 1409 |
| 1450 | 1410 |
| 1451 Condition LCodeGen::EmitIsObject(Register input, | 1411 Condition LCodeGen::EmitIsObject(Register input, |
| 1452 Register temp1, | 1412 Register temp1, |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1471 | 1431 |
| 1472 __ movzx_b(temp2, FieldOperand(temp1, Map::kInstanceTypeOffset)); | 1432 __ movzx_b(temp2, FieldOperand(temp1, Map::kInstanceTypeOffset)); |
| 1473 __ cmp(temp2, FIRST_JS_OBJECT_TYPE); | 1433 __ cmp(temp2, FIRST_JS_OBJECT_TYPE); |
| 1474 __ j(below, is_not_object); | 1434 __ j(below, is_not_object); |
| 1475 __ cmp(temp2, LAST_JS_OBJECT_TYPE); | 1435 __ cmp(temp2, LAST_JS_OBJECT_TYPE); |
| 1476 return below_equal; | 1436 return below_equal; |
| 1477 } | 1437 } |
| 1478 | 1438 |
| 1479 | 1439 |
| 1480 void LCodeGen::DoIsObject(LIsObject* instr) { | 1440 void LCodeGen::DoIsObject(LIsObject* instr) { |
| 1481 Register reg = ToRegister(instr->input()); | 1441 Register reg = ToRegister(instr->InputAt(0)); |
| 1482 Register result = ToRegister(instr->result()); | 1442 Register result = ToRegister(instr->result()); |
| 1483 Register temp = ToRegister(instr->temp()); | 1443 Register temp = ToRegister(instr->TempAt(0)); |
| 1484 Label is_false, is_true, done; | 1444 Label is_false, is_true, done; |
| 1485 | 1445 |
| 1486 Condition true_cond = EmitIsObject(reg, result, temp, &is_false, &is_true); | 1446 Condition true_cond = EmitIsObject(reg, result, temp, &is_false, &is_true); |
| 1487 __ j(true_cond, &is_true); | 1447 __ j(true_cond, &is_true); |
| 1488 | 1448 |
| 1489 __ bind(&is_false); | 1449 __ bind(&is_false); |
| 1490 __ mov(result, Handle<Object>(HEAP->false_value())); | 1450 __ mov(result, FACTORY->false_value()); |
| 1491 __ jmp(&done); | 1451 __ jmp(&done); |
| 1492 | 1452 |
| 1493 __ bind(&is_true); | 1453 __ bind(&is_true); |
| 1494 __ mov(result, Handle<Object>(HEAP->true_value())); | 1454 __ mov(result, FACTORY->true_value()); |
| 1495 | 1455 |
| 1496 __ bind(&done); | 1456 __ bind(&done); |
| 1497 } | 1457 } |
| 1498 | 1458 |
| 1499 | 1459 |
| 1500 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { | 1460 void LCodeGen::DoIsObjectAndBranch(LIsObjectAndBranch* instr) { |
| 1501 Register reg = ToRegister(instr->input()); | 1461 Register reg = ToRegister(instr->InputAt(0)); |
| 1502 Register temp = ToRegister(instr->temp()); | 1462 Register temp = ToRegister(instr->TempAt(0)); |
| 1503 Register temp2 = ToRegister(instr->temp2()); | 1463 Register temp2 = ToRegister(instr->TempAt(1)); |
| 1504 | 1464 |
| 1505 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1465 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 1506 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1466 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 1507 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 1467 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
| 1508 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1468 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
| 1509 | 1469 |
| 1510 Condition true_cond = EmitIsObject(reg, temp, temp2, false_label, true_label); | 1470 Condition true_cond = EmitIsObject(reg, temp, temp2, false_label, true_label); |
| 1511 | 1471 |
| 1512 EmitBranch(true_block, false_block, true_cond); | 1472 EmitBranch(true_block, false_block, true_cond); |
| 1513 } | 1473 } |
| 1514 | 1474 |
| 1515 | 1475 |
| 1516 void LCodeGen::DoIsSmi(LIsSmi* instr) { | 1476 void LCodeGen::DoIsSmi(LIsSmi* instr) { |
| 1517 Operand input = ToOperand(instr->input()); | 1477 Operand input = ToOperand(instr->InputAt(0)); |
| 1518 Register result = ToRegister(instr->result()); | 1478 Register result = ToRegister(instr->result()); |
| 1519 | 1479 |
| 1520 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); | 1480 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); |
| 1521 __ test(input, Immediate(kSmiTagMask)); | 1481 __ test(input, Immediate(kSmiTagMask)); |
| 1522 __ mov(result, Handle<Object>(HEAP->true_value())); | 1482 __ mov(result, FACTORY->true_value()); |
| 1523 NearLabel done; | 1483 NearLabel done; |
| 1524 __ j(zero, &done); | 1484 __ j(zero, &done); |
| 1525 __ mov(result, Handle<Object>(HEAP->false_value())); | 1485 __ mov(result, FACTORY->false_value()); |
| 1526 __ bind(&done); | 1486 __ bind(&done); |
| 1527 } | 1487 } |
| 1528 | 1488 |
| 1529 | 1489 |
| 1530 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { | 1490 void LCodeGen::DoIsSmiAndBranch(LIsSmiAndBranch* instr) { |
| 1531 Operand input = ToOperand(instr->input()); | 1491 Operand input = ToOperand(instr->InputAt(0)); |
| 1532 | 1492 |
| 1533 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1493 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 1534 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1494 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 1535 | 1495 |
| 1536 __ test(input, Immediate(kSmiTagMask)); | 1496 __ test(input, Immediate(kSmiTagMask)); |
| 1537 EmitBranch(true_block, false_block, zero); | 1497 EmitBranch(true_block, false_block, zero); |
| 1538 } | 1498 } |
| 1539 | 1499 |
| 1540 | 1500 |
| 1541 InstanceType LHasInstanceType::TestType() { | 1501 static InstanceType TestType(HHasInstanceType* instr) { |
| 1542 InstanceType from = hydrogen()->from(); | 1502 InstanceType from = instr->from(); |
| 1543 InstanceType to = hydrogen()->to(); | 1503 InstanceType to = instr->to(); |
| 1544 if (from == FIRST_TYPE) return to; | 1504 if (from == FIRST_TYPE) return to; |
| 1545 ASSERT(from == to || to == LAST_TYPE); | 1505 ASSERT(from == to || to == LAST_TYPE); |
| 1546 return from; | 1506 return from; |
| 1547 } | 1507 } |
| 1548 | 1508 |
| 1549 | 1509 |
| 1550 | 1510 static Condition BranchCondition(HHasInstanceType* instr) { |
| 1551 Condition LHasInstanceType::BranchCondition() { | 1511 InstanceType from = instr->from(); |
| 1552 InstanceType from = hydrogen()->from(); | 1512 InstanceType to = instr->to(); |
| 1553 InstanceType to = hydrogen()->to(); | |
| 1554 if (from == to) return equal; | 1513 if (from == to) return equal; |
| 1555 if (to == LAST_TYPE) return above_equal; | 1514 if (to == LAST_TYPE) return above_equal; |
| 1556 if (from == FIRST_TYPE) return below_equal; | 1515 if (from == FIRST_TYPE) return below_equal; |
| 1557 UNREACHABLE(); | 1516 UNREACHABLE(); |
| 1558 return equal; | 1517 return equal; |
| 1559 } | 1518 } |
| 1560 | 1519 |
| 1561 | 1520 |
| 1562 void LCodeGen::DoHasInstanceType(LHasInstanceType* instr) { | 1521 void LCodeGen::DoHasInstanceType(LHasInstanceType* instr) { |
| 1563 Register input = ToRegister(instr->input()); | 1522 Register input = ToRegister(instr->InputAt(0)); |
| 1564 Register result = ToRegister(instr->result()); | 1523 Register result = ToRegister(instr->result()); |
| 1565 | 1524 |
| 1566 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); | 1525 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); |
| 1567 __ test(input, Immediate(kSmiTagMask)); | 1526 __ test(input, Immediate(kSmiTagMask)); |
| 1568 NearLabel done, is_false; | 1527 NearLabel done, is_false; |
| 1569 __ j(zero, &is_false); | 1528 __ j(zero, &is_false); |
| 1570 __ CmpObjectType(input, instr->TestType(), result); | 1529 __ CmpObjectType(input, TestType(instr->hydrogen()), result); |
| 1571 __ j(NegateCondition(instr->BranchCondition()), &is_false); | 1530 __ j(NegateCondition(BranchCondition(instr->hydrogen())), &is_false); |
| 1572 __ mov(result, Handle<Object>(HEAP->true_value())); | 1531 __ mov(result, FACTORY->true_value()); |
| 1573 __ jmp(&done); | 1532 __ jmp(&done); |
| 1574 __ bind(&is_false); | 1533 __ bind(&is_false); |
| 1575 __ mov(result, Handle<Object>(HEAP->false_value())); | 1534 __ mov(result, FACTORY->false_value()); |
| 1576 __ bind(&done); | 1535 __ bind(&done); |
| 1577 } | 1536 } |
| 1578 | 1537 |
| 1579 | 1538 |
| 1580 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { | 1539 void LCodeGen::DoHasInstanceTypeAndBranch(LHasInstanceTypeAndBranch* instr) { |
| 1581 Register input = ToRegister(instr->input()); | 1540 Register input = ToRegister(instr->InputAt(0)); |
| 1582 Register temp = ToRegister(instr->temp()); | 1541 Register temp = ToRegister(instr->TempAt(0)); |
| 1583 | 1542 |
| 1584 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1543 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 1585 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1544 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 1586 | 1545 |
| 1587 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1546 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
| 1588 | 1547 |
| 1589 __ test(input, Immediate(kSmiTagMask)); | 1548 __ test(input, Immediate(kSmiTagMask)); |
| 1590 __ j(zero, false_label); | 1549 __ j(zero, false_label); |
| 1591 | 1550 |
| 1592 __ CmpObjectType(input, instr->TestType(), temp); | 1551 __ CmpObjectType(input, TestType(instr->hydrogen()), temp); |
| 1593 EmitBranch(true_block, false_block, instr->BranchCondition()); | 1552 EmitBranch(true_block, false_block, BranchCondition(instr->hydrogen())); |
| 1594 } | 1553 } |
| 1595 | 1554 |
| 1596 | 1555 |
| 1597 void LCodeGen::DoHasCachedArrayIndex(LHasCachedArrayIndex* instr) { | 1556 void LCodeGen::DoHasCachedArrayIndex(LHasCachedArrayIndex* instr) { |
| 1598 Register input = ToRegister(instr->input()); | 1557 Register input = ToRegister(instr->InputAt(0)); |
| 1599 Register result = ToRegister(instr->result()); | 1558 Register result = ToRegister(instr->result()); |
| 1600 | 1559 |
| 1601 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); | 1560 ASSERT(instr->hydrogen()->value()->representation().IsTagged()); |
| 1602 __ mov(result, Handle<Object>(HEAP->true_value())); | 1561 __ mov(result, FACTORY->true_value()); |
| 1603 __ test(FieldOperand(input, String::kHashFieldOffset), | 1562 __ test(FieldOperand(input, String::kHashFieldOffset), |
| 1604 Immediate(String::kContainsCachedArrayIndexMask)); | 1563 Immediate(String::kContainsCachedArrayIndexMask)); |
| 1605 NearLabel done; | 1564 NearLabel done; |
| 1606 __ j(not_zero, &done); | 1565 __ j(not_zero, &done); |
| 1607 __ mov(result, Handle<Object>(HEAP->false_value())); | 1566 __ mov(result, FACTORY->false_value()); |
| 1608 __ bind(&done); | 1567 __ bind(&done); |
| 1609 } | 1568 } |
| 1610 | 1569 |
| 1611 | 1570 |
| 1612 void LCodeGen::DoHasCachedArrayIndexAndBranch( | 1571 void LCodeGen::DoHasCachedArrayIndexAndBranch( |
| 1613 LHasCachedArrayIndexAndBranch* instr) { | 1572 LHasCachedArrayIndexAndBranch* instr) { |
| 1614 Register input = ToRegister(instr->input()); | 1573 Register input = ToRegister(instr->InputAt(0)); |
| 1615 | 1574 |
| 1616 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1575 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 1617 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1576 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 1618 | 1577 |
| 1619 __ test(FieldOperand(input, String::kHashFieldOffset), | 1578 __ test(FieldOperand(input, String::kHashFieldOffset), |
| 1620 Immediate(String::kContainsCachedArrayIndexMask)); | 1579 Immediate(String::kContainsCachedArrayIndexMask)); |
| 1621 EmitBranch(true_block, false_block, not_equal); | 1580 EmitBranch(true_block, false_block, not_equal); |
| 1622 } | 1581 } |
| 1623 | 1582 |
| 1624 | 1583 |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1673 // booted. This routine isn't expected to work for random API-created | 1632 // booted. This routine isn't expected to work for random API-created |
| 1674 // classes and it doesn't have to because you can't access it with natives | 1633 // classes and it doesn't have to because you can't access it with natives |
| 1675 // syntax. Since both sides are symbols it is sufficient to use an identity | 1634 // syntax. Since both sides are symbols it is sufficient to use an identity |
| 1676 // comparison. | 1635 // comparison. |
| 1677 __ cmp(temp, class_name); | 1636 __ cmp(temp, class_name); |
| 1678 // End with the answer in the z flag. | 1637 // End with the answer in the z flag. |
| 1679 } | 1638 } |
| 1680 | 1639 |
| 1681 | 1640 |
| 1682 void LCodeGen::DoClassOfTest(LClassOfTest* instr) { | 1641 void LCodeGen::DoClassOfTest(LClassOfTest* instr) { |
| 1683 Register input = ToRegister(instr->input()); | 1642 Register input = ToRegister(instr->InputAt(0)); |
| 1684 Register result = ToRegister(instr->result()); | 1643 Register result = ToRegister(instr->result()); |
| 1685 ASSERT(input.is(result)); | 1644 ASSERT(input.is(result)); |
| 1686 Register temp = ToRegister(instr->temporary()); | 1645 Register temp = ToRegister(instr->TempAt(0)); |
| 1687 Handle<String> class_name = instr->hydrogen()->class_name(); | 1646 Handle<String> class_name = instr->hydrogen()->class_name(); |
| 1688 NearLabel done; | 1647 NearLabel done; |
| 1689 Label is_true, is_false; | 1648 Label is_true, is_false; |
| 1690 | 1649 |
| 1691 EmitClassOfTest(&is_true, &is_false, class_name, input, temp, input); | 1650 EmitClassOfTest(&is_true, &is_false, class_name, input, temp, input); |
| 1692 | 1651 |
| 1693 __ j(not_equal, &is_false); | 1652 __ j(not_equal, &is_false); |
| 1694 | 1653 |
| 1695 __ bind(&is_true); | 1654 __ bind(&is_true); |
| 1696 __ mov(result, Handle<Object>(HEAP->true_value())); | 1655 __ mov(result, FACTORY->true_value()); |
| 1697 __ jmp(&done); | 1656 __ jmp(&done); |
| 1698 | 1657 |
| 1699 __ bind(&is_false); | 1658 __ bind(&is_false); |
| 1700 __ mov(result, Handle<Object>(HEAP->false_value())); | 1659 __ mov(result, FACTORY->false_value()); |
| 1701 __ bind(&done); | 1660 __ bind(&done); |
| 1702 } | 1661 } |
| 1703 | 1662 |
| 1704 | 1663 |
| 1705 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { | 1664 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { |
| 1706 Register input = ToRegister(instr->input()); | 1665 Register input = ToRegister(instr->InputAt(0)); |
| 1707 Register temp = ToRegister(instr->temporary()); | 1666 Register temp = ToRegister(instr->TempAt(0)); |
| 1708 Register temp2 = ToRegister(instr->temporary2()); | 1667 Register temp2 = ToRegister(instr->TempAt(1)); |
| 1709 if (input.is(temp)) { | 1668 if (input.is(temp)) { |
| 1710 // Swap. | 1669 // Swap. |
| 1711 Register swapper = temp; | 1670 Register swapper = temp; |
| 1712 temp = temp2; | 1671 temp = temp2; |
| 1713 temp2 = swapper; | 1672 temp2 = swapper; |
| 1714 } | 1673 } |
| 1715 Handle<String> class_name = instr->hydrogen()->class_name(); | 1674 Handle<String> class_name = instr->hydrogen()->class_name(); |
| 1716 | 1675 |
| 1717 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1676 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 1718 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1677 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 1719 | 1678 |
| 1720 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 1679 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
| 1721 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1680 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
| 1722 | 1681 |
| 1723 EmitClassOfTest(true_label, false_label, class_name, input, temp, temp2); | 1682 EmitClassOfTest(true_label, false_label, class_name, input, temp, temp2); |
| 1724 | 1683 |
| 1725 EmitBranch(true_block, false_block, equal); | 1684 EmitBranch(true_block, false_block, equal); |
| 1726 } | 1685 } |
| 1727 | 1686 |
| 1728 | 1687 |
| 1729 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { | 1688 void LCodeGen::DoCmpMapAndBranch(LCmpMapAndBranch* instr) { |
| 1730 Register reg = ToRegister(instr->input()); | 1689 Register reg = ToRegister(instr->InputAt(0)); |
| 1731 int true_block = instr->true_block_id(); | 1690 int true_block = instr->true_block_id(); |
| 1732 int false_block = instr->false_block_id(); | 1691 int false_block = instr->false_block_id(); |
| 1733 | 1692 |
| 1734 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), instr->map()); | 1693 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), instr->map()); |
| 1735 EmitBranch(true_block, false_block, equal); | 1694 EmitBranch(true_block, false_block, equal); |
| 1736 } | 1695 } |
| 1737 | 1696 |
| 1738 | 1697 |
| 1739 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { | 1698 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { |
| 1740 // Object and function are in fixed registers defined by the stub. | 1699 // Object and function are in fixed registers defined by the stub. |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1777 | 1736 |
| 1778 private: | 1737 private: |
| 1779 LInstanceOfKnownGlobal* instr_; | 1738 LInstanceOfKnownGlobal* instr_; |
| 1780 Label map_check_; | 1739 Label map_check_; |
| 1781 }; | 1740 }; |
| 1782 | 1741 |
| 1783 DeferredInstanceOfKnownGlobal* deferred; | 1742 DeferredInstanceOfKnownGlobal* deferred; |
| 1784 deferred = new DeferredInstanceOfKnownGlobal(this, instr); | 1743 deferred = new DeferredInstanceOfKnownGlobal(this, instr); |
| 1785 | 1744 |
| 1786 Label done, false_result; | 1745 Label done, false_result; |
| 1787 Register object = ToRegister(instr->input()); | 1746 Register object = ToRegister(instr->InputAt(0)); |
| 1788 Register temp = ToRegister(instr->temp()); | 1747 Register temp = ToRegister(instr->TempAt(0)); |
| 1789 | 1748 |
| 1790 // A Smi is not instance of anything. | 1749 // A Smi is not instance of anything. |
| 1791 __ test(object, Immediate(kSmiTagMask)); | 1750 __ test(object, Immediate(kSmiTagMask)); |
| 1792 __ j(zero, &false_result, not_taken); | 1751 __ j(zero, &false_result, not_taken); |
| 1793 | 1752 |
| 1794 // This is the inlined call site instanceof cache. The two occourences of the | 1753 // This is the inlined call site instanceof cache. The two occourences of the |
| 1795 // hole value will be patched to the last map/result pair generated by the | 1754 // hole value will be patched to the last map/result pair generated by the |
| 1796 // instanceof stub. | 1755 // instanceof stub. |
| 1797 NearLabel cache_miss; | 1756 NearLabel cache_miss; |
| 1798 Register map = ToRegister(instr->temp()); | 1757 Register map = ToRegister(instr->TempAt(0)); |
| 1799 __ mov(map, FieldOperand(object, HeapObject::kMapOffset)); | 1758 __ mov(map, FieldOperand(object, HeapObject::kMapOffset)); |
| 1800 __ bind(deferred->map_check()); // Label for calculating code patching. | 1759 __ bind(deferred->map_check()); // Label for calculating code patching. |
| 1801 __ cmp(map, FACTORY->the_hole_value()); // Patched to cached map. | 1760 __ cmp(map, FACTORY->the_hole_value()); // Patched to cached map. |
| 1802 __ j(not_equal, &cache_miss, not_taken); | 1761 __ j(not_equal, &cache_miss, not_taken); |
| 1803 __ mov(eax, FACTORY->the_hole_value()); // Patched to either true or false. | 1762 __ mov(eax, FACTORY->the_hole_value()); // Patched to either true or false. |
| 1804 __ jmp(&done); | 1763 __ jmp(&done); |
| 1805 | 1764 |
| 1806 // The inlined call site cache did not match. Check null and string before | 1765 // The inlined call site cache did not match. Check null and string before |
| 1807 // calling the deferred code. | 1766 // calling the deferred code. |
| 1808 __ bind(&cache_miss); | 1767 __ bind(&cache_miss); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1836 flags | InstanceofStub::kArgsInRegisters); | 1795 flags | InstanceofStub::kArgsInRegisters); |
| 1837 flags = static_cast<InstanceofStub::Flags>( | 1796 flags = static_cast<InstanceofStub::Flags>( |
| 1838 flags | InstanceofStub::kCallSiteInlineCheck); | 1797 flags | InstanceofStub::kCallSiteInlineCheck); |
| 1839 flags = static_cast<InstanceofStub::Flags>( | 1798 flags = static_cast<InstanceofStub::Flags>( |
| 1840 flags | InstanceofStub::kReturnTrueFalseObject); | 1799 flags | InstanceofStub::kReturnTrueFalseObject); |
| 1841 InstanceofStub stub(flags); | 1800 InstanceofStub stub(flags); |
| 1842 | 1801 |
| 1843 // Get the temp register reserved by the instruction. This needs to be edi as | 1802 // Get the temp register reserved by the instruction. This needs to be edi as |
| 1844 // its slot of the pushing of safepoint registers is used to communicate the | 1803 // its slot of the pushing of safepoint registers is used to communicate the |
| 1845 // offset to the location of the map check. | 1804 // offset to the location of the map check. |
| 1846 Register temp = ToRegister(instr->temp()); | 1805 Register temp = ToRegister(instr->TempAt(0)); |
| 1847 ASSERT(temp.is(edi)); | 1806 ASSERT(temp.is(edi)); |
| 1848 __ mov(InstanceofStub::right(), Immediate(instr->function())); | 1807 __ mov(InstanceofStub::right(), Immediate(instr->function())); |
| 1849 static const int kAdditionalDelta = 13; | 1808 static const int kAdditionalDelta = 13; |
| 1850 int delta = masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta; | 1809 int delta = masm_->SizeOfCodeGeneratedSince(map_check) + kAdditionalDelta; |
| 1851 Label before_push_delta; | 1810 Label before_push_delta; |
| 1852 __ bind(&before_push_delta); | 1811 __ bind(&before_push_delta); |
| 1853 __ mov(temp, Immediate(delta)); | 1812 __ mov(temp, Immediate(delta)); |
| 1854 __ mov(Operand(esp, EspIndexForPushAll(temp) * kPointerSize), temp); | 1813 __ mov(Operand(esp, EspIndexForPushAll(temp) * kPointerSize), temp); |
| 1855 __ call(stub.GetCode(), RelocInfo::CODE_TARGET); | 1814 __ call(stub.GetCode(), RelocInfo::CODE_TARGET); |
| 1856 ASSERT_EQ(kAdditionalDelta, | 1815 ASSERT_EQ(kAdditionalDelta, |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1941 Register result = ToRegister(instr->result()); | 1900 Register result = ToRegister(instr->result()); |
| 1942 __ mov(result, Operand::Cell(instr->hydrogen()->cell())); | 1901 __ mov(result, Operand::Cell(instr->hydrogen()->cell())); |
| 1943 if (instr->hydrogen()->check_hole_value()) { | 1902 if (instr->hydrogen()->check_hole_value()) { |
| 1944 __ cmp(result, FACTORY->the_hole_value()); | 1903 __ cmp(result, FACTORY->the_hole_value()); |
| 1945 DeoptimizeIf(equal, instr->environment()); | 1904 DeoptimizeIf(equal, instr->environment()); |
| 1946 } | 1905 } |
| 1947 } | 1906 } |
| 1948 | 1907 |
| 1949 | 1908 |
| 1950 void LCodeGen::DoStoreGlobal(LStoreGlobal* instr) { | 1909 void LCodeGen::DoStoreGlobal(LStoreGlobal* instr) { |
| 1951 Register value = ToRegister(instr->input()); | 1910 Register value = ToRegister(instr->InputAt(0)); |
| 1952 __ mov(Operand::Cell(instr->hydrogen()->cell()), value); | 1911 __ mov(Operand::Cell(instr->hydrogen()->cell()), value); |
| 1953 } | 1912 } |
| 1954 | 1913 |
| 1955 | 1914 |
| 1915 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { |
| 1916 // TODO(antonm): load a context with a separate instruction. |
| 1917 Register result = ToRegister(instr->result()); |
| 1918 __ LoadContext(result, instr->context_chain_length()); |
| 1919 __ mov(result, ContextOperand(result, instr->slot_index())); |
| 1920 } |
| 1921 |
| 1922 |
| 1956 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { | 1923 void LCodeGen::DoLoadNamedField(LLoadNamedField* instr) { |
| 1957 Register object = ToRegister(instr->input()); | 1924 Register object = ToRegister(instr->InputAt(0)); |
| 1958 Register result = ToRegister(instr->result()); | 1925 Register result = ToRegister(instr->result()); |
| 1959 if (instr->hydrogen()->is_in_object()) { | 1926 if (instr->hydrogen()->is_in_object()) { |
| 1960 __ mov(result, FieldOperand(object, instr->hydrogen()->offset())); | 1927 __ mov(result, FieldOperand(object, instr->hydrogen()->offset())); |
| 1961 } else { | 1928 } else { |
| 1962 __ mov(result, FieldOperand(object, JSObject::kPropertiesOffset)); | 1929 __ mov(result, FieldOperand(object, JSObject::kPropertiesOffset)); |
| 1963 __ mov(result, FieldOperand(result, instr->hydrogen()->offset())); | 1930 __ mov(result, FieldOperand(result, instr->hydrogen()->offset())); |
| 1964 } | 1931 } |
| 1965 } | 1932 } |
| 1966 | 1933 |
| 1967 | 1934 |
| 1968 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { | 1935 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { |
| 1969 ASSERT(ToRegister(instr->object()).is(eax)); | 1936 ASSERT(ToRegister(instr->object()).is(eax)); |
| 1970 ASSERT(ToRegister(instr->result()).is(eax)); | 1937 ASSERT(ToRegister(instr->result()).is(eax)); |
| 1971 | 1938 |
| 1972 __ mov(ecx, instr->name()); | 1939 __ mov(ecx, instr->name()); |
| 1973 Handle<Code> ic(Isolate::Current()->builtins()->builtin( | 1940 Handle<Code> ic(Isolate::Current()->builtins()->builtin( |
| 1974 Builtins::LoadIC_Initialize)); | 1941 Builtins::LoadIC_Initialize)); |
| 1975 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 1942 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 1976 } | 1943 } |
| 1977 | 1944 |
| 1978 | 1945 |
| 1979 void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { | 1946 void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { |
| 1980 Register function = ToRegister(instr->function()); | 1947 Register function = ToRegister(instr->function()); |
| 1981 Register temp = ToRegister(instr->temporary()); | 1948 Register temp = ToRegister(instr->TempAt(0)); |
| 1982 Register result = ToRegister(instr->result()); | 1949 Register result = ToRegister(instr->result()); |
| 1983 | 1950 |
| 1984 // Check that the function really is a function. | 1951 // Check that the function really is a function. |
| 1985 __ CmpObjectType(function, JS_FUNCTION_TYPE, result); | 1952 __ CmpObjectType(function, JS_FUNCTION_TYPE, result); |
| 1986 DeoptimizeIf(not_equal, instr->environment()); | 1953 DeoptimizeIf(not_equal, instr->environment()); |
| 1987 | 1954 |
| 1988 // Check whether the function has an instance prototype. | 1955 // Check whether the function has an instance prototype. |
| 1989 NearLabel non_instance; | 1956 NearLabel non_instance; |
| 1990 __ test_b(FieldOperand(result, Map::kBitFieldOffset), | 1957 __ test_b(FieldOperand(result, Map::kBitFieldOffset), |
| 1991 1 << Map::kHasNonInstancePrototype); | 1958 1 << Map::kHasNonInstancePrototype); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 2012 // in the function's map. | 1979 // in the function's map. |
| 2013 __ bind(&non_instance); | 1980 __ bind(&non_instance); |
| 2014 __ mov(result, FieldOperand(result, Map::kConstructorOffset)); | 1981 __ mov(result, FieldOperand(result, Map::kConstructorOffset)); |
| 2015 | 1982 |
| 2016 // All done. | 1983 // All done. |
| 2017 __ bind(&done); | 1984 __ bind(&done); |
| 2018 } | 1985 } |
| 2019 | 1986 |
| 2020 | 1987 |
| 2021 void LCodeGen::DoLoadElements(LLoadElements* instr) { | 1988 void LCodeGen::DoLoadElements(LLoadElements* instr) { |
| 2022 ASSERT(instr->result()->Equals(instr->input())); | 1989 ASSERT(instr->result()->Equals(instr->InputAt(0))); |
| 2023 Register reg = ToRegister(instr->input()); | 1990 Register reg = ToRegister(instr->InputAt(0)); |
| 2024 __ mov(reg, FieldOperand(reg, JSObject::kElementsOffset)); | 1991 __ mov(reg, FieldOperand(reg, JSObject::kElementsOffset)); |
| 2025 if (FLAG_debug_code) { | 1992 if (FLAG_debug_code) { |
| 2026 NearLabel done; | 1993 NearLabel done; |
| 2027 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), | 1994 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), |
| 2028 Immediate(FACTORY->fixed_array_map())); | 1995 Immediate(FACTORY->fixed_array_map())); |
| 2029 __ j(equal, &done); | 1996 __ j(equal, &done); |
| 2030 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), | 1997 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), |
| 2031 Immediate(FACTORY->fixed_cow_array_map())); | 1998 Immediate(FACTORY->fixed_cow_array_map())); |
| 2032 __ Check(equal, "Check for fast elements failed."); | 1999 __ Check(equal, "Check for fast elements failed."); |
| 2033 __ bind(&done); | 2000 __ bind(&done); |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2094 __ bind(&adapted); | 2061 __ bind(&adapted); |
| 2095 __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); | 2062 __ mov(result, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); |
| 2096 | 2063 |
| 2097 // Result is the frame pointer for the frame if not adapted and for the real | 2064 // Result is the frame pointer for the frame if not adapted and for the real |
| 2098 // frame below the adaptor frame if adapted. | 2065 // frame below the adaptor frame if adapted. |
| 2099 __ bind(&done); | 2066 __ bind(&done); |
| 2100 } | 2067 } |
| 2101 | 2068 |
| 2102 | 2069 |
| 2103 void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) { | 2070 void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) { |
| 2104 Operand elem = ToOperand(instr->input()); | 2071 Operand elem = ToOperand(instr->InputAt(0)); |
| 2105 Register result = ToRegister(instr->result()); | 2072 Register result = ToRegister(instr->result()); |
| 2106 | 2073 |
| 2107 NearLabel done; | 2074 NearLabel done; |
| 2108 | 2075 |
| 2109 // If no arguments adaptor frame the number of arguments is fixed. | 2076 // If no arguments adaptor frame the number of arguments is fixed. |
| 2110 __ cmp(ebp, elem); | 2077 __ cmp(ebp, elem); |
| 2111 __ mov(result, Immediate(scope()->num_parameters())); | 2078 __ mov(result, Immediate(scope()->num_parameters())); |
| 2112 __ j(equal, &done); | 2079 __ j(equal, &done); |
| 2113 | 2080 |
| 2114 // Arguments adaptor frame present. Get argument length from there. | 2081 // Arguments adaptor frame present. Get argument length from there. |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2168 ASSERT(receiver.is(eax)); | 2135 ASSERT(receiver.is(eax)); |
| 2169 v8::internal::ParameterCount actual(eax); | 2136 v8::internal::ParameterCount actual(eax); |
| 2170 SafepointGenerator safepoint_generator(this, | 2137 SafepointGenerator safepoint_generator(this, |
| 2171 instr->pointer_map(), | 2138 instr->pointer_map(), |
| 2172 Safepoint::kNoDeoptimizationIndex); | 2139 Safepoint::kNoDeoptimizationIndex); |
| 2173 __ InvokeFunction(edi, actual, CALL_FUNCTION, &safepoint_generator); | 2140 __ InvokeFunction(edi, actual, CALL_FUNCTION, &safepoint_generator); |
| 2174 } | 2141 } |
| 2175 | 2142 |
| 2176 | 2143 |
| 2177 void LCodeGen::DoPushArgument(LPushArgument* instr) { | 2144 void LCodeGen::DoPushArgument(LPushArgument* instr) { |
| 2178 LOperand* argument = instr->input(); | 2145 LOperand* argument = instr->InputAt(0); |
| 2179 if (argument->IsConstantOperand()) { | 2146 if (argument->IsConstantOperand()) { |
| 2180 __ push(ToImmediate(argument)); | 2147 __ push(ToImmediate(argument)); |
| 2181 } else { | 2148 } else { |
| 2182 __ push(ToOperand(argument)); | 2149 __ push(ToOperand(argument)); |
| 2183 } | 2150 } |
| 2184 } | 2151 } |
| 2185 | 2152 |
| 2186 | 2153 |
| 2187 void LCodeGen::DoGlobalObject(LGlobalObject* instr) { | 2154 void LCodeGen::DoGlobalObject(LGlobalObject* instr) { |
| 2188 Register result = ToRegister(instr->result()); | 2155 Register result = ToRegister(instr->result()); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2234 | 2201 |
| 2235 | 2202 |
| 2236 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { | 2203 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { |
| 2237 ASSERT(ToRegister(instr->result()).is(eax)); | 2204 ASSERT(ToRegister(instr->result()).is(eax)); |
| 2238 __ mov(edi, instr->function()); | 2205 __ mov(edi, instr->function()); |
| 2239 CallKnownFunction(instr->function(), instr->arity(), instr); | 2206 CallKnownFunction(instr->function(), instr->arity(), instr); |
| 2240 } | 2207 } |
| 2241 | 2208 |
| 2242 | 2209 |
| 2243 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) { | 2210 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LUnaryMathOperation* instr) { |
| 2244 Register input_reg = ToRegister(instr->input()); | 2211 Register input_reg = ToRegister(instr->InputAt(0)); |
| 2245 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), | 2212 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), |
| 2246 FACTORY->heap_number_map()); | 2213 FACTORY->heap_number_map()); |
| 2247 DeoptimizeIf(not_equal, instr->environment()); | 2214 DeoptimizeIf(not_equal, instr->environment()); |
| 2248 | 2215 |
| 2249 Label done; | 2216 Label done; |
| 2250 Register tmp = input_reg.is(eax) ? ecx : eax; | 2217 Register tmp = input_reg.is(eax) ? ecx : eax; |
| 2251 Register tmp2 = tmp.is(ecx) ? edx : input_reg.is(ecx) ? edx : ecx; | 2218 Register tmp2 = tmp.is(ecx) ? edx : input_reg.is(ecx) ? edx : ecx; |
| 2252 | 2219 |
| 2253 // Preserve the value of all registers. | 2220 // Preserve the value of all registers. |
| 2254 __ PushSafepointRegisters(); | 2221 __ PushSafepointRegisters(); |
| 2255 | 2222 |
| 2256 Label negative; | 2223 Label negative; |
| 2257 __ mov(tmp, FieldOperand(input_reg, HeapNumber::kExponentOffset)); | 2224 __ mov(tmp, FieldOperand(input_reg, HeapNumber::kExponentOffset)); |
| 2258 // Check the sign of the argument. If the argument is positive, | 2225 // Check the sign of the argument. If the argument is positive, just |
| 2259 // just return it. | 2226 // return it. We do not need to patch the stack since |input| and |
| 2227 // |result| are the same register and |input| will be restored |
| 2228 // unchanged by popping safepoint registers. |
| 2260 __ test(tmp, Immediate(HeapNumber::kSignMask)); | 2229 __ test(tmp, Immediate(HeapNumber::kSignMask)); |
| 2261 __ j(not_zero, &negative); | 2230 __ j(not_zero, &negative); |
| 2262 __ mov(tmp, input_reg); | |
| 2263 __ jmp(&done); | 2231 __ jmp(&done); |
| 2264 | 2232 |
| 2265 __ bind(&negative); | 2233 __ bind(&negative); |
| 2266 | 2234 |
| 2267 Label allocated, slow; | 2235 Label allocated, slow; |
| 2268 __ AllocateHeapNumber(tmp, tmp2, no_reg, &slow); | 2236 __ AllocateHeapNumber(tmp, tmp2, no_reg, &slow); |
| 2269 __ jmp(&allocated); | 2237 __ jmp(&allocated); |
| 2270 | 2238 |
| 2271 // Slow case: Call the runtime system to do the number allocation. | 2239 // Slow case: Call the runtime system to do the number allocation. |
| 2272 __ bind(&slow); | 2240 __ bind(&slow); |
| 2273 | 2241 |
| 2274 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); | 2242 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); |
| 2275 RecordSafepointWithRegisters( | 2243 RecordSafepointWithRegisters( |
| 2276 instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex); | 2244 instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex); |
| 2277 // Set the pointer to the new heap number in tmp. | 2245 // Set the pointer to the new heap number in tmp. |
| 2278 if (!tmp.is(eax)) __ mov(tmp, eax); | 2246 if (!tmp.is(eax)) __ mov(tmp, eax); |
| 2279 | 2247 |
| 2280 // Restore input_reg after call to runtime. | 2248 // Restore input_reg after call to runtime. |
| 2281 __ mov(input_reg, Operand(esp, EspIndexForPushAll(input_reg) * kPointerSize)); | 2249 __ mov(input_reg, Operand(esp, EspIndexForPushAll(input_reg) * kPointerSize)); |
| 2282 | 2250 |
| 2283 __ bind(&allocated); | 2251 __ bind(&allocated); |
| 2284 __ mov(tmp2, FieldOperand(input_reg, HeapNumber::kExponentOffset)); | 2252 __ mov(tmp2, FieldOperand(input_reg, HeapNumber::kExponentOffset)); |
| 2285 __ and_(tmp2, ~HeapNumber::kSignMask); | 2253 __ and_(tmp2, ~HeapNumber::kSignMask); |
| 2286 __ mov(FieldOperand(tmp, HeapNumber::kExponentOffset), tmp2); | 2254 __ mov(FieldOperand(tmp, HeapNumber::kExponentOffset), tmp2); |
| 2287 __ mov(tmp2, FieldOperand(input_reg, HeapNumber::kMantissaOffset)); | 2255 __ mov(tmp2, FieldOperand(input_reg, HeapNumber::kMantissaOffset)); |
| 2288 __ mov(FieldOperand(tmp, HeapNumber::kMantissaOffset), tmp2); | 2256 __ mov(FieldOperand(tmp, HeapNumber::kMantissaOffset), tmp2); |
| 2257 __ mov(Operand(esp, EspIndexForPushAll(input_reg) * kPointerSize), tmp); |
| 2289 | 2258 |
| 2290 __ bind(&done); | 2259 __ bind(&done); |
| 2291 __ mov(Operand(esp, EspIndexForPushAll(input_reg) * kPointerSize), tmp); | 2260 __ PopSafepointRegisters(); |
| 2261 } |
| 2292 | 2262 |
| 2293 __ PopSafepointRegisters(); | 2263 |
| 2264 void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) { |
| 2265 Register input_reg = ToRegister(instr->InputAt(0)); |
| 2266 __ test(input_reg, Operand(input_reg)); |
| 2267 Label is_positive; |
| 2268 __ j(not_sign, &is_positive); |
| 2269 __ neg(input_reg); |
| 2270 __ test(input_reg, Operand(input_reg)); |
| 2271 DeoptimizeIf(negative, instr->environment()); |
| 2272 __ bind(&is_positive); |
| 2294 } | 2273 } |
| 2295 | 2274 |
| 2296 | 2275 |
| 2297 void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) { | 2276 void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) { |
| 2298 // Class for deferred case. | 2277 // Class for deferred case. |
| 2299 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode { | 2278 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode { |
| 2300 public: | 2279 public: |
| 2301 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, | 2280 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, |
| 2302 LUnaryMathOperation* instr) | 2281 LUnaryMathOperation* instr) |
| 2303 : LDeferredCode(codegen), instr_(instr) { } | 2282 : LDeferredCode(codegen), instr_(instr) { } |
| 2304 virtual void Generate() { | 2283 virtual void Generate() { |
| 2305 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); | 2284 codegen()->DoDeferredMathAbsTaggedHeapNumber(instr_); |
| 2306 } | 2285 } |
| 2307 private: | 2286 private: |
| 2308 LUnaryMathOperation* instr_; | 2287 LUnaryMathOperation* instr_; |
| 2309 }; | 2288 }; |
| 2310 | 2289 |
| 2311 ASSERT(instr->input()->Equals(instr->result())); | 2290 ASSERT(instr->InputAt(0)->Equals(instr->result())); |
| 2312 Representation r = instr->hydrogen()->value()->representation(); | 2291 Representation r = instr->hydrogen()->value()->representation(); |
| 2313 | 2292 |
| 2314 if (r.IsDouble()) { | 2293 if (r.IsDouble()) { |
| 2315 XMMRegister scratch = xmm0; | 2294 XMMRegister scratch = xmm0; |
| 2316 XMMRegister input_reg = ToDoubleRegister(instr->input()); | 2295 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); |
| 2317 __ pxor(scratch, scratch); | 2296 __ pxor(scratch, scratch); |
| 2318 __ subsd(scratch, input_reg); | 2297 __ subsd(scratch, input_reg); |
| 2319 __ pand(input_reg, scratch); | 2298 __ pand(input_reg, scratch); |
| 2320 } else if (r.IsInteger32()) { | 2299 } else if (r.IsInteger32()) { |
| 2321 Register input_reg = ToRegister(instr->input()); | 2300 EmitIntegerMathAbs(instr); |
| 2322 __ test(input_reg, Operand(input_reg)); | |
| 2323 Label is_positive; | |
| 2324 __ j(not_sign, &is_positive); | |
| 2325 __ neg(input_reg); | |
| 2326 __ test(input_reg, Operand(input_reg)); | |
| 2327 DeoptimizeIf(negative, instr->environment()); | |
| 2328 __ bind(&is_positive); | |
| 2329 } else { // Tagged case. | 2301 } else { // Tagged case. |
| 2330 DeferredMathAbsTaggedHeapNumber* deferred = | 2302 DeferredMathAbsTaggedHeapNumber* deferred = |
| 2331 new DeferredMathAbsTaggedHeapNumber(this, instr); | 2303 new DeferredMathAbsTaggedHeapNumber(this, instr); |
| 2332 Label not_smi; | 2304 Register input_reg = ToRegister(instr->InputAt(0)); |
| 2333 Register input_reg = ToRegister(instr->input()); | |
| 2334 // Smi check. | 2305 // Smi check. |
| 2335 __ test(input_reg, Immediate(kSmiTagMask)); | 2306 __ test(input_reg, Immediate(kSmiTagMask)); |
| 2336 __ j(not_zero, deferred->entry()); | 2307 __ j(not_zero, deferred->entry()); |
| 2337 __ test(input_reg, Operand(input_reg)); | 2308 EmitIntegerMathAbs(instr); |
| 2338 Label is_positive; | |
| 2339 __ j(not_sign, &is_positive); | |
| 2340 __ neg(input_reg); | |
| 2341 | |
| 2342 __ test(input_reg, Operand(input_reg)); | |
| 2343 DeoptimizeIf(negative, instr->environment()); | |
| 2344 | |
| 2345 __ bind(&is_positive); | |
| 2346 __ bind(deferred->exit()); | 2309 __ bind(deferred->exit()); |
| 2347 } | 2310 } |
| 2348 } | 2311 } |
| 2349 | 2312 |
| 2350 | 2313 |
| 2351 void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) { | 2314 void LCodeGen::DoMathFloor(LUnaryMathOperation* instr) { |
| 2352 XMMRegister xmm_scratch = xmm0; | 2315 XMMRegister xmm_scratch = xmm0; |
| 2353 Register output_reg = ToRegister(instr->result()); | 2316 Register output_reg = ToRegister(instr->result()); |
| 2354 XMMRegister input_reg = ToDoubleRegister(instr->input()); | 2317 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); |
| 2355 __ xorpd(xmm_scratch, xmm_scratch); // Zero the register. | 2318 __ xorpd(xmm_scratch, xmm_scratch); // Zero the register. |
| 2356 __ ucomisd(input_reg, xmm_scratch); | 2319 __ ucomisd(input_reg, xmm_scratch); |
| 2357 | 2320 |
| 2358 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 2321 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 2359 DeoptimizeIf(below_equal, instr->environment()); | 2322 DeoptimizeIf(below_equal, instr->environment()); |
| 2360 } else { | 2323 } else { |
| 2361 DeoptimizeIf(below, instr->environment()); | 2324 DeoptimizeIf(below, instr->environment()); |
| 2362 } | 2325 } |
| 2363 | 2326 |
| 2364 // Use truncating instruction (OK because input is positive). | 2327 // Use truncating instruction (OK because input is positive). |
| 2365 __ cvttsd2si(output_reg, Operand(input_reg)); | 2328 __ cvttsd2si(output_reg, Operand(input_reg)); |
| 2366 | 2329 |
| 2367 // Overflow is signalled with minint. | 2330 // Overflow is signalled with minint. |
| 2368 __ cmp(output_reg, 0x80000000u); | 2331 __ cmp(output_reg, 0x80000000u); |
| 2369 DeoptimizeIf(equal, instr->environment()); | 2332 DeoptimizeIf(equal, instr->environment()); |
| 2370 } | 2333 } |
| 2371 | 2334 |
| 2372 | 2335 |
| 2373 void LCodeGen::DoMathRound(LUnaryMathOperation* instr) { | 2336 void LCodeGen::DoMathRound(LUnaryMathOperation* instr) { |
| 2374 XMMRegister xmm_scratch = xmm0; | 2337 XMMRegister xmm_scratch = xmm0; |
| 2375 Register output_reg = ToRegister(instr->result()); | 2338 Register output_reg = ToRegister(instr->result()); |
| 2376 XMMRegister input_reg = ToDoubleRegister(instr->input()); | 2339 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); |
| 2377 | 2340 |
| 2378 // xmm_scratch = 0.5 | 2341 // xmm_scratch = 0.5 |
| 2379 ExternalReference one_half = ExternalReference::address_of_one_half(); | 2342 ExternalReference one_half = ExternalReference::address_of_one_half(); |
| 2380 __ movdbl(xmm_scratch, Operand::StaticVariable(one_half)); | 2343 __ movdbl(xmm_scratch, Operand::StaticVariable(one_half)); |
| 2381 | 2344 |
| 2382 // input = input + 0.5 | 2345 // input = input + 0.5 |
| 2383 __ addsd(input_reg, xmm_scratch); | 2346 __ addsd(input_reg, xmm_scratch); |
| 2384 | 2347 |
| 2385 // We need to return -0 for the input range [-0.5, 0[, otherwise | 2348 // We need to return -0 for the input range [-0.5, 0[, otherwise |
| 2386 // compute Math.floor(value + 0.5). | 2349 // compute Math.floor(value + 0.5). |
| (...skipping 12 matching lines...) Expand all Loading... |
| 2399 // Use truncating instruction (OK because input is positive). | 2362 // Use truncating instruction (OK because input is positive). |
| 2400 __ cvttsd2si(output_reg, Operand(input_reg)); | 2363 __ cvttsd2si(output_reg, Operand(input_reg)); |
| 2401 | 2364 |
| 2402 // Overflow is signalled with minint. | 2365 // Overflow is signalled with minint. |
| 2403 __ cmp(output_reg, 0x80000000u); | 2366 __ cmp(output_reg, 0x80000000u); |
| 2404 DeoptimizeIf(equal, instr->environment()); | 2367 DeoptimizeIf(equal, instr->environment()); |
| 2405 } | 2368 } |
| 2406 | 2369 |
| 2407 | 2370 |
| 2408 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) { | 2371 void LCodeGen::DoMathSqrt(LUnaryMathOperation* instr) { |
| 2409 XMMRegister input_reg = ToDoubleRegister(instr->input()); | 2372 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); |
| 2410 ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); | 2373 ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); |
| 2411 __ sqrtsd(input_reg, input_reg); | 2374 __ sqrtsd(input_reg, input_reg); |
| 2412 } | 2375 } |
| 2413 | 2376 |
| 2414 | 2377 |
| 2415 void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) { | 2378 void LCodeGen::DoMathPowHalf(LUnaryMathOperation* instr) { |
| 2416 XMMRegister xmm_scratch = xmm0; | 2379 XMMRegister xmm_scratch = xmm0; |
| 2417 XMMRegister input_reg = ToDoubleRegister(instr->input()); | 2380 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); |
| 2418 ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); | 2381 ASSERT(ToDoubleRegister(instr->result()).is(input_reg)); |
| 2419 ExternalReference negative_infinity = | 2382 ExternalReference negative_infinity = |
| 2420 ExternalReference::address_of_negative_infinity(); | 2383 ExternalReference::address_of_negative_infinity(); |
| 2421 __ movdbl(xmm_scratch, Operand::StaticVariable(negative_infinity)); | 2384 __ movdbl(xmm_scratch, Operand::StaticVariable(negative_infinity)); |
| 2422 __ ucomisd(xmm_scratch, input_reg); | 2385 __ ucomisd(xmm_scratch, input_reg); |
| 2423 DeoptimizeIf(equal, instr->environment()); | 2386 DeoptimizeIf(equal, instr->environment()); |
| 2424 __ sqrtsd(input_reg, input_reg); | 2387 __ sqrtsd(input_reg, input_reg); |
| 2425 } | 2388 } |
| 2426 | 2389 |
| 2427 | 2390 |
| 2428 void LCodeGen::DoPower(LPower* instr) { | 2391 void LCodeGen::DoPower(LPower* instr) { |
| 2429 LOperand* left = instr->left(); | 2392 LOperand* left = instr->InputAt(0); |
| 2430 LOperand* right = instr->right(); | 2393 LOperand* right = instr->InputAt(1); |
| 2431 DoubleRegister result_reg = ToDoubleRegister(instr->result()); | 2394 DoubleRegister result_reg = ToDoubleRegister(instr->result()); |
| 2432 Representation exponent_type = instr->hydrogen()->right()->representation(); | 2395 Representation exponent_type = instr->hydrogen()->right()->representation(); |
| 2433 if (exponent_type.IsDouble()) { | 2396 if (exponent_type.IsDouble()) { |
| 2434 // It is safe to use ebx directly since the instruction is marked | 2397 // It is safe to use ebx directly since the instruction is marked |
| 2435 // as a call. | 2398 // as a call. |
| 2436 __ PrepareCallCFunction(4, ebx); | 2399 __ PrepareCallCFunction(4, ebx); |
| 2437 __ movdbl(Operand(esp, 0 * kDoubleSize), ToDoubleRegister(left)); | 2400 __ movdbl(Operand(esp, 0 * kDoubleSize), ToDoubleRegister(left)); |
| 2438 __ movdbl(Operand(esp, 1 * kDoubleSize), ToDoubleRegister(right)); | 2401 __ movdbl(Operand(esp, 1 * kDoubleSize), ToDoubleRegister(right)); |
| 2439 __ CallCFunction(ExternalReference::power_double_double_function(), 4); | 2402 __ CallCFunction(ExternalReference::power_double_double_function(), 4); |
| 2440 } else if (exponent_type.IsInteger32()) { | 2403 } else if (exponent_type.IsInteger32()) { |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2533 break; | 2496 break; |
| 2534 | 2497 |
| 2535 default: | 2498 default: |
| 2536 UNREACHABLE(); | 2499 UNREACHABLE(); |
| 2537 } | 2500 } |
| 2538 } | 2501 } |
| 2539 | 2502 |
| 2540 | 2503 |
| 2541 void LCodeGen::DoCallKeyed(LCallKeyed* instr) { | 2504 void LCodeGen::DoCallKeyed(LCallKeyed* instr) { |
| 2542 ASSERT(ToRegister(instr->result()).is(eax)); | 2505 ASSERT(ToRegister(instr->result()).is(eax)); |
| 2506 ASSERT(ToRegister(instr->InputAt(0)).is(ecx)); |
| 2543 | 2507 |
| 2544 int arity = instr->arity(); | 2508 int arity = instr->arity(); |
| 2545 Handle<Code> ic = Isolate::Current()->stub_cache()-> | 2509 Handle<Code> ic = Isolate::Current()->stub_cache()-> |
| 2546 ComputeKeyedCallInitialize(arity, NOT_IN_LOOP); | 2510 ComputeKeyedCallInitialize(arity, NOT_IN_LOOP); |
| 2547 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 2511 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 2548 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); | 2512 __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); |
| 2549 } | 2513 } |
| 2550 | 2514 |
| 2551 | 2515 |
| 2552 void LCodeGen::DoCallNamed(LCallNamed* instr) { | 2516 void LCodeGen::DoCallNamed(LCallNamed* instr) { |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2585 | 2549 |
| 2586 | 2550 |
| 2587 void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) { | 2551 void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) { |
| 2588 ASSERT(ToRegister(instr->result()).is(eax)); | 2552 ASSERT(ToRegister(instr->result()).is(eax)); |
| 2589 __ mov(edi, instr->target()); | 2553 __ mov(edi, instr->target()); |
| 2590 CallKnownFunction(instr->target(), instr->arity(), instr); | 2554 CallKnownFunction(instr->target(), instr->arity(), instr); |
| 2591 } | 2555 } |
| 2592 | 2556 |
| 2593 | 2557 |
| 2594 void LCodeGen::DoCallNew(LCallNew* instr) { | 2558 void LCodeGen::DoCallNew(LCallNew* instr) { |
| 2595 ASSERT(ToRegister(instr->input()).is(edi)); | 2559 ASSERT(ToRegister(instr->InputAt(0)).is(edi)); |
| 2596 ASSERT(ToRegister(instr->result()).is(eax)); | 2560 ASSERT(ToRegister(instr->result()).is(eax)); |
| 2597 | 2561 |
| 2598 Handle<Code> builtin(Isolate::Current()->builtins()->builtin( | 2562 Handle<Code> builtin(Isolate::Current()->builtins()->builtin( |
| 2599 Builtins::JSConstructCall)); | 2563 Builtins::JSConstructCall)); |
| 2600 __ Set(eax, Immediate(instr->arity())); | 2564 __ Set(eax, Immediate(instr->arity())); |
| 2601 CallCode(builtin, RelocInfo::CONSTRUCT_CALL, instr); | 2565 CallCode(builtin, RelocInfo::CONSTRUCT_CALL, instr); |
| 2602 } | 2566 } |
| 2603 | 2567 |
| 2604 | 2568 |
| 2605 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { | 2569 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { |
| 2606 CallRuntime(instr->function(), instr->arity(), instr); | 2570 CallRuntime(instr->function(), instr->arity(), instr); |
| 2607 } | 2571 } |
| 2608 | 2572 |
| 2609 | 2573 |
| 2610 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { | 2574 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { |
| 2611 Register object = ToRegister(instr->object()); | 2575 Register object = ToRegister(instr->object()); |
| 2612 Register value = ToRegister(instr->value()); | 2576 Register value = ToRegister(instr->value()); |
| 2613 int offset = instr->offset(); | 2577 int offset = instr->offset(); |
| 2614 | 2578 |
| 2615 if (!instr->transition().is_null()) { | 2579 if (!instr->transition().is_null()) { |
| 2616 __ mov(FieldOperand(object, HeapObject::kMapOffset), instr->transition()); | 2580 __ mov(FieldOperand(object, HeapObject::kMapOffset), instr->transition()); |
| 2617 } | 2581 } |
| 2618 | 2582 |
| 2619 // Do the store. | 2583 // Do the store. |
| 2620 if (instr->is_in_object()) { | 2584 if (instr->is_in_object()) { |
| 2621 __ mov(FieldOperand(object, offset), value); | 2585 __ mov(FieldOperand(object, offset), value); |
| 2622 if (instr->needs_write_barrier()) { | 2586 if (instr->needs_write_barrier()) { |
| 2623 Register temp = ToRegister(instr->temp()); | 2587 Register temp = ToRegister(instr->TempAt(0)); |
| 2624 // Update the write barrier for the object for in-object properties. | 2588 // Update the write barrier for the object for in-object properties. |
| 2625 __ RecordWrite(object, offset, value, temp); | 2589 __ RecordWrite(object, offset, value, temp); |
| 2626 } | 2590 } |
| 2627 } else { | 2591 } else { |
| 2628 Register temp = ToRegister(instr->temp()); | 2592 Register temp = ToRegister(instr->TempAt(0)); |
| 2629 __ mov(temp, FieldOperand(object, JSObject::kPropertiesOffset)); | 2593 __ mov(temp, FieldOperand(object, JSObject::kPropertiesOffset)); |
| 2630 __ mov(FieldOperand(temp, offset), value); | 2594 __ mov(FieldOperand(temp, offset), value); |
| 2631 if (instr->needs_write_barrier()) { | 2595 if (instr->needs_write_barrier()) { |
| 2632 // Update the write barrier for the properties array. | 2596 // Update the write barrier for the properties array. |
| 2633 // object is used as a scratch register. | 2597 // object is used as a scratch register. |
| 2634 __ RecordWrite(temp, offset, value, object); | 2598 __ RecordWrite(temp, offset, value, object); |
| 2635 } | 2599 } |
| 2636 } | 2600 } |
| 2637 } | 2601 } |
| 2638 | 2602 |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2683 ASSERT(ToRegister(instr->object()).is(edx)); | 2647 ASSERT(ToRegister(instr->object()).is(edx)); |
| 2684 ASSERT(ToRegister(instr->key()).is(ecx)); | 2648 ASSERT(ToRegister(instr->key()).is(ecx)); |
| 2685 ASSERT(ToRegister(instr->value()).is(eax)); | 2649 ASSERT(ToRegister(instr->value()).is(eax)); |
| 2686 | 2650 |
| 2687 Handle<Code> ic(Isolate::Current()->builtins()->builtin( | 2651 Handle<Code> ic(Isolate::Current()->builtins()->builtin( |
| 2688 Builtins::KeyedStoreIC_Initialize)); | 2652 Builtins::KeyedStoreIC_Initialize)); |
| 2689 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 2653 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
| 2690 } | 2654 } |
| 2691 | 2655 |
| 2692 | 2656 |
| 2657 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { |
| 2658 class DeferredStringCharCodeAt: public LDeferredCode { |
| 2659 public: |
| 2660 DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr) |
| 2661 : LDeferredCode(codegen), instr_(instr) { } |
| 2662 virtual void Generate() { codegen()->DoDeferredStringCharCodeAt(instr_); } |
| 2663 private: |
| 2664 LStringCharCodeAt* instr_; |
| 2665 }; |
| 2666 |
| 2667 Register string = ToRegister(instr->string()); |
| 2668 Register index = no_reg; |
| 2669 int const_index = -1; |
| 2670 if (instr->index()->IsConstantOperand()) { |
| 2671 const_index = ToInteger32(LConstantOperand::cast(instr->index())); |
| 2672 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue); |
| 2673 if (!Smi::IsValid(const_index)) { |
| 2674 // Guaranteed to be out of bounds because of the assert above. |
| 2675 // So the bounds check that must dominate this instruction must |
| 2676 // have deoptimized already. |
| 2677 if (FLAG_debug_code) { |
| 2678 __ Abort("StringCharCodeAt: out of bounds index."); |
| 2679 } |
| 2680 // No code needs to be generated. |
| 2681 return; |
| 2682 } |
| 2683 } else { |
| 2684 index = ToRegister(instr->index()); |
| 2685 } |
| 2686 Register result = ToRegister(instr->result()); |
| 2687 |
| 2688 DeferredStringCharCodeAt* deferred = |
| 2689 new DeferredStringCharCodeAt(this, instr); |
| 2690 |
| 2691 NearLabel flat_string, ascii_string, done; |
| 2692 |
| 2693 // Fetch the instance type of the receiver into result register. |
| 2694 __ mov(result, FieldOperand(string, HeapObject::kMapOffset)); |
| 2695 __ movzx_b(result, FieldOperand(result, Map::kInstanceTypeOffset)); |
| 2696 |
| 2697 // We need special handling for non-flat strings. |
| 2698 STATIC_ASSERT(kSeqStringTag == 0); |
| 2699 __ test(result, Immediate(kStringRepresentationMask)); |
| 2700 __ j(zero, &flat_string); |
| 2701 |
| 2702 // Handle non-flat strings. |
| 2703 __ test(result, Immediate(kIsConsStringMask)); |
| 2704 __ j(zero, deferred->entry()); |
| 2705 |
| 2706 // ConsString. |
| 2707 // Check whether the right hand side is the empty string (i.e. if |
| 2708 // this is really a flat string in a cons string). If that is not |
| 2709 // the case we would rather go to the runtime system now to flatten |
| 2710 // the string. |
| 2711 __ cmp(FieldOperand(string, ConsString::kSecondOffset), |
| 2712 Immediate(FACTORY->empty_string())); |
| 2713 __ j(not_equal, deferred->entry()); |
| 2714 // Get the first of the two strings and load its instance type. |
| 2715 __ mov(string, FieldOperand(string, ConsString::kFirstOffset)); |
| 2716 __ mov(result, FieldOperand(string, HeapObject::kMapOffset)); |
| 2717 __ movzx_b(result, FieldOperand(result, Map::kInstanceTypeOffset)); |
| 2718 // If the first cons component is also non-flat, then go to runtime. |
| 2719 STATIC_ASSERT(kSeqStringTag == 0); |
| 2720 __ test(result, Immediate(kStringRepresentationMask)); |
| 2721 __ j(not_zero, deferred->entry()); |
| 2722 |
| 2723 // Check for 1-byte or 2-byte string. |
| 2724 __ bind(&flat_string); |
| 2725 STATIC_ASSERT(kAsciiStringTag != 0); |
| 2726 __ test(result, Immediate(kStringEncodingMask)); |
| 2727 __ j(not_zero, &ascii_string); |
| 2728 |
| 2729 // 2-byte string. |
| 2730 // Load the 2-byte character code into the result register. |
| 2731 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize == 1); |
| 2732 if (instr->index()->IsConstantOperand()) { |
| 2733 __ movzx_w(result, |
| 2734 FieldOperand(string, |
| 2735 SeqTwoByteString::kHeaderSize + 2 * const_index)); |
| 2736 } else { |
| 2737 __ movzx_w(result, FieldOperand(string, |
| 2738 index, |
| 2739 times_2, |
| 2740 SeqTwoByteString::kHeaderSize)); |
| 2741 } |
| 2742 __ jmp(&done); |
| 2743 |
| 2744 // ASCII string. |
| 2745 // Load the byte into the result register. |
| 2746 __ bind(&ascii_string); |
| 2747 if (instr->index()->IsConstantOperand()) { |
| 2748 __ movzx_b(result, FieldOperand(string, |
| 2749 SeqAsciiString::kHeaderSize + const_index)); |
| 2750 } else { |
| 2751 __ movzx_b(result, FieldOperand(string, |
| 2752 index, |
| 2753 times_1, |
| 2754 SeqAsciiString::kHeaderSize)); |
| 2755 } |
| 2756 __ bind(&done); |
| 2757 __ bind(deferred->exit()); |
| 2758 } |
| 2759 |
| 2760 |
| 2761 void LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) { |
| 2762 Register string = ToRegister(instr->string()); |
| 2763 Register result = ToRegister(instr->result()); |
| 2764 |
| 2765 // TODO(3095996): Get rid of this. For now, we need to make the |
| 2766 // result register contain a valid pointer because it is already |
| 2767 // contained in the register pointer map. |
| 2768 __ Set(result, Immediate(0)); |
| 2769 |
| 2770 __ PushSafepointRegisters(); |
| 2771 __ push(string); |
| 2772 // Push the index as a smi. This is safe because of the checks in |
| 2773 // DoStringCharCodeAt above. |
| 2774 STATIC_ASSERT(String::kMaxLength <= Smi::kMaxValue); |
| 2775 if (instr->index()->IsConstantOperand()) { |
| 2776 int const_index = ToInteger32(LConstantOperand::cast(instr->index())); |
| 2777 __ push(Immediate(Smi::FromInt(const_index))); |
| 2778 } else { |
| 2779 Register index = ToRegister(instr->index()); |
| 2780 __ SmiTag(index); |
| 2781 __ push(index); |
| 2782 } |
| 2783 __ CallRuntimeSaveDoubles(Runtime::kStringCharCodeAt); |
| 2784 RecordSafepointWithRegisters( |
| 2785 instr->pointer_map(), 2, Safepoint::kNoDeoptimizationIndex); |
| 2786 if (FLAG_debug_code) { |
| 2787 __ AbortIfNotSmi(eax); |
| 2788 } |
| 2789 __ SmiUntag(eax); |
| 2790 __ mov(Operand(esp, EspIndexForPushAll(result) * kPointerSize), eax); |
| 2791 __ PopSafepointRegisters(); |
| 2792 } |
| 2793 |
| 2794 |
| 2795 void LCodeGen::DoStringLength(LStringLength* instr) { |
| 2796 Register string = ToRegister(instr->string()); |
| 2797 Register result = ToRegister(instr->result()); |
| 2798 __ mov(result, FieldOperand(string, String::kLengthOffset)); |
| 2799 } |
| 2800 |
| 2801 |
| 2693 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { | 2802 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { |
| 2694 LOperand* input = instr->input(); | 2803 LOperand* input = instr->InputAt(0); |
| 2695 ASSERT(input->IsRegister() || input->IsStackSlot()); | 2804 ASSERT(input->IsRegister() || input->IsStackSlot()); |
| 2696 LOperand* output = instr->result(); | 2805 LOperand* output = instr->result(); |
| 2697 ASSERT(output->IsDoubleRegister()); | 2806 ASSERT(output->IsDoubleRegister()); |
| 2698 __ cvtsi2sd(ToDoubleRegister(output), ToOperand(input)); | 2807 __ cvtsi2sd(ToDoubleRegister(output), ToOperand(input)); |
| 2699 } | 2808 } |
| 2700 | 2809 |
| 2701 | 2810 |
| 2702 void LCodeGen::DoNumberTagI(LNumberTagI* instr) { | 2811 void LCodeGen::DoNumberTagI(LNumberTagI* instr) { |
| 2703 class DeferredNumberTagI: public LDeferredCode { | 2812 class DeferredNumberTagI: public LDeferredCode { |
| 2704 public: | 2813 public: |
| 2705 DeferredNumberTagI(LCodeGen* codegen, LNumberTagI* instr) | 2814 DeferredNumberTagI(LCodeGen* codegen, LNumberTagI* instr) |
| 2706 : LDeferredCode(codegen), instr_(instr) { } | 2815 : LDeferredCode(codegen), instr_(instr) { } |
| 2707 virtual void Generate() { codegen()->DoDeferredNumberTagI(instr_); } | 2816 virtual void Generate() { codegen()->DoDeferredNumberTagI(instr_); } |
| 2708 private: | 2817 private: |
| 2709 LNumberTagI* instr_; | 2818 LNumberTagI* instr_; |
| 2710 }; | 2819 }; |
| 2711 | 2820 |
| 2712 LOperand* input = instr->input(); | 2821 LOperand* input = instr->InputAt(0); |
| 2713 ASSERT(input->IsRegister() && input->Equals(instr->result())); | 2822 ASSERT(input->IsRegister() && input->Equals(instr->result())); |
| 2714 Register reg = ToRegister(input); | 2823 Register reg = ToRegister(input); |
| 2715 | 2824 |
| 2716 DeferredNumberTagI* deferred = new DeferredNumberTagI(this, instr); | 2825 DeferredNumberTagI* deferred = new DeferredNumberTagI(this, instr); |
| 2717 __ SmiTag(reg); | 2826 __ SmiTag(reg); |
| 2718 __ j(overflow, deferred->entry()); | 2827 __ j(overflow, deferred->entry()); |
| 2719 __ bind(deferred->exit()); | 2828 __ bind(deferred->exit()); |
| 2720 } | 2829 } |
| 2721 | 2830 |
| 2722 | 2831 |
| 2723 void LCodeGen::DoDeferredNumberTagI(LNumberTagI* instr) { | 2832 void LCodeGen::DoDeferredNumberTagI(LNumberTagI* instr) { |
| 2724 Label slow; | 2833 Label slow; |
| 2725 Register reg = ToRegister(instr->input()); | 2834 Register reg = ToRegister(instr->InputAt(0)); |
| 2726 Register tmp = reg.is(eax) ? ecx : eax; | 2835 Register tmp = reg.is(eax) ? ecx : eax; |
| 2727 | 2836 |
| 2728 // Preserve the value of all registers. | 2837 // Preserve the value of all registers. |
| 2729 __ PushSafepointRegisters(); | 2838 __ PushSafepointRegisters(); |
| 2730 | 2839 |
| 2731 // There was overflow, so bits 30 and 31 of the original integer | 2840 // There was overflow, so bits 30 and 31 of the original integer |
| 2732 // disagree. Try to allocate a heap number in new space and store | 2841 // disagree. Try to allocate a heap number in new space and store |
| 2733 // the value in there. If that fails, call the runtime system. | 2842 // the value in there. If that fails, call the runtime system. |
| 2734 NearLabel done; | 2843 NearLabel done; |
| 2735 __ SmiUntag(reg); | 2844 __ SmiUntag(reg); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 2765 void LCodeGen::DoNumberTagD(LNumberTagD* instr) { | 2874 void LCodeGen::DoNumberTagD(LNumberTagD* instr) { |
| 2766 class DeferredNumberTagD: public LDeferredCode { | 2875 class DeferredNumberTagD: public LDeferredCode { |
| 2767 public: | 2876 public: |
| 2768 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) | 2877 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) |
| 2769 : LDeferredCode(codegen), instr_(instr) { } | 2878 : LDeferredCode(codegen), instr_(instr) { } |
| 2770 virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); } | 2879 virtual void Generate() { codegen()->DoDeferredNumberTagD(instr_); } |
| 2771 private: | 2880 private: |
| 2772 LNumberTagD* instr_; | 2881 LNumberTagD* instr_; |
| 2773 }; | 2882 }; |
| 2774 | 2883 |
| 2775 XMMRegister input_reg = ToDoubleRegister(instr->input()); | 2884 XMMRegister input_reg = ToDoubleRegister(instr->InputAt(0)); |
| 2776 Register reg = ToRegister(instr->result()); | 2885 Register reg = ToRegister(instr->result()); |
| 2777 Register tmp = ToRegister(instr->temp()); | 2886 Register tmp = ToRegister(instr->TempAt(0)); |
| 2778 | 2887 |
| 2779 DeferredNumberTagD* deferred = new DeferredNumberTagD(this, instr); | 2888 DeferredNumberTagD* deferred = new DeferredNumberTagD(this, instr); |
| 2780 if (FLAG_inline_new) { | 2889 if (FLAG_inline_new) { |
| 2781 __ AllocateHeapNumber(reg, tmp, no_reg, deferred->entry()); | 2890 __ AllocateHeapNumber(reg, tmp, no_reg, deferred->entry()); |
| 2782 } else { | 2891 } else { |
| 2783 __ jmp(deferred->entry()); | 2892 __ jmp(deferred->entry()); |
| 2784 } | 2893 } |
| 2785 __ bind(deferred->exit()); | 2894 __ bind(deferred->exit()); |
| 2786 __ movdbl(FieldOperand(reg, HeapNumber::kValueOffset), input_reg); | 2895 __ movdbl(FieldOperand(reg, HeapNumber::kValueOffset), input_reg); |
| 2787 } | 2896 } |
| 2788 | 2897 |
| 2789 | 2898 |
| 2790 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { | 2899 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { |
| 2791 // TODO(3095996): Get rid of this. For now, we need to make the | 2900 // TODO(3095996): Get rid of this. For now, we need to make the |
| 2792 // result register contain a valid pointer because it is already | 2901 // result register contain a valid pointer because it is already |
| 2793 // contained in the register pointer map. | 2902 // contained in the register pointer map. |
| 2794 Register reg = ToRegister(instr->result()); | 2903 Register reg = ToRegister(instr->result()); |
| 2795 __ Set(reg, Immediate(0)); | 2904 __ Set(reg, Immediate(0)); |
| 2796 | 2905 |
| 2797 __ PushSafepointRegisters(); | 2906 __ PushSafepointRegisters(); |
| 2798 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); | 2907 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); |
| 2799 RecordSafepointWithRegisters( | 2908 RecordSafepointWithRegisters( |
| 2800 instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex); | 2909 instr->pointer_map(), 0, Safepoint::kNoDeoptimizationIndex); |
| 2801 __ mov(Operand(esp, EspIndexForPushAll(reg) * kPointerSize), eax); | 2910 __ mov(Operand(esp, EspIndexForPushAll(reg) * kPointerSize), eax); |
| 2802 __ PopSafepointRegisters(); | 2911 __ PopSafepointRegisters(); |
| 2803 } | 2912 } |
| 2804 | 2913 |
| 2805 | 2914 |
| 2806 void LCodeGen::DoSmiTag(LSmiTag* instr) { | 2915 void LCodeGen::DoSmiTag(LSmiTag* instr) { |
| 2807 LOperand* input = instr->input(); | 2916 LOperand* input = instr->InputAt(0); |
| 2808 ASSERT(input->IsRegister() && input->Equals(instr->result())); | 2917 ASSERT(input->IsRegister() && input->Equals(instr->result())); |
| 2809 ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow)); | 2918 ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow)); |
| 2810 __ SmiTag(ToRegister(input)); | 2919 __ SmiTag(ToRegister(input)); |
| 2811 } | 2920 } |
| 2812 | 2921 |
| 2813 | 2922 |
| 2814 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { | 2923 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { |
| 2815 LOperand* input = instr->input(); | 2924 LOperand* input = instr->InputAt(0); |
| 2816 ASSERT(input->IsRegister() && input->Equals(instr->result())); | 2925 ASSERT(input->IsRegister() && input->Equals(instr->result())); |
| 2817 if (instr->needs_check()) { | 2926 if (instr->needs_check()) { |
| 2818 __ test(ToRegister(input), Immediate(kSmiTagMask)); | 2927 __ test(ToRegister(input), Immediate(kSmiTagMask)); |
| 2819 DeoptimizeIf(not_zero, instr->environment()); | 2928 DeoptimizeIf(not_zero, instr->environment()); |
| 2820 } | 2929 } |
| 2821 __ SmiUntag(ToRegister(input)); | 2930 __ SmiUntag(ToRegister(input)); |
| 2822 } | 2931 } |
| 2823 | 2932 |
| 2824 | 2933 |
| 2825 void LCodeGen::EmitNumberUntagD(Register input_reg, | 2934 void LCodeGen::EmitNumberUntagD(Register input_reg, |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2865 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) | 2974 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) |
| 2866 : LDeferredCode(codegen), instr_(instr) { } | 2975 : LDeferredCode(codegen), instr_(instr) { } |
| 2867 virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); } | 2976 virtual void Generate() { codegen()->DoDeferredTaggedToI(instr_); } |
| 2868 private: | 2977 private: |
| 2869 LTaggedToI* instr_; | 2978 LTaggedToI* instr_; |
| 2870 }; | 2979 }; |
| 2871 | 2980 |
| 2872 | 2981 |
| 2873 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { | 2982 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr) { |
| 2874 NearLabel done, heap_number; | 2983 NearLabel done, heap_number; |
| 2875 Register input_reg = ToRegister(instr->input()); | 2984 Register input_reg = ToRegister(instr->InputAt(0)); |
| 2876 | 2985 |
| 2877 // Heap number map check. | 2986 // Heap number map check. |
| 2878 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), | 2987 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), |
| 2879 FACTORY->heap_number_map()); | 2988 FACTORY->heap_number_map()); |
| 2880 | 2989 |
| 2881 if (instr->truncating()) { | 2990 if (instr->truncating()) { |
| 2882 __ j(equal, &heap_number); | 2991 __ j(equal, &heap_number); |
| 2883 // Check for undefined. Undefined is converted to zero for truncating | 2992 // Check for undefined. Undefined is converted to zero for truncating |
| 2884 // conversions. | 2993 // conversions. |
| 2885 __ cmp(input_reg, FACTORY->undefined_value()); | 2994 __ cmp(input_reg, FACTORY->undefined_value()); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 2908 | 3017 |
| 2909 // Reserve space for 64 bit answer. | 3018 // Reserve space for 64 bit answer. |
| 2910 __ bind(&convert); | 3019 __ bind(&convert); |
| 2911 __ sub(Operand(esp), Immediate(kDoubleSize)); | 3020 __ sub(Operand(esp), Immediate(kDoubleSize)); |
| 2912 // Do conversion, which cannot fail because we checked the exponent. | 3021 // Do conversion, which cannot fail because we checked the exponent. |
| 2913 __ fisttp_d(Operand(esp, 0)); | 3022 __ fisttp_d(Operand(esp, 0)); |
| 2914 __ mov(input_reg, Operand(esp, 0)); // Low word of answer is the result. | 3023 __ mov(input_reg, Operand(esp, 0)); // Low word of answer is the result. |
| 2915 __ add(Operand(esp), Immediate(kDoubleSize)); | 3024 __ add(Operand(esp), Immediate(kDoubleSize)); |
| 2916 } else { | 3025 } else { |
| 2917 NearLabel deopt; | 3026 NearLabel deopt; |
| 2918 XMMRegister xmm_temp = ToDoubleRegister(instr->temp()); | 3027 XMMRegister xmm_temp = ToDoubleRegister(instr->TempAt(0)); |
| 2919 __ movdbl(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); | 3028 __ movdbl(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
| 2920 __ cvttsd2si(input_reg, Operand(xmm0)); | 3029 __ cvttsd2si(input_reg, Operand(xmm0)); |
| 2921 __ cmp(input_reg, 0x80000000u); | 3030 __ cmp(input_reg, 0x80000000u); |
| 2922 __ j(not_equal, &done); | 3031 __ j(not_equal, &done); |
| 2923 // Check if the input was 0x8000000 (kMinInt). | 3032 // Check if the input was 0x8000000 (kMinInt). |
| 2924 // If no, then we got an overflow and we deoptimize. | 3033 // If no, then we got an overflow and we deoptimize. |
| 2925 ExternalReference min_int = ExternalReference::address_of_min_int(); | 3034 ExternalReference min_int = ExternalReference::address_of_min_int(); |
| 2926 __ movdbl(xmm_temp, Operand::StaticVariable(min_int)); | 3035 __ movdbl(xmm_temp, Operand::StaticVariable(min_int)); |
| 2927 __ ucomisd(xmm_temp, xmm0); | 3036 __ ucomisd(xmm_temp, xmm0); |
| 2928 DeoptimizeIf(not_equal, instr->environment()); | 3037 DeoptimizeIf(not_equal, instr->environment()); |
| 2929 DeoptimizeIf(parity_even, instr->environment()); // NaN. | 3038 DeoptimizeIf(parity_even, instr->environment()); // NaN. |
| 2930 } | 3039 } |
| 2931 } else { | 3040 } else { |
| 2932 // Deoptimize if we don't have a heap number. | 3041 // Deoptimize if we don't have a heap number. |
| 2933 DeoptimizeIf(not_equal, instr->environment()); | 3042 DeoptimizeIf(not_equal, instr->environment()); |
| 2934 | 3043 |
| 2935 XMMRegister xmm_temp = ToDoubleRegister(instr->temp()); | 3044 XMMRegister xmm_temp = ToDoubleRegister(instr->TempAt(0)); |
| 2936 __ movdbl(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); | 3045 __ movdbl(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
| 2937 __ cvttsd2si(input_reg, Operand(xmm0)); | 3046 __ cvttsd2si(input_reg, Operand(xmm0)); |
| 2938 __ cvtsi2sd(xmm_temp, Operand(input_reg)); | 3047 __ cvtsi2sd(xmm_temp, Operand(input_reg)); |
| 2939 __ ucomisd(xmm0, xmm_temp); | 3048 __ ucomisd(xmm0, xmm_temp); |
| 2940 DeoptimizeIf(not_equal, instr->environment()); | 3049 DeoptimizeIf(not_equal, instr->environment()); |
| 2941 DeoptimizeIf(parity_even, instr->environment()); // NaN. | 3050 DeoptimizeIf(parity_even, instr->environment()); // NaN. |
| 2942 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3051 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 2943 __ test(input_reg, Operand(input_reg)); | 3052 __ test(input_reg, Operand(input_reg)); |
| 2944 __ j(not_zero, &done); | 3053 __ j(not_zero, &done); |
| 2945 __ movmskpd(input_reg, xmm0); | 3054 __ movmskpd(input_reg, xmm0); |
| 2946 __ and_(input_reg, 1); | 3055 __ and_(input_reg, 1); |
| 2947 DeoptimizeIf(not_zero, instr->environment()); | 3056 DeoptimizeIf(not_zero, instr->environment()); |
| 2948 } | 3057 } |
| 2949 } | 3058 } |
| 2950 __ bind(&done); | 3059 __ bind(&done); |
| 2951 } | 3060 } |
| 2952 | 3061 |
| 2953 | 3062 |
| 2954 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { | 3063 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { |
| 2955 LOperand* input = instr->input(); | 3064 LOperand* input = instr->InputAt(0); |
| 2956 ASSERT(input->IsRegister()); | 3065 ASSERT(input->IsRegister()); |
| 2957 ASSERT(input->Equals(instr->result())); | 3066 ASSERT(input->Equals(instr->result())); |
| 2958 | 3067 |
| 2959 Register input_reg = ToRegister(input); | 3068 Register input_reg = ToRegister(input); |
| 2960 | 3069 |
| 2961 DeferredTaggedToI* deferred = new DeferredTaggedToI(this, instr); | 3070 DeferredTaggedToI* deferred = new DeferredTaggedToI(this, instr); |
| 2962 | 3071 |
| 2963 // Smi check. | 3072 // Smi check. |
| 2964 __ test(input_reg, Immediate(kSmiTagMask)); | 3073 __ test(input_reg, Immediate(kSmiTagMask)); |
| 2965 __ j(not_zero, deferred->entry()); | 3074 __ j(not_zero, deferred->entry()); |
| 2966 | 3075 |
| 2967 // Smi to int32 conversion | 3076 // Smi to int32 conversion |
| 2968 __ SmiUntag(input_reg); // Untag smi. | 3077 __ SmiUntag(input_reg); // Untag smi. |
| 2969 | 3078 |
| 2970 __ bind(deferred->exit()); | 3079 __ bind(deferred->exit()); |
| 2971 } | 3080 } |
| 2972 | 3081 |
| 2973 | 3082 |
| 2974 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { | 3083 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { |
| 2975 LOperand* input = instr->input(); | 3084 LOperand* input = instr->InputAt(0); |
| 2976 ASSERT(input->IsRegister()); | 3085 ASSERT(input->IsRegister()); |
| 2977 LOperand* result = instr->result(); | 3086 LOperand* result = instr->result(); |
| 2978 ASSERT(result->IsDoubleRegister()); | 3087 ASSERT(result->IsDoubleRegister()); |
| 2979 | 3088 |
| 2980 Register input_reg = ToRegister(input); | 3089 Register input_reg = ToRegister(input); |
| 2981 XMMRegister result_reg = ToDoubleRegister(result); | 3090 XMMRegister result_reg = ToDoubleRegister(result); |
| 2982 | 3091 |
| 2983 EmitNumberUntagD(input_reg, result_reg, instr->environment()); | 3092 EmitNumberUntagD(input_reg, result_reg, instr->environment()); |
| 2984 } | 3093 } |
| 2985 | 3094 |
| 2986 | 3095 |
| 2987 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { | 3096 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { |
| 2988 LOperand* input = instr->input(); | 3097 LOperand* input = instr->InputAt(0); |
| 2989 ASSERT(input->IsDoubleRegister()); | 3098 ASSERT(input->IsDoubleRegister()); |
| 2990 LOperand* result = instr->result(); | 3099 LOperand* result = instr->result(); |
| 2991 ASSERT(result->IsRegister()); | 3100 ASSERT(result->IsRegister()); |
| 2992 | 3101 |
| 2993 XMMRegister input_reg = ToDoubleRegister(input); | 3102 XMMRegister input_reg = ToDoubleRegister(input); |
| 2994 Register result_reg = ToRegister(result); | 3103 Register result_reg = ToRegister(result); |
| 2995 | 3104 |
| 2996 if (instr->truncating()) { | 3105 if (instr->truncating()) { |
| 2997 // Performs a truncating conversion of a floating point number as used by | 3106 // Performs a truncating conversion of a floating point number as used by |
| 2998 // the JS bitwise operations. | 3107 // the JS bitwise operations. |
| (...skipping 17 matching lines...) Expand all Loading... |
| 3016 DeoptimizeIf(no_condition, instr->environment()); | 3125 DeoptimizeIf(no_condition, instr->environment()); |
| 3017 __ bind(&convert); | 3126 __ bind(&convert); |
| 3018 // Do conversion, which cannot fail because we checked the exponent. | 3127 // Do conversion, which cannot fail because we checked the exponent. |
| 3019 __ fld_d(Operand(esp, 0)); | 3128 __ fld_d(Operand(esp, 0)); |
| 3020 __ fisttp_d(Operand(esp, 0)); | 3129 __ fisttp_d(Operand(esp, 0)); |
| 3021 __ mov(result_reg, Operand(esp, 0)); // Low word of answer is the result. | 3130 __ mov(result_reg, Operand(esp, 0)); // Low word of answer is the result. |
| 3022 __ add(Operand(esp), Immediate(kDoubleSize)); | 3131 __ add(Operand(esp), Immediate(kDoubleSize)); |
| 3023 __ bind(&done); | 3132 __ bind(&done); |
| 3024 } else { | 3133 } else { |
| 3025 NearLabel done; | 3134 NearLabel done; |
| 3026 Register temp_reg = ToRegister(instr->temporary()); | 3135 Register temp_reg = ToRegister(instr->TempAt(0)); |
| 3027 XMMRegister xmm_scratch = xmm0; | 3136 XMMRegister xmm_scratch = xmm0; |
| 3028 | 3137 |
| 3029 // If cvttsd2si succeeded, we're done. Otherwise, we attempt | 3138 // If cvttsd2si succeeded, we're done. Otherwise, we attempt |
| 3030 // manual conversion. | 3139 // manual conversion. |
| 3031 __ j(not_equal, &done); | 3140 __ j(not_equal, &done); |
| 3032 | 3141 |
| 3033 // Get high 32 bits of the input in result_reg and temp_reg. | 3142 // Get high 32 bits of the input in result_reg and temp_reg. |
| 3034 __ pshufd(xmm_scratch, input_reg, 1); | 3143 __ pshufd(xmm_scratch, input_reg, 1); |
| 3035 __ movd(Operand(temp_reg), xmm_scratch); | 3144 __ movd(Operand(temp_reg), xmm_scratch); |
| 3036 __ mov(result_reg, temp_reg); | 3145 __ mov(result_reg, temp_reg); |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3095 // deoptimize. | 3204 // deoptimize. |
| 3096 __ and_(result_reg, 1); | 3205 __ and_(result_reg, 1); |
| 3097 DeoptimizeIf(not_zero, instr->environment()); | 3206 DeoptimizeIf(not_zero, instr->environment()); |
| 3098 } | 3207 } |
| 3099 __ bind(&done); | 3208 __ bind(&done); |
| 3100 } | 3209 } |
| 3101 } | 3210 } |
| 3102 | 3211 |
| 3103 | 3212 |
| 3104 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { | 3213 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { |
| 3105 LOperand* input = instr->input(); | 3214 LOperand* input = instr->InputAt(0); |
| 3106 ASSERT(input->IsRegister()); | 3215 ASSERT(input->IsRegister()); |
| 3107 __ test(ToRegister(input), Immediate(kSmiTagMask)); | 3216 __ test(ToRegister(input), Immediate(kSmiTagMask)); |
| 3108 DeoptimizeIf(instr->condition(), instr->environment()); | 3217 DeoptimizeIf(instr->condition(), instr->environment()); |
| 3109 } | 3218 } |
| 3110 | 3219 |
| 3111 | 3220 |
| 3112 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { | 3221 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { |
| 3113 Register input = ToRegister(instr->input()); | 3222 Register input = ToRegister(instr->InputAt(0)); |
| 3114 Register temp = ToRegister(instr->temp()); | 3223 Register temp = ToRegister(instr->TempAt(0)); |
| 3115 InstanceType first = instr->hydrogen()->first(); | 3224 InstanceType first = instr->hydrogen()->first(); |
| 3116 InstanceType last = instr->hydrogen()->last(); | 3225 InstanceType last = instr->hydrogen()->last(); |
| 3117 | 3226 |
| 3118 __ mov(temp, FieldOperand(input, HeapObject::kMapOffset)); | 3227 __ mov(temp, FieldOperand(input, HeapObject::kMapOffset)); |
| 3119 __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset), | |
| 3120 static_cast<int8_t>(first)); | |
| 3121 | 3228 |
| 3122 // If there is only one type in the interval check for equality. | 3229 // If there is only one type in the interval check for equality. |
| 3123 if (first == last) { | 3230 if (first == last) { |
| 3231 __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset), |
| 3232 static_cast<int8_t>(first)); |
| 3124 DeoptimizeIf(not_equal, instr->environment()); | 3233 DeoptimizeIf(not_equal, instr->environment()); |
| 3125 } else { | 3234 } else if (first == FIRST_STRING_TYPE && last == LAST_STRING_TYPE) { |
| 3235 // String has a dedicated bit in instance type. |
| 3236 __ test_b(FieldOperand(temp, Map::kInstanceTypeOffset), kIsNotStringMask); |
| 3237 DeoptimizeIf(not_zero, instr->environment()); |
| 3238 } else { |
| 3239 __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset), |
| 3240 static_cast<int8_t>(first)); |
| 3126 DeoptimizeIf(below, instr->environment()); | 3241 DeoptimizeIf(below, instr->environment()); |
| 3127 // Omit check for the last type. | 3242 // Omit check for the last type. |
| 3128 if (last != LAST_TYPE) { | 3243 if (last != LAST_TYPE) { |
| 3129 __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset), | 3244 __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset), |
| 3130 static_cast<int8_t>(last)); | 3245 static_cast<int8_t>(last)); |
| 3131 DeoptimizeIf(above, instr->environment()); | 3246 DeoptimizeIf(above, instr->environment()); |
| 3132 } | 3247 } |
| 3133 } | 3248 } |
| 3134 } | 3249 } |
| 3135 | 3250 |
| 3136 | 3251 |
| 3137 void LCodeGen::DoCheckFunction(LCheckFunction* instr) { | 3252 void LCodeGen::DoCheckFunction(LCheckFunction* instr) { |
| 3138 ASSERT(instr->input()->IsRegister()); | 3253 ASSERT(instr->InputAt(0)->IsRegister()); |
| 3139 Register reg = ToRegister(instr->input()); | 3254 Register reg = ToRegister(instr->InputAt(0)); |
| 3140 __ cmp(reg, instr->hydrogen()->target()); | 3255 __ cmp(reg, instr->hydrogen()->target()); |
| 3141 DeoptimizeIf(not_equal, instr->environment()); | 3256 DeoptimizeIf(not_equal, instr->environment()); |
| 3142 } | 3257 } |
| 3143 | 3258 |
| 3144 | 3259 |
| 3145 void LCodeGen::DoCheckMap(LCheckMap* instr) { | 3260 void LCodeGen::DoCheckMap(LCheckMap* instr) { |
| 3146 LOperand* input = instr->input(); | 3261 LOperand* input = instr->InputAt(0); |
| 3147 ASSERT(input->IsRegister()); | 3262 ASSERT(input->IsRegister()); |
| 3148 Register reg = ToRegister(input); | 3263 Register reg = ToRegister(input); |
| 3149 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), | 3264 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), |
| 3150 instr->hydrogen()->map()); | 3265 instr->hydrogen()->map()); |
| 3151 DeoptimizeIf(not_equal, instr->environment()); | 3266 DeoptimizeIf(not_equal, instr->environment()); |
| 3152 } | 3267 } |
| 3153 | 3268 |
| 3154 | 3269 |
| 3155 void LCodeGen::LoadPrototype(Register result, Handle<JSObject> prototype) { | 3270 void LCodeGen::LoadHeapObject(Register result, Handle<HeapObject> object) { |
| 3156 if (HEAP->InNewSpace(*prototype)) { | 3271 if (HEAP->InNewSpace(*object)) { |
| 3157 Handle<JSGlobalPropertyCell> cell = | 3272 Handle<JSGlobalPropertyCell> cell = |
| 3158 FACTORY->NewJSGlobalPropertyCell(prototype); | 3273 FACTORY->NewJSGlobalPropertyCell(object); |
| 3159 __ mov(result, Operand::Cell(cell)); | 3274 __ mov(result, Operand::Cell(cell)); |
| 3160 } else { | 3275 } else { |
| 3161 __ mov(result, prototype); | 3276 __ mov(result, object); |
| 3162 } | 3277 } |
| 3163 } | 3278 } |
| 3164 | 3279 |
| 3165 | 3280 |
| 3166 void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) { | 3281 void LCodeGen::DoCheckPrototypeMaps(LCheckPrototypeMaps* instr) { |
| 3167 Register reg = ToRegister(instr->temp()); | 3282 Register reg = ToRegister(instr->TempAt(0)); |
| 3168 | 3283 |
| 3169 Handle<JSObject> holder = instr->holder(); | 3284 Handle<JSObject> holder = instr->holder(); |
| 3170 Handle<JSObject> current_prototype = instr->prototype(); | 3285 Handle<JSObject> current_prototype = instr->prototype(); |
| 3171 | 3286 |
| 3172 // Load prototype object. | 3287 // Load prototype object. |
| 3173 LoadPrototype(reg, current_prototype); | 3288 LoadHeapObject(reg, current_prototype); |
| 3174 | 3289 |
| 3175 // Check prototype maps up to the holder. | 3290 // Check prototype maps up to the holder. |
| 3176 while (!current_prototype.is_identical_to(holder)) { | 3291 while (!current_prototype.is_identical_to(holder)) { |
| 3177 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), | 3292 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), |
| 3178 Handle<Map>(current_prototype->map())); | 3293 Handle<Map>(current_prototype->map())); |
| 3179 DeoptimizeIf(not_equal, instr->environment()); | 3294 DeoptimizeIf(not_equal, instr->environment()); |
| 3180 current_prototype = | 3295 current_prototype = |
| 3181 Handle<JSObject>(JSObject::cast(current_prototype->GetPrototype())); | 3296 Handle<JSObject>(JSObject::cast(current_prototype->GetPrototype())); |
| 3182 // Load next prototype object. | 3297 // Load next prototype object. |
| 3183 LoadPrototype(reg, current_prototype); | 3298 LoadHeapObject(reg, current_prototype); |
| 3184 } | 3299 } |
| 3185 | 3300 |
| 3186 // Check the holder map. | 3301 // Check the holder map. |
| 3187 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), | 3302 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), |
| 3188 Handle<Map>(current_prototype->map())); | 3303 Handle<Map>(current_prototype->map())); |
| 3189 DeoptimizeIf(not_equal, instr->environment()); | 3304 DeoptimizeIf(not_equal, instr->environment()); |
| 3190 } | 3305 } |
| 3191 | 3306 |
| 3192 | 3307 |
| 3193 void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) { | 3308 void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) { |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3301 __ push(Immediate(shared_info)); | 3416 __ push(Immediate(shared_info)); |
| 3302 __ push(Immediate(pretenure | 3417 __ push(Immediate(pretenure |
| 3303 ? FACTORY->true_value() | 3418 ? FACTORY->true_value() |
| 3304 : FACTORY->false_value())); | 3419 : FACTORY->false_value())); |
| 3305 CallRuntime(Runtime::kNewClosure, 3, instr); | 3420 CallRuntime(Runtime::kNewClosure, 3, instr); |
| 3306 } | 3421 } |
| 3307 } | 3422 } |
| 3308 | 3423 |
| 3309 | 3424 |
| 3310 void LCodeGen::DoTypeof(LTypeof* instr) { | 3425 void LCodeGen::DoTypeof(LTypeof* instr) { |
| 3311 LOperand* input = instr->input(); | 3426 LOperand* input = instr->InputAt(0); |
| 3312 if (input->IsConstantOperand()) { | 3427 if (input->IsConstantOperand()) { |
| 3313 __ push(ToImmediate(input)); | 3428 __ push(ToImmediate(input)); |
| 3314 } else { | 3429 } else { |
| 3315 __ push(ToOperand(input)); | 3430 __ push(ToOperand(input)); |
| 3316 } | 3431 } |
| 3317 CallRuntime(Runtime::kTypeof, 1, instr); | 3432 CallRuntime(Runtime::kTypeof, 1, instr); |
| 3318 } | 3433 } |
| 3319 | 3434 |
| 3320 | 3435 |
| 3321 void LCodeGen::DoTypeofIs(LTypeofIs* instr) { | 3436 void LCodeGen::DoTypeofIs(LTypeofIs* instr) { |
| 3322 Register input = ToRegister(instr->input()); | 3437 Register input = ToRegister(instr->InputAt(0)); |
| 3323 Register result = ToRegister(instr->result()); | 3438 Register result = ToRegister(instr->result()); |
| 3324 Label true_label; | 3439 Label true_label; |
| 3325 Label false_label; | 3440 Label false_label; |
| 3326 NearLabel done; | 3441 NearLabel done; |
| 3327 | 3442 |
| 3328 Condition final_branch_condition = EmitTypeofIs(&true_label, | 3443 Condition final_branch_condition = EmitTypeofIs(&true_label, |
| 3329 &false_label, | 3444 &false_label, |
| 3330 input, | 3445 input, |
| 3331 instr->type_literal()); | 3446 instr->type_literal()); |
| 3332 __ j(final_branch_condition, &true_label); | 3447 __ j(final_branch_condition, &true_label); |
| 3333 __ bind(&false_label); | 3448 __ bind(&false_label); |
| 3334 __ mov(result, Handle<Object>(HEAP->false_value())); | 3449 __ mov(result, FACTORY->false_value()); |
| 3335 __ jmp(&done); | 3450 __ jmp(&done); |
| 3336 | 3451 |
| 3337 __ bind(&true_label); | 3452 __ bind(&true_label); |
| 3338 __ mov(result, Handle<Object>(HEAP->true_value())); | 3453 __ mov(result, FACTORY->true_value()); |
| 3339 | 3454 |
| 3340 __ bind(&done); | 3455 __ bind(&done); |
| 3341 } | 3456 } |
| 3342 | 3457 |
| 3343 | 3458 |
| 3344 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { | 3459 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { |
| 3345 Register input = ToRegister(instr->input()); | 3460 Register input = ToRegister(instr->InputAt(0)); |
| 3346 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 3461 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 3347 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 3462 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 3348 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 3463 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
| 3349 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 3464 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
| 3350 | 3465 |
| 3351 Condition final_branch_condition = EmitTypeofIs(true_label, | 3466 Condition final_branch_condition = EmitTypeofIs(true_label, |
| 3352 false_label, | 3467 false_label, |
| 3353 input, | 3468 input, |
| 3354 instr->type_literal()); | 3469 instr->type_literal()); |
| 3355 | 3470 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 3373 __ test(input, Immediate(kSmiTagMask)); | 3488 __ test(input, Immediate(kSmiTagMask)); |
| 3374 __ j(zero, false_label); | 3489 __ j(zero, false_label); |
| 3375 __ mov(input, FieldOperand(input, HeapObject::kMapOffset)); | 3490 __ mov(input, FieldOperand(input, HeapObject::kMapOffset)); |
| 3376 __ test_b(FieldOperand(input, Map::kBitFieldOffset), | 3491 __ test_b(FieldOperand(input, Map::kBitFieldOffset), |
| 3377 1 << Map::kIsUndetectable); | 3492 1 << Map::kIsUndetectable); |
| 3378 __ j(not_zero, false_label); | 3493 __ j(not_zero, false_label); |
| 3379 __ CmpInstanceType(input, FIRST_NONSTRING_TYPE); | 3494 __ CmpInstanceType(input, FIRST_NONSTRING_TYPE); |
| 3380 final_branch_condition = below; | 3495 final_branch_condition = below; |
| 3381 | 3496 |
| 3382 } else if (type_name->Equals(HEAP->boolean_symbol())) { | 3497 } else if (type_name->Equals(HEAP->boolean_symbol())) { |
| 3383 __ cmp(input, Handle<Object>(HEAP->true_value())); | 3498 __ cmp(input, FACTORY->true_value()); |
| 3384 __ j(equal, true_label); | 3499 __ j(equal, true_label); |
| 3385 __ cmp(input, Handle<Object>(HEAP->false_value())); | 3500 __ cmp(input, FACTORY->false_value()); |
| 3386 final_branch_condition = equal; | 3501 final_branch_condition = equal; |
| 3387 | 3502 |
| 3388 } else if (type_name->Equals(HEAP->undefined_symbol())) { | 3503 } else if (type_name->Equals(HEAP->undefined_symbol())) { |
| 3389 __ cmp(input, FACTORY->undefined_value()); | 3504 __ cmp(input, FACTORY->undefined_value()); |
| 3390 __ j(equal, true_label); | 3505 __ j(equal, true_label); |
| 3391 __ test(input, Immediate(kSmiTagMask)); | 3506 __ test(input, Immediate(kSmiTagMask)); |
| 3392 __ j(zero, false_label); | 3507 __ j(zero, false_label); |
| 3393 // Check for undetectable objects => true. | 3508 // Check for undetectable objects => true. |
| 3394 __ mov(input, FieldOperand(input, HeapObject::kMapOffset)); | 3509 __ mov(input, FieldOperand(input, HeapObject::kMapOffset)); |
| 3395 __ test_b(FieldOperand(input, Map::kBitFieldOffset), | 3510 __ test_b(FieldOperand(input, Map::kBitFieldOffset), |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3489 ASSERT(osr_pc_offset_ == -1); | 3604 ASSERT(osr_pc_offset_ == -1); |
| 3490 osr_pc_offset_ = masm()->pc_offset(); | 3605 osr_pc_offset_ = masm()->pc_offset(); |
| 3491 } | 3606 } |
| 3492 | 3607 |
| 3493 | 3608 |
| 3494 #undef __ | 3609 #undef __ |
| 3495 | 3610 |
| 3496 } } // namespace v8::internal | 3611 } } // namespace v8::internal |
| 3497 | 3612 |
| 3498 #endif // V8_TARGET_ARCH_IA32 | 3613 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |