| 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 784 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 795 Result answer = frame_->CallStub(&stub, 2); | 795 Result answer = frame_->CallStub(&stub, 2); |
| 796 frame_->Push(&answer); | 796 frame_->Push(&answer); |
| 797 } | 797 } |
| 798 } | 798 } |
| 799 | 799 |
| 800 | 800 |
| 801 class DeferredInlinedSmiOperation: public DeferredCode { | 801 class DeferredInlinedSmiOperation: public DeferredCode { |
| 802 public: | 802 public: |
| 803 DeferredInlinedSmiOperation(CodeGenerator* generator, | 803 DeferredInlinedSmiOperation(CodeGenerator* generator, |
| 804 Token::Value op, | 804 Token::Value op, |
| 805 int value, | 805 Smi* value, |
| 806 OverwriteMode overwrite_mode) | 806 OverwriteMode overwrite_mode) |
| 807 : DeferredCode(generator), | 807 : DeferredCode(generator), |
| 808 op_(op), | 808 op_(op), |
| 809 value_(value), | 809 value_(value), |
| 810 overwrite_mode_(overwrite_mode) { | 810 overwrite_mode_(overwrite_mode) { |
| 811 set_comment("[ DeferredInlinedSmiOperation"); | 811 set_comment("[ DeferredInlinedSmiOperation"); |
| 812 } | 812 } |
| 813 | 813 |
| 814 virtual void Generate(); | 814 virtual void Generate(); |
| 815 | 815 |
| 816 private: | 816 private: |
| 817 Token::Value op_; | 817 Token::Value op_; |
| 818 int value_; | 818 Smi* value_; |
| 819 OverwriteMode overwrite_mode_; | 819 OverwriteMode overwrite_mode_; |
| 820 }; | 820 }; |
| 821 | 821 |
| 822 | 822 |
| 823 void DeferredInlinedSmiOperation::Generate() { | 823 void DeferredInlinedSmiOperation::Generate() { |
| 824 // The argument is passed in eax. | 824 Result left(generator()); |
| 825 enter()->Bind(); | 825 enter()->Bind(&left); |
| 826 VirtualFrame::SpilledScope spilled_scope(generator()); | 826 generator()->frame()->Push(&left); |
| 827 generator()->frame()->EmitPush(eax); | 827 generator()->frame()->Push(value_); |
| 828 generator()->frame()->EmitPush(Immediate(Smi::FromInt(value_))); | |
| 829 GenericBinaryOpStub igostub(op_, overwrite_mode_, SMI_CODE_INLINED); | 828 GenericBinaryOpStub igostub(op_, overwrite_mode_, SMI_CODE_INLINED); |
| 830 generator()->frame()->CallStub(&igostub, 2); | 829 Result answer = generator()->frame()->CallStub(&igostub, 2); |
| 831 // The result is returned in eax. | 830 exit()->Jump(&answer); |
| 832 exit()->Jump(); | |
| 833 } | 831 } |
| 834 | 832 |
| 835 | 833 |
| 836 class DeferredInlinedSmiOperationReversed: public DeferredCode { | 834 class DeferredInlinedSmiOperationReversed: public DeferredCode { |
| 837 public: | 835 public: |
| 838 DeferredInlinedSmiOperationReversed(CodeGenerator* generator, | 836 DeferredInlinedSmiOperationReversed(CodeGenerator* generator, |
| 839 Token::Value op, | 837 Token::Value op, |
| 840 int value, | 838 Smi* value, |
| 841 OverwriteMode overwrite_mode) | 839 OverwriteMode overwrite_mode) |
| 842 : DeferredCode(generator), | 840 : DeferredCode(generator), |
| 843 op_(op), | 841 op_(op), |
| 844 value_(value), | 842 value_(value), |
| 845 overwrite_mode_(overwrite_mode) { | 843 overwrite_mode_(overwrite_mode) { |
| 846 set_comment("[ DeferredInlinedSmiOperationReversed"); | 844 set_comment("[ DeferredInlinedSmiOperationReversed"); |
| 847 } | 845 } |
| 848 | 846 |
| 849 virtual void Generate(); | 847 virtual void Generate(); |
| 850 | 848 |
| 851 private: | 849 private: |
| 852 Token::Value op_; | 850 Token::Value op_; |
| 853 int value_; | 851 Smi* value_; |
| 854 OverwriteMode overwrite_mode_; | 852 OverwriteMode overwrite_mode_; |
| 855 }; | 853 }; |
| 856 | 854 |
| 857 | 855 |
| 858 void DeferredInlinedSmiOperationReversed::Generate() { | 856 void DeferredInlinedSmiOperationReversed::Generate() { |
| 859 // The argument is passed in eax. | 857 Result right(generator()); |
| 860 enter()->Bind(); | 858 enter()->Bind(&right); |
| 861 VirtualFrame::SpilledScope spilled_scope(generator()); | 859 generator()->frame()->Push(value_); |
| 862 generator()->frame()->EmitPush(Immediate(Smi::FromInt(value_))); | 860 generator()->frame()->Push(&right); |
| 863 generator()->frame()->EmitPush(eax); | |
| 864 GenericBinaryOpStub igostub(op_, overwrite_mode_, SMI_CODE_INLINED); | 861 GenericBinaryOpStub igostub(op_, overwrite_mode_, SMI_CODE_INLINED); |
| 865 generator()->frame()->CallStub(&igostub, 2); | 862 Result answer = generator()->frame()->CallStub(&igostub, 2); |
| 866 // The result is returned in eax. | 863 exit()->Jump(&answer); |
| 867 exit()->Jump(); | |
| 868 } | 864 } |
| 869 | 865 |
| 870 | 866 |
| 871 class DeferredInlinedSmiAdd: public DeferredCode { | 867 class DeferredInlinedSmiAdd: public DeferredCode { |
| 872 public: | 868 public: |
| 873 DeferredInlinedSmiAdd(CodeGenerator* generator, | 869 DeferredInlinedSmiAdd(CodeGenerator* generator, |
| 874 Smi* value, | 870 Smi* value, |
| 875 OverwriteMode overwrite_mode) | 871 OverwriteMode overwrite_mode) |
| 876 : DeferredCode(generator), | 872 : DeferredCode(generator), |
| 877 value_(value), | 873 value_(value), |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1077 break; | 1073 break; |
| 1078 } | 1074 } |
| 1079 | 1075 |
| 1080 case Token::SAR: { | 1076 case Token::SAR: { |
| 1081 if (reversed) { | 1077 if (reversed) { |
| 1082 Result top = frame_->Pop(); | 1078 Result top = frame_->Pop(); |
| 1083 frame_->Push(value); | 1079 frame_->Push(value); |
| 1084 frame_->Push(&top); | 1080 frame_->Push(&top); |
| 1085 GenericBinaryOperation(op, type, overwrite_mode); | 1081 GenericBinaryOperation(op, type, overwrite_mode); |
| 1086 } else { | 1082 } else { |
| 1087 VirtualFrame::SpilledScope spilled_scope(this); | 1083 // Only the least significant 5 bits of the shift value are used. |
| 1088 int shift_value = int_value & 0x1f; // only least significant 5 bits | 1084 // In the slow case, this masking is done inside the runtime call. |
| 1085 int shift_value = int_value & 0x1f; |
| 1089 DeferredCode* deferred = | 1086 DeferredCode* deferred = |
| 1090 new DeferredInlinedSmiOperation(this, Token::SAR, shift_value, | 1087 new DeferredInlinedSmiOperation(this, Token::SAR, smi_value, |
| 1091 overwrite_mode); | 1088 overwrite_mode); |
| 1092 frame_->EmitPop(eax); | 1089 Result result = frame_->Pop(); |
| 1093 __ test(eax, Immediate(kSmiTagMask)); | 1090 result.ToRegister(); |
| 1094 deferred->enter()->Branch(not_zero, not_taken); | 1091 __ test(result.reg(), Immediate(kSmiTagMask)); |
| 1095 __ sar(eax, shift_value); | 1092 deferred->enter()->Branch(not_zero, &result, not_taken); |
| 1096 __ and_(eax, ~kSmiTagMask); | 1093 frame_->Spill(result.reg()); |
| 1097 deferred->exit()->Bind(); | 1094 __ sar(result.reg(), shift_value); |
| 1098 frame_->EmitPush(eax); | 1095 __ and_(result.reg(), ~kSmiTagMask); |
| 1096 deferred->exit()->Bind(&result); |
| 1097 frame_->Push(&result); |
| 1099 } | 1098 } |
| 1100 break; | 1099 break; |
| 1101 } | 1100 } |
| 1102 | 1101 |
| 1103 case Token::SHR: { | 1102 case Token::SHR: { |
| 1104 if (reversed) { | 1103 if (reversed) { |
| 1105 Result top = frame_->Pop(); | 1104 Result top = frame_->Pop(); |
| 1106 frame_->Push(value); | 1105 frame_->Push(value); |
| 1107 frame_->Push(&top); | 1106 frame_->Push(&top); |
| 1108 GenericBinaryOperation(op, type, overwrite_mode); | 1107 GenericBinaryOperation(op, type, overwrite_mode); |
| 1109 } else { | 1108 } else { |
| 1110 VirtualFrame::SpilledScope spilled_scope(this); | 1109 // Only the least significant 5 bits of the shift value are used. |
| 1111 int shift_value = int_value & 0x1f; // only least significant 5 bits | 1110 // In the slow case, this masking is done inside the runtime call. |
| 1111 int shift_value = int_value & 0x1f; |
| 1112 DeferredCode* deferred = | 1112 DeferredCode* deferred = |
| 1113 new DeferredInlinedSmiOperation(this, Token::SHR, shift_value, | 1113 new DeferredInlinedSmiOperation(this, Token::SHR, smi_value, |
| 1114 overwrite_mode); | 1114 overwrite_mode); |
| 1115 frame_->EmitPop(eax); | 1115 Result operand = frame_->Pop(); |
| 1116 __ test(eax, Immediate(kSmiTagMask)); | 1116 operand.ToRegister(); |
| 1117 __ mov(ebx, Operand(eax)); | 1117 __ test(operand.reg(), Immediate(kSmiTagMask)); |
| 1118 deferred->enter()->Branch(not_zero, not_taken); | 1118 deferred->enter()->Branch(not_zero, &operand, not_taken); |
| 1119 __ sar(ebx, kSmiTagSize); | 1119 Result answer = allocator()->Allocate(); |
| 1120 __ shr(ebx, shift_value); | 1120 ASSERT(answer.is_valid()); |
| 1121 __ test(ebx, Immediate(0xc0000000)); | 1121 __ mov(answer.reg(), Operand(operand.reg())); |
| 1122 deferred->enter()->Branch(not_zero, not_taken); | 1122 __ sar(answer.reg(), kSmiTagSize); |
| 1123 // tag result and store it in TOS (eax) | 1123 __ shr(answer.reg(), shift_value); |
| 1124 ASSERT(kSmiTagSize == times_2); // adjust code if not the case | 1124 // A negative Smi shifted right two is in the positive Smi range. |
| 1125 __ lea(eax, Operand(ebx, ebx, times_1, kSmiTag)); | 1125 if (shift_value < 2) { |
| 1126 deferred->exit()->Bind(); | 1126 __ test(answer.reg(), Immediate(0xc0000000)); |
| 1127 frame_->EmitPush(eax); | 1127 deferred->enter()->Branch(not_zero, &operand, not_taken); |
| 1128 } |
| 1129 operand.Unuse(); |
| 1130 ASSERT(kSmiTagSize == times_2); // Adjust the code if not true. |
| 1131 __ lea(answer.reg(), |
| 1132 Operand(answer.reg(), answer.reg(), times_1, kSmiTag)); |
| 1133 deferred->exit()->Bind(&answer); |
| 1134 frame_->Push(&answer); |
| 1128 } | 1135 } |
| 1129 break; | 1136 break; |
| 1130 } | 1137 } |
| 1131 | 1138 |
| 1132 case Token::SHL: { | 1139 case Token::SHL: { |
| 1133 VirtualFrame::SpilledScope spilled_scope(this); | |
| 1134 if (reversed) { | 1140 if (reversed) { |
| 1135 frame_->EmitPop(eax); | 1141 Result top = frame_->Pop(); |
| 1136 frame_->EmitPush(Immediate(value)); | 1142 frame_->Push(value); |
| 1137 frame_->EmitPush(eax); | 1143 frame_->Push(&top); |
| 1138 GenericBinaryOperation(op, type, overwrite_mode); | 1144 GenericBinaryOperation(op, type, overwrite_mode); |
| 1139 } else { | 1145 } else { |
| 1140 int shift_value = int_value & 0x1f; // only least significant 5 bits | 1146 // Only the least significant 5 bits of the shift value are used. |
| 1147 // In the slow case, this masking is done inside the runtime call. |
| 1148 int shift_value = int_value & 0x1f; |
| 1141 DeferredCode* deferred = | 1149 DeferredCode* deferred = |
| 1142 new DeferredInlinedSmiOperation(this, Token::SHL, shift_value, | 1150 new DeferredInlinedSmiOperation(this, Token::SHL, smi_value, |
| 1143 overwrite_mode); | 1151 overwrite_mode); |
| 1144 frame_->EmitPop(eax); | 1152 Result operand = frame_->Pop(); |
| 1145 __ test(eax, Immediate(kSmiTagMask)); | 1153 operand.ToRegister(); |
| 1146 __ mov(ebx, Operand(eax)); | 1154 __ test(operand.reg(), Immediate(kSmiTagMask)); |
| 1147 deferred->enter()->Branch(not_zero, not_taken); | 1155 deferred->enter()->Branch(not_zero, &operand, not_taken); |
| 1148 __ sar(ebx, kSmiTagSize); | 1156 Result answer = allocator()->Allocate(); |
| 1149 __ shl(ebx, shift_value); | 1157 ASSERT(answer.is_valid()); |
| 1150 __ lea(ecx, Operand(ebx, 0x40000000)); | 1158 __ mov(answer.reg(), Operand(operand.reg())); |
| 1151 __ test(ecx, Immediate(0x80000000)); | 1159 ASSERT(kSmiTag == 0); // adjust code if not the case |
| 1152 deferred->enter()->Branch(not_zero, not_taken); | 1160 if (shift_value == 0) { |
| 1153 // tag result and store it in TOS (eax) | 1161 __ sar(answer.reg(), kSmiTagSize); |
| 1162 } else if (shift_value > 1) { |
| 1163 __ shl(answer.reg(), shift_value - 1); |
| 1164 } // We do no shifts, only the Smi conversion, if shift_value is 1. |
| 1165 // Convert int result to Smi, checking that it is in int range. |
| 1154 ASSERT(kSmiTagSize == times_2); // adjust code if not the case | 1166 ASSERT(kSmiTagSize == times_2); // adjust code if not the case |
| 1155 __ lea(eax, Operand(ebx, ebx, times_1, kSmiTag)); | 1167 __ add(answer.reg(), Operand(answer.reg())); |
| 1156 deferred->exit()->Bind(); | 1168 deferred->enter()->Branch(overflow, &operand, not_taken); |
| 1157 frame_->EmitPush(eax); | 1169 deferred->exit()->Bind(&answer); |
| 1170 frame_->Push(&answer); |
| 1158 } | 1171 } |
| 1159 break; | 1172 break; |
| 1160 } | 1173 } |
| 1161 | 1174 |
| 1162 case Token::BIT_OR: | 1175 case Token::BIT_OR: |
| 1163 case Token::BIT_XOR: | 1176 case Token::BIT_XOR: |
| 1164 case Token::BIT_AND: { | 1177 case Token::BIT_AND: { |
| 1165 VirtualFrame::SpilledScope spilled_scope(this); | |
| 1166 DeferredCode* deferred = NULL; | 1178 DeferredCode* deferred = NULL; |
| 1167 if (!reversed) { | 1179 if (!reversed) { |
| 1168 deferred = new DeferredInlinedSmiOperation(this, op, int_value, | 1180 deferred = new DeferredInlinedSmiOperation(this, op, smi_value, |
| 1169 overwrite_mode); | 1181 overwrite_mode); |
| 1170 } else { | 1182 } else { |
| 1171 deferred = new DeferredInlinedSmiOperationReversed(this, op, int_value, | 1183 deferred = new DeferredInlinedSmiOperationReversed(this, op, smi_value, |
| 1172 overwrite_mode); | 1184 overwrite_mode); |
| 1173 } | 1185 } |
| 1174 frame_->EmitPop(eax); | 1186 Result operand = frame_->Pop(); |
| 1175 __ test(eax, Immediate(kSmiTagMask)); | 1187 operand.ToRegister(); |
| 1176 deferred->enter()->Branch(not_zero, not_taken); | 1188 __ test(operand.reg(), Immediate(kSmiTagMask)); |
| 1189 deferred->enter()->Branch(not_zero, &operand, not_taken); |
| 1190 frame_->Spill(operand.reg()); |
| 1177 if (op == Token::BIT_AND) { | 1191 if (op == Token::BIT_AND) { |
| 1178 __ and_(Operand(eax), Immediate(value)); | 1192 __ and_(Operand(operand.reg()), Immediate(value)); |
| 1179 } else if (op == Token::BIT_XOR) { | 1193 } else if (op == Token::BIT_XOR) { |
| 1180 __ xor_(Operand(eax), Immediate(value)); | 1194 __ xor_(Operand(operand.reg()), Immediate(value)); |
| 1181 } else { | 1195 } else { |
| 1182 ASSERT(op == Token::BIT_OR); | 1196 ASSERT(op == Token::BIT_OR); |
| 1183 __ or_(Operand(eax), Immediate(value)); | 1197 __ or_(Operand(operand.reg()), Immediate(value)); |
| 1184 } | 1198 } |
| 1185 deferred->exit()->Bind(); | 1199 deferred->exit()->Bind(&operand); |
| 1186 frame_->EmitPush(eax); | 1200 frame_->Push(&operand); |
| 1187 break; | 1201 break; |
| 1188 } | 1202 } |
| 1189 | 1203 |
| 1190 default: { | 1204 default: { |
| 1191 if (!reversed) { | 1205 if (!reversed) { |
| 1192 frame_->Push(value); | 1206 frame_->Push(value); |
| 1193 } else { | 1207 } else { |
| 1194 Result top = frame_->Pop(); | 1208 Result top = frame_->Pop(); |
| 1195 frame_->Push(value); | 1209 frame_->Push(value); |
| 1196 frame_->Push(&top); | 1210 frame_->Push(&top); |
| (...skipping 4990 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6187 | 6201 |
| 6188 // Slow-case: Go through the JavaScript implementation. | 6202 // Slow-case: Go through the JavaScript implementation. |
| 6189 __ bind(&slow); | 6203 __ bind(&slow); |
| 6190 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); | 6204 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); |
| 6191 } | 6205 } |
| 6192 | 6206 |
| 6193 | 6207 |
| 6194 #undef __ | 6208 #undef __ |
| 6195 | 6209 |
| 6196 } } // namespace v8::internal | 6210 } } // namespace v8::internal |
| OLD | NEW |