OLD | NEW |
---|---|
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 1128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1139 | 1139 |
1140 case Token::SHL: | 1140 case Token::SHL: |
1141 case Token::SHR: | 1141 case Token::SHR: |
1142 case Token::SAR: { | 1142 case Token::SAR: { |
1143 ASSERT(!reversed); | 1143 ASSERT(!reversed); |
1144 Register scratch = VirtualFrame::scratch0(); | 1144 Register scratch = VirtualFrame::scratch0(); |
1145 Register scratch2 = VirtualFrame::scratch1(); | 1145 Register scratch2 = VirtualFrame::scratch1(); |
1146 int shift_value = int_value & 0x1f; // least significant 5 bits | 1146 int shift_value = int_value & 0x1f; // least significant 5 bits |
1147 DeferredCode* deferred = | 1147 DeferredCode* deferred = |
1148 new DeferredInlineSmiOperation(op, shift_value, false, mode, tos); | 1148 new DeferredInlineSmiOperation(op, shift_value, false, mode, tos); |
1149 __ tst(tos, Operand(kSmiTagMask)); | 1149 uint32_t problematic_mask = kSmiTagMask; |
1150 deferred->Branch(ne); | 1150 // For unsigned shift by zero all negative smis are problematic. |
1151 __ mov(scratch, Operand(tos, ASR, kSmiTagSize)); // remove tags | 1151 if (shift_value == 0 && op == Token::SHR) problematic_mask |= 0x80000000; |
1152 __ tst(tos, Operand(problematic_mask)); | |
1153 deferred->Branch(ne); // Go slow for problematic input. | |
1152 switch (op) { | 1154 switch (op) { |
1153 case Token::SHL: { | 1155 case Token::SHL: { |
1154 if (shift_value != 0) { | 1156 if (shift_value != 0) { |
1155 __ mov(scratch, Operand(scratch, LSL, shift_value)); | 1157 int adjusted_shift = shift_value - kSmiTagSize; |
1158 ASSERT(adjusted_shift >= 0); | |
1159 if (adjusted_shift != 0) { | |
1160 __ mov(scratch, Operand(tos, LSL, adjusted_shift)); | |
1161 // Check that the *signed* result fits in a smi. | |
1162 __ add(scratch2, scratch, Operand(0x40000000), SetCC); | |
1163 deferred->Branch(mi); | |
1164 __ mov(tos, Operand(scratch, LSL, kSmiTagSize)); | |
1165 } else { | |
1166 // Check that the *signed* result fits in a smi. | |
1167 __ add(scratch2, tos, Operand(0x40000000), SetCC); | |
1168 deferred->Branch(mi); | |
1169 __ mov(tos, Operand(tos, LSL, kSmiTagSize)); | |
1170 } | |
1156 } | 1171 } |
1157 // check that the *signed* result fits in a smi | |
1158 __ add(scratch2, scratch, Operand(0x40000000), SetCC); | |
1159 deferred->Branch(mi); | |
1160 break; | 1172 break; |
1161 } | 1173 } |
1162 case Token::SHR: { | 1174 case Token::SHR: { |
1163 // LSR by immediate 0 means shifting 32 bits. | |
1164 if (shift_value != 0) { | 1175 if (shift_value != 0) { |
1176 __ mov(scratch, Operand(tos, ASR, kSmiTagSize)); // Remove tag. | |
1177 // LSR by immediate 0 means shifting 32 bits. | |
1165 __ mov(scratch, Operand(scratch, LSR, shift_value)); | 1178 __ mov(scratch, Operand(scratch, LSR, shift_value)); |
1179 if (shift_value < 2) { | |
Søren Thygesen Gjesse
2010/05/11 07:57:11
With the test above this is shift_value == 1.
| |
1180 // check that the *unsigned* result fits in a smi | |
1181 // neither of the two high-order bits can be set: | |
1182 // - 0x80000000: high bit would be lost when smi tagging | |
1183 // - 0x40000000: this number would convert to negative when | |
1184 // smi tagging these two cases can only happen with shifts | |
1185 // by 0 or 1 when handed a valid smi | |
1186 __ tst(scratch, Operand(0xc0000000)); | |
1187 deferred->Branch(ne); | |
1188 } | |
1189 __ mov(tos, Operand(scratch, LSL, kSmiTagSize)); | |
1166 } | 1190 } |
1167 // check that the *unsigned* result fits in a smi | |
1168 // neither of the two high-order bits can be set: | |
1169 // - 0x80000000: high bit would be lost when smi tagging | |
1170 // - 0x40000000: this number would convert to negative when | |
1171 // smi tagging these two cases can only happen with shifts | |
1172 // by 0 or 1 when handed a valid smi | |
1173 __ tst(scratch, Operand(0xc0000000)); | |
1174 deferred->Branch(ne); | |
1175 break; | 1191 break; |
1176 } | 1192 } |
1177 case Token::SAR: { | 1193 case Token::SAR: { |
1194 // In the ARM instructions set, ASR by immediate 0 means shifting 32 | |
1195 // bits. | |
1178 if (shift_value != 0) { | 1196 if (shift_value != 0) { |
1179 // ASR by immediate 0 means shifting 32 bits. | 1197 // Do the shift and the tag removal in one operation. If the shift |
1180 __ mov(scratch, Operand(scratch, ASR, shift_value)); | 1198 // is 31 bits (the highest possible value) then we emit the |
1199 // instruction as a shift by 0 which means shift arithmetically by | |
1200 // 32. | |
1201 __ mov(tos, Operand(tos, ASR, (kSmiTagSize + shift_value) & 0x1f)); | |
1202 // Put tag back. | |
1203 __ mov(tos, Operand(tos, LSL, kSmiTagSize)); | |
1181 } | 1204 } |
1182 break; | 1205 break; |
1183 } | 1206 } |
1184 default: UNREACHABLE(); | 1207 default: UNREACHABLE(); |
1185 } | 1208 } |
1186 __ mov(tos, Operand(scratch, LSL, kSmiTagSize)); | |
1187 deferred->BindExit(); | 1209 deferred->BindExit(); |
1188 frame_->EmitPush(tos); | 1210 frame_->EmitPush(tos); |
1189 break; | 1211 break; |
1190 } | 1212 } |
1191 | 1213 |
1192 case Token::MOD: { | 1214 case Token::MOD: { |
1193 ASSERT(!reversed); | 1215 ASSERT(!reversed); |
1194 ASSERT(int_value >= 2); | 1216 ASSERT(int_value >= 2); |
1195 ASSERT(IsPowerOf2(int_value)); | 1217 ASSERT(IsPowerOf2(int_value)); |
1196 DeferredCode* deferred = | 1218 DeferredCode* deferred = |
(...skipping 8804 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
10001 | 10023 |
10002 // Just jump to runtime to add the two strings. | 10024 // Just jump to runtime to add the two strings. |
10003 __ bind(&string_add_runtime); | 10025 __ bind(&string_add_runtime); |
10004 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); | 10026 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); |
10005 } | 10027 } |
10006 | 10028 |
10007 | 10029 |
10008 #undef __ | 10030 #undef __ |
10009 | 10031 |
10010 } } // namespace v8::internal | 10032 } } // namespace v8::internal |
OLD | NEW |