Chromium Code Reviews| 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 |