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 |