Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(20)

Side by Side Diff: src/codegen-ia32.cc

Issue 18669: Remove spills from SMI immediate bitwise and shift operations. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/toiger/
Patch Set: '' Created 11 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698