| OLD | NEW |
| 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 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 768 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 779 frame_->Push(&answer); | 779 frame_->Push(&answer); |
| 780 } else { | 780 } else { |
| 781 // Call the stub and push the result to the stack. | 781 // Call the stub and push the result to the stack. |
| 782 GenericBinaryOpStub stub(op, overwrite_mode, flags); | 782 GenericBinaryOpStub stub(op, overwrite_mode, flags); |
| 783 Result answer = frame_->CallStub(&stub, 2); | 783 Result answer = frame_->CallStub(&stub, 2); |
| 784 frame_->Push(&answer); | 784 frame_->Push(&answer); |
| 785 } | 785 } |
| 786 } | 786 } |
| 787 | 787 |
| 788 | 788 |
| 789 class DeferredInlinedSmiOperation: public DeferredCode { | 789 class DeferredInlineSmiOperation: public DeferredCode { |
| 790 public: | 790 public: |
| 791 DeferredInlinedSmiOperation(CodeGenerator* generator, | 791 DeferredInlineSmiOperation(CodeGenerator* generator, |
| 792 Token::Value op, | 792 Token::Value op, |
| 793 Smi* value, | 793 Smi* value, |
| 794 OverwriteMode overwrite_mode) | 794 OverwriteMode overwrite_mode) |
| 795 : DeferredCode(generator), | 795 : DeferredCode(generator), |
| 796 op_(op), | 796 op_(op), |
| 797 value_(value), | 797 value_(value), |
| 798 overwrite_mode_(overwrite_mode) { | 798 overwrite_mode_(overwrite_mode) { |
| 799 set_comment("[ DeferredInlinedSmiOperation"); | 799 set_comment("[ DeferredInlineSmiOperation"); |
| 800 } | 800 } |
| 801 | 801 |
| 802 virtual void Generate(); | 802 virtual void Generate(); |
| 803 | 803 |
| 804 private: | 804 private: |
| 805 Token::Value op_; | 805 Token::Value op_; |
| 806 Smi* value_; | 806 Smi* value_; |
| 807 OverwriteMode overwrite_mode_; | 807 OverwriteMode overwrite_mode_; |
| 808 }; | 808 }; |
| 809 | 809 |
| 810 | 810 |
| 811 void DeferredInlinedSmiOperation::Generate() { | 811 void DeferredInlineSmiOperation::Generate() { |
| 812 Result left(generator()); | 812 Result left(generator()); |
| 813 enter()->Bind(&left); | 813 enter()->Bind(&left); |
| 814 generator()->frame()->Push(&left); | 814 generator()->frame()->Push(&left); |
| 815 generator()->frame()->Push(value_); | 815 generator()->frame()->Push(value_); |
| 816 GenericBinaryOpStub igostub(op_, overwrite_mode_, SMI_CODE_INLINED); | 816 GenericBinaryOpStub igostub(op_, overwrite_mode_, SMI_CODE_INLINED); |
| 817 Result answer = generator()->frame()->CallStub(&igostub, 2); | 817 Result answer = generator()->frame()->CallStub(&igostub, 2); |
| 818 exit()->Jump(&answer); | 818 exit()->Jump(&answer); |
| 819 } | 819 } |
| 820 | 820 |
| 821 | 821 |
| 822 class DeferredInlinedSmiOperationReversed: public DeferredCode { | 822 class DeferredInlineSmiOperationReversed: public DeferredCode { |
| 823 public: | 823 public: |
| 824 DeferredInlinedSmiOperationReversed(CodeGenerator* generator, | 824 DeferredInlineSmiOperationReversed(CodeGenerator* generator, |
| 825 Token::Value op, | 825 Token::Value op, |
| 826 Smi* value, | 826 Smi* value, |
| 827 OverwriteMode overwrite_mode) | 827 OverwriteMode overwrite_mode) |
| 828 : DeferredCode(generator), | 828 : DeferredCode(generator), |
| 829 op_(op), | 829 op_(op), |
| 830 value_(value), | 830 value_(value), |
| 831 overwrite_mode_(overwrite_mode) { | 831 overwrite_mode_(overwrite_mode) { |
| 832 set_comment("[ DeferredInlinedSmiOperationReversed"); | 832 set_comment("[ DeferredInlineSmiOperationReversed"); |
| 833 } | 833 } |
| 834 | 834 |
| 835 virtual void Generate(); | 835 virtual void Generate(); |
| 836 | 836 |
| 837 private: | 837 private: |
| 838 Token::Value op_; | 838 Token::Value op_; |
| 839 Smi* value_; | 839 Smi* value_; |
| 840 OverwriteMode overwrite_mode_; | 840 OverwriteMode overwrite_mode_; |
| 841 }; | 841 }; |
| 842 | 842 |
| 843 | 843 |
| 844 void DeferredInlinedSmiOperationReversed::Generate() { | 844 void DeferredInlineSmiOperationReversed::Generate() { |
| 845 Result right(generator()); | 845 Result right(generator()); |
| 846 enter()->Bind(&right); | 846 enter()->Bind(&right); |
| 847 generator()->frame()->Push(value_); | 847 generator()->frame()->Push(value_); |
| 848 generator()->frame()->Push(&right); | 848 generator()->frame()->Push(&right); |
| 849 GenericBinaryOpStub igostub(op_, overwrite_mode_, SMI_CODE_INLINED); | 849 GenericBinaryOpStub igostub(op_, overwrite_mode_, SMI_CODE_INLINED); |
| 850 Result answer = generator()->frame()->CallStub(&igostub, 2); | 850 Result answer = generator()->frame()->CallStub(&igostub, 2); |
| 851 exit()->Jump(&answer); | 851 exit()->Jump(&answer); |
| 852 } | 852 } |
| 853 | 853 |
| 854 | 854 |
| 855 class DeferredInlinedSmiAdd: public DeferredCode { | 855 class DeferredInlineSmiAdd: public DeferredCode { |
| 856 public: | 856 public: |
| 857 DeferredInlinedSmiAdd(CodeGenerator* generator, | 857 DeferredInlineSmiAdd(CodeGenerator* generator, |
| 858 Smi* value, | 858 Smi* value, |
| 859 OverwriteMode overwrite_mode) | 859 OverwriteMode overwrite_mode) |
| 860 : DeferredCode(generator), | 860 : DeferredCode(generator), |
| 861 value_(value), | 861 value_(value), |
| 862 overwrite_mode_(overwrite_mode) { | 862 overwrite_mode_(overwrite_mode) { |
| 863 set_comment("[ DeferredInlinedSmiAdd"); | 863 set_comment("[ DeferredInlineSmiAdd"); |
| 864 } | 864 } |
| 865 | 865 |
| 866 virtual void Generate(); | 866 virtual void Generate(); |
| 867 | 867 |
| 868 private: | 868 private: |
| 869 Smi* value_; | 869 Smi* value_; |
| 870 OverwriteMode overwrite_mode_; | 870 OverwriteMode overwrite_mode_; |
| 871 }; | 871 }; |
| 872 | 872 |
| 873 | 873 |
| 874 void DeferredInlinedSmiAdd::Generate() { | 874 void DeferredInlineSmiAdd::Generate() { |
| 875 // Undo the optimistic add operation and call the shared stub. | 875 // Undo the optimistic add operation and call the shared stub. |
| 876 Result left(generator()); // Initially left + value_. | 876 Result left(generator()); // Initially left + value_. |
| 877 enter()->Bind(&left); | 877 enter()->Bind(&left); |
| 878 left.ToRegister(); | 878 left.ToRegister(); |
| 879 generator()->frame()->Spill(left.reg()); | 879 generator()->frame()->Spill(left.reg()); |
| 880 __ sub(Operand(left.reg()), Immediate(value_)); | 880 __ sub(Operand(left.reg()), Immediate(value_)); |
| 881 generator()->frame()->Push(&left); | 881 generator()->frame()->Push(&left); |
| 882 generator()->frame()->Push(value_); | 882 generator()->frame()->Push(value_); |
| 883 GenericBinaryOpStub igostub(Token::ADD, overwrite_mode_, SMI_CODE_INLINED); | 883 GenericBinaryOpStub igostub(Token::ADD, overwrite_mode_, SMI_CODE_INLINED); |
| 884 Result answer = generator()->frame()->CallStub(&igostub, 2); | 884 Result answer = generator()->frame()->CallStub(&igostub, 2); |
| 885 exit()->Jump(&answer); | 885 exit()->Jump(&answer); |
| 886 } | 886 } |
| 887 | 887 |
| 888 | 888 |
| 889 class DeferredInlinedSmiAddReversed: public DeferredCode { | 889 class DeferredInlineSmiAddReversed: public DeferredCode { |
| 890 public: | 890 public: |
| 891 DeferredInlinedSmiAddReversed(CodeGenerator* generator, | 891 DeferredInlineSmiAddReversed(CodeGenerator* generator, |
| 892 Smi* value, | 892 Smi* value, |
| 893 OverwriteMode overwrite_mode) | 893 OverwriteMode overwrite_mode) |
| 894 : DeferredCode(generator), | 894 : DeferredCode(generator), |
| 895 value_(value), | 895 value_(value), |
| 896 overwrite_mode_(overwrite_mode) { | 896 overwrite_mode_(overwrite_mode) { |
| 897 set_comment("[ DeferredInlinedSmiAddReversed"); | 897 set_comment("[ DeferredInlineSmiAddReversed"); |
| 898 } | 898 } |
| 899 | 899 |
| 900 virtual void Generate(); | 900 virtual void Generate(); |
| 901 | 901 |
| 902 private: | 902 private: |
| 903 Smi* value_; | 903 Smi* value_; |
| 904 OverwriteMode overwrite_mode_; | 904 OverwriteMode overwrite_mode_; |
| 905 }; | 905 }; |
| 906 | 906 |
| 907 | 907 |
| 908 void DeferredInlinedSmiAddReversed::Generate() { | 908 void DeferredInlineSmiAddReversed::Generate() { |
| 909 // Undo the optimistic add operation and call the shared stub. | 909 // Undo the optimistic add operation and call the shared stub. |
| 910 Result right(generator()); // Initially value_ + right. | 910 Result right(generator()); // Initially value_ + right. |
| 911 enter()->Bind(&right); | 911 enter()->Bind(&right); |
| 912 right.ToRegister(); | 912 right.ToRegister(); |
| 913 generator()->frame()->Spill(right.reg()); | 913 generator()->frame()->Spill(right.reg()); |
| 914 __ sub(Operand(right.reg()), Immediate(value_)); | 914 __ sub(Operand(right.reg()), Immediate(value_)); |
| 915 generator()->frame()->Push(value_); | 915 generator()->frame()->Push(value_); |
| 916 generator()->frame()->Push(&right); | 916 generator()->frame()->Push(&right); |
| 917 GenericBinaryOpStub igostub(Token::ADD, overwrite_mode_, SMI_CODE_INLINED); | 917 GenericBinaryOpStub igostub(Token::ADD, overwrite_mode_, SMI_CODE_INLINED); |
| 918 Result answer = generator()->frame()->CallStub(&igostub, 2); | 918 Result answer = generator()->frame()->CallStub(&igostub, 2); |
| 919 exit()->Jump(&answer); | 919 exit()->Jump(&answer); |
| 920 } | 920 } |
| 921 | 921 |
| 922 | 922 |
| 923 class DeferredInlinedSmiSub: public DeferredCode { | 923 class DeferredInlineSmiSub: public DeferredCode { |
| 924 public: | 924 public: |
| 925 DeferredInlinedSmiSub(CodeGenerator* generator, | 925 DeferredInlineSmiSub(CodeGenerator* generator, |
| 926 Smi* value, | 926 Smi* value, |
| 927 OverwriteMode overwrite_mode) | 927 OverwriteMode overwrite_mode) |
| 928 : DeferredCode(generator), | 928 : DeferredCode(generator), |
| 929 value_(value), | 929 value_(value), |
| 930 overwrite_mode_(overwrite_mode) { | 930 overwrite_mode_(overwrite_mode) { |
| 931 set_comment("[ DeferredInlinedSmiSub"); | 931 set_comment("[ DeferredInlineSmiSub"); |
| 932 } | 932 } |
| 933 | 933 |
| 934 virtual void Generate(); | 934 virtual void Generate(); |
| 935 | 935 |
| 936 private: | 936 private: |
| 937 Smi* value_; | 937 Smi* value_; |
| 938 OverwriteMode overwrite_mode_; | 938 OverwriteMode overwrite_mode_; |
| 939 }; | 939 }; |
| 940 | 940 |
| 941 | 941 |
| 942 void DeferredInlinedSmiSub::Generate() { | 942 void DeferredInlineSmiSub::Generate() { |
| 943 // Undo the optimistic sub operation and call the shared stub. | 943 // Undo the optimistic sub operation and call the shared stub. |
| 944 Result left(generator()); // Initially left - value_. | 944 Result left(generator()); // Initially left - value_. |
| 945 enter()->Bind(&left); | 945 enter()->Bind(&left); |
| 946 left.ToRegister(); | 946 left.ToRegister(); |
| 947 generator()->frame()->Spill(left.reg()); | 947 generator()->frame()->Spill(left.reg()); |
| 948 __ add(Operand(left.reg()), Immediate(value_)); | 948 __ add(Operand(left.reg()), Immediate(value_)); |
| 949 generator()->frame()->Push(&left); | 949 generator()->frame()->Push(&left); |
| 950 generator()->frame()->Push(value_); | 950 generator()->frame()->Push(value_); |
| 951 GenericBinaryOpStub igostub(Token::SUB, overwrite_mode_, SMI_CODE_INLINED); | 951 GenericBinaryOpStub igostub(Token::SUB, overwrite_mode_, SMI_CODE_INLINED); |
| 952 Result answer = generator()->frame()->CallStub(&igostub, 2); | 952 Result answer = generator()->frame()->CallStub(&igostub, 2); |
| 953 exit()->Jump(&answer); | 953 exit()->Jump(&answer); |
| 954 } | 954 } |
| 955 | 955 |
| 956 | 956 |
| 957 class DeferredInlinedSmiSubReversed: public DeferredCode { | 957 class DeferredInlineSmiSubReversed: public DeferredCode { |
| 958 public: | 958 public: |
| 959 DeferredInlinedSmiSubReversed(CodeGenerator* generator, | 959 DeferredInlineSmiSubReversed(CodeGenerator* generator, |
| 960 Smi* value, | 960 Smi* value, |
| 961 OverwriteMode overwrite_mode) | 961 OverwriteMode overwrite_mode) |
| 962 : DeferredCode(generator), | 962 : DeferredCode(generator), |
| 963 value_(value), | 963 value_(value), |
| 964 overwrite_mode_(overwrite_mode) { | 964 overwrite_mode_(overwrite_mode) { |
| 965 set_comment("[ DeferredInlinedSmiSubReversed"); | 965 set_comment("[ DeferredInlineSmiSubReversed"); |
| 966 } | 966 } |
| 967 | 967 |
| 968 virtual void Generate(); | 968 virtual void Generate(); |
| 969 | 969 |
| 970 private: | 970 private: |
| 971 Smi* value_; | 971 Smi* value_; |
| 972 OverwriteMode overwrite_mode_; | 972 OverwriteMode overwrite_mode_; |
| 973 }; | 973 }; |
| 974 | 974 |
| 975 | 975 |
| 976 void DeferredInlinedSmiSubReversed::Generate() { | 976 void DeferredInlineSmiSubReversed::Generate() { |
| 977 // Call the shared stub. | 977 // Call the shared stub. |
| 978 Result right(generator()); | 978 Result right(generator()); |
| 979 enter()->Bind(&right); | 979 enter()->Bind(&right); |
| 980 generator()->frame()->Push(value_); | 980 generator()->frame()->Push(value_); |
| 981 generator()->frame()->Push(&right); | 981 generator()->frame()->Push(&right); |
| 982 GenericBinaryOpStub igostub(Token::SUB, overwrite_mode_, SMI_CODE_INLINED); | 982 GenericBinaryOpStub igostub(Token::SUB, overwrite_mode_, SMI_CODE_INLINED); |
| 983 Result answer = generator()->frame()->CallStub(&igostub, 2); | 983 Result answer = generator()->frame()->CallStub(&igostub, 2); |
| 984 exit()->Jump(&answer); | 984 exit()->Jump(&answer); |
| 985 } | 985 } |
| 986 | 986 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1002 | 1002 |
| 1003 // Get the literal value. | 1003 // Get the literal value. |
| 1004 Smi* smi_value = Smi::cast(*value); | 1004 Smi* smi_value = Smi::cast(*value); |
| 1005 int int_value = smi_value->value(); | 1005 int int_value = smi_value->value(); |
| 1006 ASSERT(is_intn(int_value, kMaxSmiInlinedBits)); | 1006 ASSERT(is_intn(int_value, kMaxSmiInlinedBits)); |
| 1007 | 1007 |
| 1008 switch (op) { | 1008 switch (op) { |
| 1009 case Token::ADD: { | 1009 case Token::ADD: { |
| 1010 DeferredCode* deferred = NULL; | 1010 DeferredCode* deferred = NULL; |
| 1011 if (!reversed) { | 1011 if (!reversed) { |
| 1012 deferred = new DeferredInlinedSmiAdd(this, smi_value, overwrite_mode); | 1012 deferred = new DeferredInlineSmiAdd(this, smi_value, overwrite_mode); |
| 1013 } else { | 1013 } else { |
| 1014 deferred = new DeferredInlinedSmiAddReversed(this, smi_value, | 1014 deferred = new DeferredInlineSmiAddReversed(this, smi_value, |
| 1015 overwrite_mode); | 1015 overwrite_mode); |
| 1016 } | 1016 } |
| 1017 Result operand = frame_->Pop(); | 1017 Result operand = frame_->Pop(); |
| 1018 operand.ToRegister(); | 1018 operand.ToRegister(); |
| 1019 frame_->Spill(operand.reg()); | 1019 frame_->Spill(operand.reg()); |
| 1020 __ add(Operand(operand.reg()), Immediate(value)); | 1020 __ add(Operand(operand.reg()), Immediate(value)); |
| 1021 deferred->enter()->Branch(overflow, &operand, not_taken); | 1021 deferred->enter()->Branch(overflow, &operand, not_taken); |
| 1022 __ test(Operand(operand.reg()), Immediate(kSmiTagMask)); | 1022 __ test(Operand(operand.reg()), Immediate(kSmiTagMask)); |
| 1023 deferred->enter()->Branch(not_zero, &operand, not_taken); | 1023 deferred->enter()->Branch(not_zero, &operand, not_taken); |
| 1024 deferred->exit()->Bind(&operand); | 1024 deferred->exit()->Bind(&operand); |
| 1025 frame_->Push(&operand); | 1025 frame_->Push(&operand); |
| 1026 break; | 1026 break; |
| 1027 } | 1027 } |
| 1028 | 1028 |
| 1029 case Token::SUB: { | 1029 case Token::SUB: { |
| 1030 DeferredCode* deferred = NULL; | 1030 DeferredCode* deferred = NULL; |
| 1031 Result operand = frame_->Pop(); | 1031 Result operand = frame_->Pop(); |
| 1032 Result answer(this); // Only allocated a new register if reversed. | 1032 Result answer(this); // Only allocated a new register if reversed. |
| 1033 if (!reversed) { | 1033 if (!reversed) { |
| 1034 operand.ToRegister(); | 1034 operand.ToRegister(); |
| 1035 frame_->Spill(operand.reg()); | 1035 frame_->Spill(operand.reg()); |
| 1036 deferred = new DeferredInlinedSmiSub(this, | 1036 deferred = new DeferredInlineSmiSub(this, |
| 1037 smi_value, | 1037 smi_value, |
| 1038 overwrite_mode); | 1038 overwrite_mode); |
| 1039 __ sub(Operand(operand.reg()), Immediate(value)); | 1039 __ sub(Operand(operand.reg()), Immediate(value)); |
| 1040 answer = operand; | 1040 answer = operand; |
| 1041 } else { | 1041 } else { |
| 1042 answer = allocator()->Allocate(); | 1042 answer = allocator()->Allocate(); |
| 1043 ASSERT(answer.is_valid()); | 1043 ASSERT(answer.is_valid()); |
| 1044 deferred = new DeferredInlinedSmiSubReversed(this, | 1044 deferred = new DeferredInlineSmiSubReversed(this, |
| 1045 smi_value, | 1045 smi_value, |
| 1046 overwrite_mode); | 1046 overwrite_mode); |
| 1047 __ mov(answer.reg(), Immediate(value)); | 1047 __ mov(answer.reg(), Immediate(value)); |
| 1048 if (operand.is_register()) { | 1048 if (operand.is_register()) { |
| 1049 __ sub(answer.reg(), Operand(operand.reg())); | 1049 __ sub(answer.reg(), Operand(operand.reg())); |
| 1050 } else { | 1050 } else { |
| 1051 ASSERT(operand.is_constant()); | 1051 ASSERT(operand.is_constant()); |
| 1052 __ sub(Operand(answer.reg()), Immediate(operand.handle())); | 1052 __ sub(Operand(answer.reg()), Immediate(operand.handle())); |
| 1053 } | 1053 } |
| 1054 } | 1054 } |
| 1055 deferred->enter()->Branch(overflow, &operand, not_taken); | 1055 deferred->enter()->Branch(overflow, &operand, not_taken); |
| 1056 __ test(answer.reg(), Immediate(kSmiTagMask)); | 1056 __ test(answer.reg(), Immediate(kSmiTagMask)); |
| 1057 deferred->enter()->Branch(not_zero, &operand, not_taken); | 1057 deferred->enter()->Branch(not_zero, &operand, not_taken); |
| 1058 operand.Unuse(); | 1058 operand.Unuse(); |
| 1059 deferred->exit()->Bind(&answer); | 1059 deferred->exit()->Bind(&answer); |
| 1060 frame_->Push(&answer); | 1060 frame_->Push(&answer); |
| 1061 break; | 1061 break; |
| 1062 } | 1062 } |
| 1063 | 1063 |
| 1064 case Token::SAR: { | 1064 case Token::SAR: { |
| 1065 if (reversed) { | 1065 if (reversed) { |
| 1066 Result top = frame_->Pop(); | 1066 Result top = frame_->Pop(); |
| 1067 frame_->Push(value); | 1067 frame_->Push(value); |
| 1068 frame_->Push(&top); | 1068 frame_->Push(&top); |
| 1069 GenericBinaryOperation(op, type, overwrite_mode); | 1069 GenericBinaryOperation(op, type, overwrite_mode); |
| 1070 } else { | 1070 } else { |
| 1071 // Only the least significant 5 bits of the shift value are used. | 1071 // Only the least significant 5 bits of the shift value are used. |
| 1072 // In the slow case, this masking is done inside the runtime call. | 1072 // In the slow case, this masking is done inside the runtime call. |
| 1073 int shift_value = int_value & 0x1f; | 1073 int shift_value = int_value & 0x1f; |
| 1074 DeferredCode* deferred = | 1074 DeferredCode* deferred = |
| 1075 new DeferredInlinedSmiOperation(this, Token::SAR, smi_value, | 1075 new DeferredInlineSmiOperation(this, Token::SAR, smi_value, |
| 1076 overwrite_mode); | 1076 overwrite_mode); |
| 1077 Result result = frame_->Pop(); | 1077 Result result = frame_->Pop(); |
| 1078 result.ToRegister(); | 1078 result.ToRegister(); |
| 1079 __ test(result.reg(), Immediate(kSmiTagMask)); | 1079 __ test(result.reg(), Immediate(kSmiTagMask)); |
| 1080 deferred->enter()->Branch(not_zero, &result, not_taken); | 1080 deferred->enter()->Branch(not_zero, &result, not_taken); |
| 1081 frame_->Spill(result.reg()); | 1081 frame_->Spill(result.reg()); |
| 1082 __ sar(result.reg(), shift_value); | 1082 __ sar(result.reg(), shift_value); |
| 1083 __ and_(result.reg(), ~kSmiTagMask); | 1083 __ and_(result.reg(), ~kSmiTagMask); |
| 1084 deferred->exit()->Bind(&result); | 1084 deferred->exit()->Bind(&result); |
| 1085 frame_->Push(&result); | 1085 frame_->Push(&result); |
| 1086 } | 1086 } |
| 1087 break; | 1087 break; |
| 1088 } | 1088 } |
| 1089 | 1089 |
| 1090 case Token::SHR: { | 1090 case Token::SHR: { |
| 1091 if (reversed) { | 1091 if (reversed) { |
| 1092 Result top = frame_->Pop(); | 1092 Result top = frame_->Pop(); |
| 1093 frame_->Push(value); | 1093 frame_->Push(value); |
| 1094 frame_->Push(&top); | 1094 frame_->Push(&top); |
| 1095 GenericBinaryOperation(op, type, overwrite_mode); | 1095 GenericBinaryOperation(op, type, overwrite_mode); |
| 1096 } else { | 1096 } else { |
| 1097 // Only the least significant 5 bits of the shift value are used. | 1097 // Only the least significant 5 bits of the shift value are used. |
| 1098 // In the slow case, this masking is done inside the runtime call. | 1098 // In the slow case, this masking is done inside the runtime call. |
| 1099 int shift_value = int_value & 0x1f; | 1099 int shift_value = int_value & 0x1f; |
| 1100 DeferredCode* deferred = | 1100 DeferredCode* deferred = |
| 1101 new DeferredInlinedSmiOperation(this, Token::SHR, smi_value, | 1101 new DeferredInlineSmiOperation(this, Token::SHR, smi_value, |
| 1102 overwrite_mode); | 1102 overwrite_mode); |
| 1103 Result operand = frame_->Pop(); | 1103 Result operand = frame_->Pop(); |
| 1104 operand.ToRegister(); | 1104 operand.ToRegister(); |
| 1105 __ test(operand.reg(), Immediate(kSmiTagMask)); | 1105 __ test(operand.reg(), Immediate(kSmiTagMask)); |
| 1106 deferred->enter()->Branch(not_zero, &operand, not_taken); | 1106 deferred->enter()->Branch(not_zero, &operand, not_taken); |
| 1107 Result answer = allocator()->Allocate(); | 1107 Result answer = allocator()->Allocate(); |
| 1108 ASSERT(answer.is_valid()); | 1108 ASSERT(answer.is_valid()); |
| 1109 __ mov(answer.reg(), Operand(operand.reg())); | 1109 __ mov(answer.reg(), Operand(operand.reg())); |
| 1110 __ sar(answer.reg(), kSmiTagSize); | 1110 __ sar(answer.reg(), kSmiTagSize); |
| 1111 __ shr(answer.reg(), shift_value); | 1111 __ shr(answer.reg(), shift_value); |
| 1112 // A negative Smi shifted right two is in the positive Smi range. | 1112 // A negative Smi shifted right two is in the positive Smi range. |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1128 if (reversed) { | 1128 if (reversed) { |
| 1129 Result top = frame_->Pop(); | 1129 Result top = frame_->Pop(); |
| 1130 frame_->Push(value); | 1130 frame_->Push(value); |
| 1131 frame_->Push(&top); | 1131 frame_->Push(&top); |
| 1132 GenericBinaryOperation(op, type, overwrite_mode); | 1132 GenericBinaryOperation(op, type, overwrite_mode); |
| 1133 } else { | 1133 } else { |
| 1134 // Only the least significant 5 bits of the shift value are used. | 1134 // Only the least significant 5 bits of the shift value are used. |
| 1135 // In the slow case, this masking is done inside the runtime call. | 1135 // In the slow case, this masking is done inside the runtime call. |
| 1136 int shift_value = int_value & 0x1f; | 1136 int shift_value = int_value & 0x1f; |
| 1137 DeferredCode* deferred = | 1137 DeferredCode* deferred = |
| 1138 new DeferredInlinedSmiOperation(this, Token::SHL, smi_value, | 1138 new DeferredInlineSmiOperation(this, Token::SHL, smi_value, |
| 1139 overwrite_mode); | 1139 overwrite_mode); |
| 1140 Result operand = frame_->Pop(); | 1140 Result operand = frame_->Pop(); |
| 1141 operand.ToRegister(); | 1141 operand.ToRegister(); |
| 1142 __ test(operand.reg(), Immediate(kSmiTagMask)); | 1142 __ test(operand.reg(), Immediate(kSmiTagMask)); |
| 1143 deferred->enter()->Branch(not_zero, &operand, not_taken); | 1143 deferred->enter()->Branch(not_zero, &operand, not_taken); |
| 1144 Result answer = allocator()->Allocate(); | 1144 Result answer = allocator()->Allocate(); |
| 1145 ASSERT(answer.is_valid()); | 1145 ASSERT(answer.is_valid()); |
| 1146 __ mov(answer.reg(), Operand(operand.reg())); | 1146 __ mov(answer.reg(), Operand(operand.reg())); |
| 1147 ASSERT(kSmiTag == 0); // adjust code if not the case | 1147 ASSERT(kSmiTag == 0); // adjust code if not the case |
| 1148 // We do no shifts, only the Smi conversion, if shift_value is 1. | 1148 // We do no shifts, only the Smi conversion, if shift_value is 1. |
| 1149 if (shift_value == 0) { | 1149 if (shift_value == 0) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1160 frame_->Push(&answer); | 1160 frame_->Push(&answer); |
| 1161 } | 1161 } |
| 1162 break; | 1162 break; |
| 1163 } | 1163 } |
| 1164 | 1164 |
| 1165 case Token::BIT_OR: | 1165 case Token::BIT_OR: |
| 1166 case Token::BIT_XOR: | 1166 case Token::BIT_XOR: |
| 1167 case Token::BIT_AND: { | 1167 case Token::BIT_AND: { |
| 1168 DeferredCode* deferred = NULL; | 1168 DeferredCode* deferred = NULL; |
| 1169 if (!reversed) { | 1169 if (!reversed) { |
| 1170 deferred = new DeferredInlinedSmiOperation(this, op, smi_value, | 1170 deferred = new DeferredInlineSmiOperation(this, op, smi_value, |
| 1171 overwrite_mode); | 1171 overwrite_mode); |
| 1172 } else { | 1172 } else { |
| 1173 deferred = new DeferredInlinedSmiOperationReversed(this, op, smi_value, | 1173 deferred = new DeferredInlineSmiOperationReversed(this, op, smi_value, |
| 1174 overwrite_mode); | 1174 overwrite_mode); |
| 1175 } | 1175 } |
| 1176 Result operand = frame_->Pop(); | 1176 Result operand = frame_->Pop(); |
| 1177 operand.ToRegister(); | 1177 operand.ToRegister(); |
| 1178 __ test(operand.reg(), Immediate(kSmiTagMask)); | 1178 __ test(operand.reg(), Immediate(kSmiTagMask)); |
| 1179 deferred->enter()->Branch(not_zero, &operand, not_taken); | 1179 deferred->enter()->Branch(not_zero, &operand, not_taken); |
| 1180 frame_->Spill(operand.reg()); | 1180 frame_->Spill(operand.reg()); |
| 1181 if (op == Token::BIT_AND) { | 1181 if (op == Token::BIT_AND) { |
| 1182 __ and_(Operand(operand.reg()), Immediate(value)); | 1182 __ and_(Operand(operand.reg()), Immediate(value)); |
| 1183 } else if (op == Token::BIT_XOR) { | 1183 } else if (op == Token::BIT_XOR) { |
| 1184 __ xor_(Operand(operand.reg()), Immediate(value)); | 1184 __ xor_(Operand(operand.reg()), Immediate(value)); |
| (...skipping 964 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2149 } | 2149 } |
| 2150 if (node->break_target()->is_linked()) { | 2150 if (node->break_target()->is_linked()) { |
| 2151 node->break_target()->Bind(); | 2151 node->break_target()->Bind(); |
| 2152 } | 2152 } |
| 2153 | 2153 |
| 2154 } else { | 2154 } else { |
| 2155 ASSERT(info == DONT_KNOW); | 2155 ASSERT(info == DONT_KNOW); |
| 2156 // We have to compile the test expression if it can be reached by | 2156 // We have to compile the test expression if it can be reached by |
| 2157 // control flow falling out of the body or via continue. | 2157 // control flow falling out of the body or via continue. |
| 2158 if (node->continue_target()->is_linked()) { | 2158 if (node->continue_target()->is_linked()) { |
| 2159 node->continue_target()->Bind(); | 2159 node->continue_target()->Bind(); |
| 2160 } | 2160 } |
| 2161 if (has_valid_frame()) { | 2161 if (has_valid_frame()) { |
| 2162 ControlDestination dest(&body, node->break_target(), false); | 2162 ControlDestination dest(&body, node->break_target(), false); |
| 2163 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true); | 2163 LoadCondition(node->cond(), NOT_INSIDE_TYPEOF, &dest, true); |
| 2164 } | 2164 } |
| 2165 if (node->break_target()->is_linked()) { | 2165 if (node->break_target()->is_linked()) { |
| 2166 node->break_target()->Bind(); | 2166 node->break_target()->Bind(); |
| 2167 } | 2167 } |
| 2168 } | 2168 } |
| 2169 break; | 2169 break; |
| (...skipping 1418 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3588 ASSERT(function.is_valid()); | 3588 ASSERT(function.is_valid()); |
| 3589 | 3589 |
| 3590 // Call the construct call builtin that handles allocation and | 3590 // Call the construct call builtin that handles allocation and |
| 3591 // constructor invocation. | 3591 // constructor invocation. |
| 3592 CodeForSourcePosition(node->position()); | 3592 CodeForSourcePosition(node->position()); |
| 3593 Handle<Code> ic(Builtins::builtin(Builtins::JSConstructCall)); | 3593 Handle<Code> ic(Builtins::builtin(Builtins::JSConstructCall)); |
| 3594 Result result = frame_->CallCodeObject(ic, | 3594 Result result = frame_->CallCodeObject(ic, |
| 3595 RelocInfo::CONSTRUCT_CALL, | 3595 RelocInfo::CONSTRUCT_CALL, |
| 3596 &num_args, | 3596 &num_args, |
| 3597 &function, | 3597 &function, |
| 3598 args->length() + 1); | 3598 arg_count + 1); |
| 3599 | 3599 |
| 3600 // Replace the function on the stack with the result. | 3600 // Replace the function on the stack with the result. |
| 3601 frame_->SetElementAt(0, &result); | 3601 frame_->SetElementAt(0, &result); |
| 3602 } | 3602 } |
| 3603 | 3603 |
| 3604 | 3604 |
| 3605 void CodeGenerator::VisitCallEval(CallEval* node) { | 3605 void CodeGenerator::VisitCallEval(CallEval* node) { |
| 3606 Comment cmnt(masm_, "[ CallEval"); | 3606 Comment cmnt(masm_, "[ CallEval"); |
| 3607 | 3607 |
| 3608 // In a call to eval, we first call %ResolvePossiblyDirectEval to resolve | 3608 // In a call to eval, we first call %ResolvePossiblyDirectEval to resolve |
| (...skipping 2934 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6543 | 6543 |
| 6544 // Slow-case: Go through the JavaScript implementation. | 6544 // Slow-case: Go through the JavaScript implementation. |
| 6545 __ bind(&slow); | 6545 __ bind(&slow); |
| 6546 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); | 6546 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); |
| 6547 } | 6547 } |
| 6548 | 6548 |
| 6549 | 6549 |
| 6550 #undef __ | 6550 #undef __ |
| 6551 | 6551 |
| 6552 } } // namespace v8::internal | 6552 } } // namespace v8::internal |
| OLD | NEW |