| 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 714 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 725 return OpBits::encode(op_) | | 725 return OpBits::encode(op_) | |
| 726 ModeBits::encode(mode_) | | 726 ModeBits::encode(mode_) | |
| 727 FlagBits::encode(flags_); | 727 FlagBits::encode(flags_); |
| 728 } | 728 } |
| 729 void Generate(MacroAssembler* masm); | 729 void Generate(MacroAssembler* masm); |
| 730 }; | 730 }; |
| 731 | 731 |
| 732 | 732 |
| 733 const char* GenericBinaryOpStub::GetName() { | 733 const char* GenericBinaryOpStub::GetName() { |
| 734 switch (op_) { | 734 switch (op_) { |
| 735 case Token::ADD: return "GenericBinaryOpStub_ADD"; | 735 case Token::ADD: return "GenericBinaryOpStub_ADD"; |
| 736 case Token::SUB: return "GenericBinaryOpStub_SUB"; | 736 case Token::SUB: return "GenericBinaryOpStub_SUB"; |
| 737 case Token::MUL: return "GenericBinaryOpStub_MUL"; | 737 case Token::MUL: return "GenericBinaryOpStub_MUL"; |
| 738 case Token::DIV: return "GenericBinaryOpStub_DIV"; | 738 case Token::DIV: return "GenericBinaryOpStub_DIV"; |
| 739 case Token::BIT_OR: return "GenericBinaryOpStub_BIT_OR"; | 739 case Token::BIT_OR: return "GenericBinaryOpStub_BIT_OR"; |
| 740 case Token::BIT_AND: return "GenericBinaryOpStub_BIT_AND"; | 740 case Token::BIT_AND: return "GenericBinaryOpStub_BIT_AND"; |
| 741 case Token::BIT_XOR: return "GenericBinaryOpStub_BIT_XOR"; | 741 case Token::BIT_XOR: return "GenericBinaryOpStub_BIT_XOR"; |
| 742 case Token::SAR: return "GenericBinaryOpStub_SAR"; | 742 case Token::SAR: return "GenericBinaryOpStub_SAR"; |
| 743 case Token::SHL: return "GenericBinaryOpStub_SHL"; | 743 case Token::SHL: return "GenericBinaryOpStub_SHL"; |
| 744 case Token::SHR: return "GenericBinaryOpStub_SHR"; | 744 case Token::SHR: return "GenericBinaryOpStub_SHR"; |
| 745 default: return "GenericBinaryOpStub"; | 745 default: return "GenericBinaryOpStub"; |
| 746 } | 746 } |
| 747 } | 747 } |
| 748 | 748 |
| 749 | 749 |
| 750 class DeferredInlineBinaryOperation: public DeferredCode { | 750 class DeferredInlineBinaryOperation: public DeferredCode { |
| 751 public: | 751 public: |
| 752 DeferredInlineBinaryOperation(CodeGenerator* generator, | 752 DeferredInlineBinaryOperation(CodeGenerator* generator, |
| 753 Token::Value op, | 753 Token::Value op, |
| 754 OverwriteMode mode, | 754 OverwriteMode mode, |
| 755 GenericBinaryFlags flags) | 755 GenericBinaryFlags flags) |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 829 GenericBinaryOpStub stub(op, overwrite_mode, flags); | 829 GenericBinaryOpStub stub(op, overwrite_mode, flags); |
| 830 Result answer = frame_->CallStub(&stub, 2); | 830 Result answer = frame_->CallStub(&stub, 2); |
| 831 frame_->Push(&answer); | 831 frame_->Push(&answer); |
| 832 } | 832 } |
| 833 } | 833 } |
| 834 | 834 |
| 835 | 835 |
| 836 class DeferredInlineSmiOperation: public DeferredCode { | 836 class DeferredInlineSmiOperation: public DeferredCode { |
| 837 public: | 837 public: |
| 838 DeferredInlineSmiOperation(CodeGenerator* generator, | 838 DeferredInlineSmiOperation(CodeGenerator* generator, |
| 839 Token::Value op, | 839 Token::Value op, |
| 840 Smi* value, | 840 Smi* value, |
| 841 OverwriteMode overwrite_mode) | 841 OverwriteMode overwrite_mode) |
| 842 : DeferredCode(generator), | 842 : DeferredCode(generator), |
| 843 op_(op), | 843 op_(op), |
| 844 value_(value), | 844 value_(value), |
| 845 overwrite_mode_(overwrite_mode) { | 845 overwrite_mode_(overwrite_mode) { |
| 846 set_comment("[ DeferredInlineSmiOperation"); | 846 set_comment("[ DeferredInlineSmiOperation"); |
| 847 } | 847 } |
| 848 | 848 |
| 849 virtual void Generate(); | 849 virtual void Generate(); |
| 850 | 850 |
| 851 private: | 851 private: |
| (...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1112 if (reversed) { | 1112 if (reversed) { |
| 1113 Result top = frame_->Pop(); | 1113 Result top = frame_->Pop(); |
| 1114 frame_->Push(value); | 1114 frame_->Push(value); |
| 1115 frame_->Push(&top); | 1115 frame_->Push(&top); |
| 1116 GenericBinaryOperation(op, type, overwrite_mode); | 1116 GenericBinaryOperation(op, type, overwrite_mode); |
| 1117 } else { | 1117 } else { |
| 1118 // Only the least significant 5 bits of the shift value are used. | 1118 // Only the least significant 5 bits of the shift value are used. |
| 1119 // In the slow case, this masking is done inside the runtime call. | 1119 // In the slow case, this masking is done inside the runtime call. |
| 1120 int shift_value = int_value & 0x1f; | 1120 int shift_value = int_value & 0x1f; |
| 1121 DeferredCode* deferred = | 1121 DeferredCode* deferred = |
| 1122 new DeferredInlineSmiOperation(this, Token::SAR, smi_value, | 1122 new DeferredInlineSmiOperation(this, Token::SAR, smi_value, |
| 1123 overwrite_mode); | 1123 overwrite_mode); |
| 1124 Result result = frame_->Pop(); | 1124 Result result = frame_->Pop(); |
| 1125 result.ToRegister(); | 1125 result.ToRegister(); |
| 1126 __ test(result.reg(), Immediate(kSmiTagMask)); | 1126 __ test(result.reg(), Immediate(kSmiTagMask)); |
| 1127 deferred->enter()->Branch(not_zero, &result, not_taken); | 1127 deferred->enter()->Branch(not_zero, &result, not_taken); |
| 1128 frame_->Spill(result.reg()); | 1128 frame_->Spill(result.reg()); |
| 1129 __ sar(result.reg(), shift_value); | 1129 __ sar(result.reg(), shift_value); |
| 1130 __ and_(result.reg(), ~kSmiTagMask); | 1130 __ and_(result.reg(), ~kSmiTagMask); |
| 1131 deferred->BindExit(&result); | 1131 deferred->BindExit(&result); |
| 1132 frame_->Push(&result); | 1132 frame_->Push(&result); |
| 1133 } | 1133 } |
| 1134 break; | 1134 break; |
| 1135 } | 1135 } |
| 1136 | 1136 |
| 1137 case Token::SHR: { | 1137 case Token::SHR: { |
| 1138 if (reversed) { | 1138 if (reversed) { |
| 1139 Result top = frame_->Pop(); | 1139 Result top = frame_->Pop(); |
| 1140 frame_->Push(value); | 1140 frame_->Push(value); |
| 1141 frame_->Push(&top); | 1141 frame_->Push(&top); |
| 1142 GenericBinaryOperation(op, type, overwrite_mode); | 1142 GenericBinaryOperation(op, type, overwrite_mode); |
| 1143 } else { | 1143 } else { |
| 1144 // Only the least significant 5 bits of the shift value are used. | 1144 // Only the least significant 5 bits of the shift value are used. |
| 1145 // In the slow case, this masking is done inside the runtime call. | 1145 // In the slow case, this masking is done inside the runtime call. |
| 1146 int shift_value = int_value & 0x1f; | 1146 int shift_value = int_value & 0x1f; |
| 1147 DeferredCode* deferred = | 1147 DeferredCode* deferred = |
| 1148 new DeferredInlineSmiOperation(this, Token::SHR, smi_value, | 1148 new DeferredInlineSmiOperation(this, Token::SHR, smi_value, |
| 1149 overwrite_mode); | 1149 overwrite_mode); |
| 1150 Result operand = frame_->Pop(); | 1150 Result operand = frame_->Pop(); |
| 1151 operand.ToRegister(); | 1151 operand.ToRegister(); |
| 1152 __ test(operand.reg(), Immediate(kSmiTagMask)); | 1152 __ test(operand.reg(), Immediate(kSmiTagMask)); |
| 1153 deferred->enter()->Branch(not_zero, &operand, not_taken); | 1153 deferred->enter()->Branch(not_zero, &operand, not_taken); |
| 1154 Result answer = allocator()->Allocate(); | 1154 Result answer = allocator()->Allocate(); |
| 1155 ASSERT(answer.is_valid()); | 1155 ASSERT(answer.is_valid()); |
| 1156 __ mov(answer.reg(), Operand(operand.reg())); | 1156 __ mov(answer.reg(), Operand(operand.reg())); |
| 1157 __ sar(answer.reg(), kSmiTagSize); | 1157 __ sar(answer.reg(), kSmiTagSize); |
| 1158 __ shr(answer.reg(), shift_value); | 1158 __ shr(answer.reg(), shift_value); |
| 1159 // A negative Smi shifted right two is in the positive Smi range. | 1159 // A negative Smi shifted right two is in the positive Smi range. |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1175 if (reversed) { | 1175 if (reversed) { |
| 1176 Result top = frame_->Pop(); | 1176 Result top = frame_->Pop(); |
| 1177 frame_->Push(value); | 1177 frame_->Push(value); |
| 1178 frame_->Push(&top); | 1178 frame_->Push(&top); |
| 1179 GenericBinaryOperation(op, type, overwrite_mode); | 1179 GenericBinaryOperation(op, type, overwrite_mode); |
| 1180 } else { | 1180 } else { |
| 1181 // Only the least significant 5 bits of the shift value are used. | 1181 // Only the least significant 5 bits of the shift value are used. |
| 1182 // In the slow case, this masking is done inside the runtime call. | 1182 // In the slow case, this masking is done inside the runtime call. |
| 1183 int shift_value = int_value & 0x1f; | 1183 int shift_value = int_value & 0x1f; |
| 1184 DeferredCode* deferred = | 1184 DeferredCode* deferred = |
| 1185 new DeferredInlineSmiOperation(this, Token::SHL, smi_value, | 1185 new DeferredInlineSmiOperation(this, Token::SHL, smi_value, |
| 1186 overwrite_mode); | 1186 overwrite_mode); |
| 1187 Result operand = frame_->Pop(); | 1187 Result operand = frame_->Pop(); |
| 1188 operand.ToRegister(); | 1188 operand.ToRegister(); |
| 1189 __ test(operand.reg(), Immediate(kSmiTagMask)); | 1189 __ test(operand.reg(), Immediate(kSmiTagMask)); |
| 1190 deferred->enter()->Branch(not_zero, &operand, not_taken); | 1190 deferred->enter()->Branch(not_zero, &operand, not_taken); |
| 1191 Result answer = allocator()->Allocate(); | 1191 Result answer = allocator()->Allocate(); |
| 1192 ASSERT(answer.is_valid()); | 1192 ASSERT(answer.is_valid()); |
| 1193 __ mov(answer.reg(), Operand(operand.reg())); | 1193 __ mov(answer.reg(), Operand(operand.reg())); |
| 1194 ASSERT(kSmiTag == 0); // adjust code if not the case | 1194 ASSERT(kSmiTag == 0); // adjust code if not the case |
| 1195 // We do no shifts, only the Smi conversion, if shift_value is 1. | 1195 // We do no shifts, only the Smi conversion, if shift_value is 1. |
| 1196 if (shift_value == 0) { | 1196 if (shift_value == 0) { |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1368 dest->false_target()->Jump(); | 1368 dest->false_target()->Jump(); |
| 1369 | 1369 |
| 1370 is_smi.Bind(&left_side, &right_side); | 1370 is_smi.Bind(&left_side, &right_side); |
| 1371 left_side.ToRegister(); | 1371 left_side.ToRegister(); |
| 1372 // Test smi equality and comparison by signed int comparison. | 1372 // Test smi equality and comparison by signed int comparison. |
| 1373 if (IsUnsafeSmi(right_side.handle())) { | 1373 if (IsUnsafeSmi(right_side.handle())) { |
| 1374 right_side.ToRegister(); | 1374 right_side.ToRegister(); |
| 1375 ASSERT(right_side.is_valid()); | 1375 ASSERT(right_side.is_valid()); |
| 1376 __ cmp(left_side.reg(), Operand(right_side.reg())); | 1376 __ cmp(left_side.reg(), Operand(right_side.reg())); |
| 1377 } else { | 1377 } else { |
| 1378 __ cmp(Operand(left_side.reg()), Immediate(right_side.handle())); | 1378 __ cmp(Operand(left_side.reg()), Immediate(right_side.handle())); |
| 1379 } | 1379 } |
| 1380 left_side.Unuse(); | 1380 left_side.Unuse(); |
| 1381 right_side.Unuse(); | 1381 right_side.Unuse(); |
| 1382 dest->Split(cc); | 1382 dest->Split(cc); |
| 1383 } | 1383 } |
| 1384 } else if (cc == equal && | 1384 } else if (cc == equal && |
| 1385 (left_side_constant_null || right_side_constant_null)) { | 1385 (left_side_constant_null || right_side_constant_null)) { |
| 1386 // To make null checks efficient, we check if either the left side or | 1386 // To make null checks efficient, we check if either the left side or |
| 1387 // the right side is the constant 'null'. | 1387 // the right side is the constant 'null'. |
| 1388 // If so, we optimize the code by inlining a null check instead of | 1388 // If so, we optimize the code by inlining a null check instead of |
| (...skipping 5427 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6816 | 6816 |
| 6817 // Slow-case: Go through the JavaScript implementation. | 6817 // Slow-case: Go through the JavaScript implementation. |
| 6818 __ bind(&slow); | 6818 __ bind(&slow); |
| 6819 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); | 6819 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); |
| 6820 } | 6820 } |
| 6821 | 6821 |
| 6822 | 6822 |
| 6823 #undef __ | 6823 #undef __ |
| 6824 | 6824 |
| 6825 } } // namespace v8::internal | 6825 } } // namespace v8::internal |
| OLD | NEW |