| OLD | NEW |
| 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 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 824 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 835 __ cmp(FieldOperand(left_, HeapObject::kMapOffset), | 835 __ cmp(FieldOperand(left_, HeapObject::kMapOffset), |
| 836 Factory::heap_number_map()); | 836 Factory::heap_number_map()); |
| 837 __ j(not_equal, &call_runtime); | 837 __ j(not_equal, &call_runtime); |
| 838 __ movdbl(xmm0, FieldOperand(left_, HeapNumber::kValueOffset)); | 838 __ movdbl(xmm0, FieldOperand(left_, HeapNumber::kValueOffset)); |
| 839 if (mode_ == OVERWRITE_LEFT) { | 839 if (mode_ == OVERWRITE_LEFT) { |
| 840 __ mov(dst_, left_); | 840 __ mov(dst_, left_); |
| 841 } | 841 } |
| 842 __ jmp(&load_right); | 842 __ jmp(&load_right); |
| 843 | 843 |
| 844 __ bind(&left_smi); | 844 __ bind(&left_smi); |
| 845 __ sar(left_, 1); | 845 __ SmiUntag(left_); |
| 846 __ cvtsi2sd(xmm0, Operand(left_)); | 846 __ cvtsi2sd(xmm0, Operand(left_)); |
| 847 __ shl(left_, 1); | 847 __ SmiTag(left_); |
| 848 if (mode_ == OVERWRITE_LEFT) { | 848 if (mode_ == OVERWRITE_LEFT) { |
| 849 Label alloc_failure; | 849 Label alloc_failure; |
| 850 __ push(left_); | 850 __ push(left_); |
| 851 __ AllocateHeapNumber(dst_, left_, no_reg, &after_alloc_failure); | 851 __ AllocateHeapNumber(dst_, left_, no_reg, &after_alloc_failure); |
| 852 __ pop(left_); | 852 __ pop(left_); |
| 853 } | 853 } |
| 854 | 854 |
| 855 __ bind(&load_right); | 855 __ bind(&load_right); |
| 856 __ test(right_, Immediate(kSmiTagMask)); | 856 __ test(right_, Immediate(kSmiTagMask)); |
| 857 __ j(zero, &right_smi); | 857 __ j(zero, &right_smi); |
| 858 __ cmp(FieldOperand(right_, HeapObject::kMapOffset), | 858 __ cmp(FieldOperand(right_, HeapObject::kMapOffset), |
| 859 Factory::heap_number_map()); | 859 Factory::heap_number_map()); |
| 860 __ j(not_equal, &call_runtime); | 860 __ j(not_equal, &call_runtime); |
| 861 __ movdbl(xmm1, FieldOperand(right_, HeapNumber::kValueOffset)); | 861 __ movdbl(xmm1, FieldOperand(right_, HeapNumber::kValueOffset)); |
| 862 if (mode_ == OVERWRITE_RIGHT) { | 862 if (mode_ == OVERWRITE_RIGHT) { |
| 863 __ mov(dst_, right_); | 863 __ mov(dst_, right_); |
| 864 } else if (mode_ == NO_OVERWRITE) { | 864 } else if (mode_ == NO_OVERWRITE) { |
| 865 Label alloc_failure; | 865 Label alloc_failure; |
| 866 __ push(left_); | 866 __ push(left_); |
| 867 __ AllocateHeapNumber(dst_, left_, no_reg, &after_alloc_failure); | 867 __ AllocateHeapNumber(dst_, left_, no_reg, &after_alloc_failure); |
| 868 __ pop(left_); | 868 __ pop(left_); |
| 869 } | 869 } |
| 870 __ jmp(&do_op); | 870 __ jmp(&do_op); |
| 871 | 871 |
| 872 __ bind(&right_smi); | 872 __ bind(&right_smi); |
| 873 __ sar(right_, 1); | 873 __ SmiUntag(right_); |
| 874 __ cvtsi2sd(xmm1, Operand(right_)); | 874 __ cvtsi2sd(xmm1, Operand(right_)); |
| 875 __ shl(right_, 1); | 875 __ SmiTag(right_); |
| 876 if (mode_ == OVERWRITE_RIGHT || mode_ == NO_OVERWRITE) { | 876 if (mode_ == OVERWRITE_RIGHT || mode_ == NO_OVERWRITE) { |
| 877 Label alloc_failure; | 877 Label alloc_failure; |
| 878 __ push(left_); | 878 __ push(left_); |
| 879 __ AllocateHeapNumber(dst_, left_, no_reg, &after_alloc_failure); | 879 __ AllocateHeapNumber(dst_, left_, no_reg, &after_alloc_failure); |
| 880 __ pop(left_); | 880 __ pop(left_); |
| 881 } | 881 } |
| 882 | 882 |
| 883 __ bind(&do_op); | 883 __ bind(&do_op); |
| 884 switch (op_) { | 884 switch (op_) { |
| 885 case Token::ADD: __ addsd(xmm0, xmm1); break; | 885 case Token::ADD: __ addsd(xmm0, xmm1); break; |
| (...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1208 // Check for the corner case of dividing the most negative smi by | 1208 // Check for the corner case of dividing the most negative smi by |
| 1209 // -1. We cannot use the overflow flag, since it is not set by | 1209 // -1. We cannot use the overflow flag, since it is not set by |
| 1210 // idiv instruction. | 1210 // idiv instruction. |
| 1211 ASSERT(kSmiTag == 0 && kSmiTagSize == 1); | 1211 ASSERT(kSmiTag == 0 && kSmiTagSize == 1); |
| 1212 __ cmp(eax, 0x40000000); | 1212 __ cmp(eax, 0x40000000); |
| 1213 deferred->Branch(equal); | 1213 deferred->Branch(equal); |
| 1214 // Check that the remainder is zero. | 1214 // Check that the remainder is zero. |
| 1215 __ test(edx, Operand(edx)); | 1215 __ test(edx, Operand(edx)); |
| 1216 deferred->Branch(not_zero); | 1216 deferred->Branch(not_zero); |
| 1217 // Tag the result and store it in the quotient register. | 1217 // Tag the result and store it in the quotient register. |
| 1218 ASSERT(kSmiTagSize == times_2); // adjust code if not the case | 1218 __ SmiTag(eax); |
| 1219 __ lea(eax, Operand(eax, eax, times_1, kSmiTag)); | |
| 1220 deferred->BindExit(); | 1219 deferred->BindExit(); |
| 1221 left->Unuse(); | 1220 left->Unuse(); |
| 1222 right->Unuse(); | 1221 right->Unuse(); |
| 1223 frame_->Push("ient); | 1222 frame_->Push("ient); |
| 1224 } else { | 1223 } else { |
| 1225 ASSERT(op == Token::MOD); | 1224 ASSERT(op == Token::MOD); |
| 1226 // Check for a negative zero result. If the result is zero, and | 1225 // Check for a negative zero result. If the result is zero, and |
| 1227 // the dividend is negative, return a floating point negative | 1226 // the dividend is negative, return a floating point negative |
| 1228 // zero. The frame is unchanged in this block, so local control | 1227 // zero. The frame is unchanged in this block, so local control |
| 1229 // flow can use a Label rather than a JumpTarget. | 1228 // flow can use a Label rather than a JumpTarget. |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1269 left->reg(), | 1268 left->reg(), |
| 1270 ecx, | 1269 ecx, |
| 1271 overwrite_mode); | 1270 overwrite_mode); |
| 1272 __ mov(answer.reg(), left->reg()); | 1271 __ mov(answer.reg(), left->reg()); |
| 1273 __ or_(answer.reg(), Operand(ecx)); | 1272 __ or_(answer.reg(), Operand(ecx)); |
| 1274 __ test(answer.reg(), Immediate(kSmiTagMask)); | 1273 __ test(answer.reg(), Immediate(kSmiTagMask)); |
| 1275 deferred->Branch(not_zero); | 1274 deferred->Branch(not_zero); |
| 1276 | 1275 |
| 1277 // Untag both operands. | 1276 // Untag both operands. |
| 1278 __ mov(answer.reg(), left->reg()); | 1277 __ mov(answer.reg(), left->reg()); |
| 1279 __ sar(answer.reg(), kSmiTagSize); | 1278 __ SmiUntag(answer.reg()); |
| 1280 __ sar(ecx, kSmiTagSize); | 1279 __ SmiUntag(ecx); |
| 1281 // Perform the operation. | 1280 // Perform the operation. |
| 1282 switch (op) { | 1281 switch (op) { |
| 1283 case Token::SAR: | 1282 case Token::SAR: |
| 1284 __ sar_cl(answer.reg()); | 1283 __ sar_cl(answer.reg()); |
| 1285 // No checks of result necessary | 1284 // No checks of result necessary |
| 1286 break; | 1285 break; |
| 1287 case Token::SHR: { | 1286 case Token::SHR: { |
| 1288 Label result_ok; | 1287 Label result_ok; |
| 1289 __ shr_cl(answer.reg()); | 1288 __ shr_cl(answer.reg()); |
| 1290 // Check that the *unsigned* result fits in a smi. Neither of | 1289 // Check that the *unsigned* result fits in a smi. Neither of |
| 1291 // the two high-order bits can be set: | 1290 // the two high-order bits can be set: |
| 1292 // * 0x80000000: high bit would be lost when smi tagging. | 1291 // * 0x80000000: high bit would be lost when smi tagging. |
| 1293 // * 0x40000000: this number would convert to negative when smi | 1292 // * 0x40000000: this number would convert to negative when smi |
| 1294 // tagging. | 1293 // tagging. |
| 1295 // These two cases can only happen with shifts by 0 or 1 when | 1294 // These two cases can only happen with shifts by 0 or 1 when |
| 1296 // handed a valid smi. If the answer cannot be represented by a | 1295 // handed a valid smi. If the answer cannot be represented by a |
| 1297 // smi, restore the left and right arguments, and jump to slow | 1296 // smi, restore the left and right arguments, and jump to slow |
| 1298 // case. The low bit of the left argument may be lost, but only | 1297 // case. The low bit of the left argument may be lost, but only |
| 1299 // in a case where it is dropped anyway. | 1298 // in a case where it is dropped anyway. |
| 1300 __ test(answer.reg(), Immediate(0xc0000000)); | 1299 __ test(answer.reg(), Immediate(0xc0000000)); |
| 1301 __ j(zero, &result_ok); | 1300 __ j(zero, &result_ok); |
| 1302 ASSERT(kSmiTag == 0); | 1301 __ SmiTag(ecx); |
| 1303 __ shl(ecx, kSmiTagSize); | |
| 1304 deferred->Jump(); | 1302 deferred->Jump(); |
| 1305 __ bind(&result_ok); | 1303 __ bind(&result_ok); |
| 1306 break; | 1304 break; |
| 1307 } | 1305 } |
| 1308 case Token::SHL: { | 1306 case Token::SHL: { |
| 1309 Label result_ok; | 1307 Label result_ok; |
| 1310 __ shl_cl(answer.reg()); | 1308 __ shl_cl(answer.reg()); |
| 1311 // Check that the *signed* result fits in a smi. | 1309 // Check that the *signed* result fits in a smi. |
| 1312 __ cmp(answer.reg(), 0xc0000000); | 1310 __ cmp(answer.reg(), 0xc0000000); |
| 1313 __ j(positive, &result_ok); | 1311 __ j(positive, &result_ok); |
| 1314 ASSERT(kSmiTag == 0); | 1312 __ SmiTag(ecx); |
| 1315 __ shl(ecx, kSmiTagSize); | |
| 1316 deferred->Jump(); | 1313 deferred->Jump(); |
| 1317 __ bind(&result_ok); | 1314 __ bind(&result_ok); |
| 1318 break; | 1315 break; |
| 1319 } | 1316 } |
| 1320 default: | 1317 default: |
| 1321 UNREACHABLE(); | 1318 UNREACHABLE(); |
| 1322 } | 1319 } |
| 1323 // Smi-tag the result in answer. | 1320 // Smi-tag the result in answer. |
| 1324 ASSERT(kSmiTagSize == 1); // Adjust code if not the case. | 1321 __ SmiTag(answer.reg()); |
| 1325 __ lea(answer.reg(), | |
| 1326 Operand(answer.reg(), answer.reg(), times_1, kSmiTag)); | |
| 1327 deferred->BindExit(); | 1322 deferred->BindExit(); |
| 1328 left->Unuse(); | 1323 left->Unuse(); |
| 1329 right->Unuse(); | 1324 right->Unuse(); |
| 1330 frame_->Push(&answer); | 1325 frame_->Push(&answer); |
| 1331 return; | 1326 return; |
| 1332 } | 1327 } |
| 1333 | 1328 |
| 1334 // Handle the other binary operations. | 1329 // Handle the other binary operations. |
| 1335 left->ToRegister(); | 1330 left->ToRegister(); |
| 1336 right->ToRegister(); | 1331 right->ToRegister(); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1366 case Token::SUB: | 1361 case Token::SUB: |
| 1367 __ sub(answer.reg(), Operand(right->reg())); // Subtract optimistically. | 1362 __ sub(answer.reg(), Operand(right->reg())); // Subtract optimistically. |
| 1368 deferred->Branch(overflow); | 1363 deferred->Branch(overflow); |
| 1369 break; | 1364 break; |
| 1370 | 1365 |
| 1371 case Token::MUL: { | 1366 case Token::MUL: { |
| 1372 // If the smi tag is 0 we can just leave the tag on one operand. | 1367 // If the smi tag is 0 we can just leave the tag on one operand. |
| 1373 ASSERT(kSmiTag == 0); // Adjust code below if not the case. | 1368 ASSERT(kSmiTag == 0); // Adjust code below if not the case. |
| 1374 // Remove smi tag from the left operand (but keep sign). | 1369 // Remove smi tag from the left operand (but keep sign). |
| 1375 // Left-hand operand has been copied into answer. | 1370 // Left-hand operand has been copied into answer. |
| 1376 __ sar(answer.reg(), kSmiTagSize); | 1371 __ SmiUntag(answer.reg()); |
| 1377 // Do multiplication of smis, leaving result in answer. | 1372 // Do multiplication of smis, leaving result in answer. |
| 1378 __ imul(answer.reg(), Operand(right->reg())); | 1373 __ imul(answer.reg(), Operand(right->reg())); |
| 1379 // Go slow on overflows. | 1374 // Go slow on overflows. |
| 1380 deferred->Branch(overflow); | 1375 deferred->Branch(overflow); |
| 1381 // Check for negative zero result. If product is zero, and one | 1376 // Check for negative zero result. If product is zero, and one |
| 1382 // argument is negative, go to slow case. The frame is unchanged | 1377 // argument is negative, go to slow case. The frame is unchanged |
| 1383 // in this block, so local control flow can use a Label rather | 1378 // in this block, so local control flow can use a Label rather |
| 1384 // than a JumpTarget. | 1379 // than a JumpTarget. |
| 1385 Label non_zero_result; | 1380 Label non_zero_result; |
| 1386 __ test(answer.reg(), Operand(answer.reg())); | 1381 __ test(answer.reg(), Operand(answer.reg())); |
| (...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1713 ASSERT(answer.is_valid()); | 1708 ASSERT(answer.is_valid()); |
| 1714 DeferredInlineSmiOperation* deferred = | 1709 DeferredInlineSmiOperation* deferred = |
| 1715 new DeferredInlineSmiOperation(op, | 1710 new DeferredInlineSmiOperation(op, |
| 1716 answer.reg(), | 1711 answer.reg(), |
| 1717 operand->reg(), | 1712 operand->reg(), |
| 1718 smi_value, | 1713 smi_value, |
| 1719 overwrite_mode); | 1714 overwrite_mode); |
| 1720 __ test(operand->reg(), Immediate(kSmiTagMask)); | 1715 __ test(operand->reg(), Immediate(kSmiTagMask)); |
| 1721 deferred->Branch(not_zero); | 1716 deferred->Branch(not_zero); |
| 1722 __ mov(answer.reg(), operand->reg()); | 1717 __ mov(answer.reg(), operand->reg()); |
| 1723 __ sar(answer.reg(), kSmiTagSize); | 1718 __ SmiUntag(answer.reg()); |
| 1724 __ shr(answer.reg(), shift_value); | 1719 __ shr(answer.reg(), shift_value); |
| 1725 // A negative Smi shifted right two is in the positive Smi range. | 1720 // A negative Smi shifted right two is in the positive Smi range. |
| 1726 if (shift_value < 2) { | 1721 if (shift_value < 2) { |
| 1727 __ test(answer.reg(), Immediate(0xc0000000)); | 1722 __ test(answer.reg(), Immediate(0xc0000000)); |
| 1728 deferred->Branch(not_zero); | 1723 deferred->Branch(not_zero); |
| 1729 } | 1724 } |
| 1730 operand->Unuse(); | 1725 operand->Unuse(); |
| 1731 ASSERT(kSmiTagSize == times_2); // Adjust the code if not true. | 1726 __ SmiTag(answer.reg()); |
| 1732 __ lea(answer.reg(), | |
| 1733 Operand(answer.reg(), answer.reg(), times_1, kSmiTag)); | |
| 1734 deferred->BindExit(); | 1727 deferred->BindExit(); |
| 1735 frame_->Push(&answer); | 1728 frame_->Push(&answer); |
| 1736 } | 1729 } |
| 1737 break; | 1730 break; |
| 1738 | 1731 |
| 1739 case Token::SHL: | 1732 case Token::SHL: |
| 1740 if (reversed) { | 1733 if (reversed) { |
| 1741 Result constant_operand(value); | 1734 Result constant_operand(value); |
| 1742 LikelySmiBinaryOperation(op, &constant_operand, operand, | 1735 LikelySmiBinaryOperation(op, &constant_operand, operand, |
| 1743 overwrite_mode); | 1736 overwrite_mode); |
| (...skipping 492 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2236 for (int i = 0; i < scope_->num_parameters(); i++) { | 2229 for (int i = 0; i < scope_->num_parameters(); i++) { |
| 2237 __ push(frame_->ParameterAt(i)); | 2230 __ push(frame_->ParameterAt(i)); |
| 2238 } | 2231 } |
| 2239 __ jmp(&invoke); | 2232 __ jmp(&invoke); |
| 2240 | 2233 |
| 2241 // Arguments adaptor frame present. Copy arguments from there, but | 2234 // Arguments adaptor frame present. Copy arguments from there, but |
| 2242 // avoid copying too many arguments to avoid stack overflows. | 2235 // avoid copying too many arguments to avoid stack overflows. |
| 2243 __ bind(&adapted); | 2236 __ bind(&adapted); |
| 2244 static const uint32_t kArgumentsLimit = 1 * KB; | 2237 static const uint32_t kArgumentsLimit = 1 * KB; |
| 2245 __ mov(eax, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset)); | 2238 __ mov(eax, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
| 2246 __ shr(eax, kSmiTagSize); | 2239 __ SmiUntag(eax); |
| 2247 __ mov(ecx, Operand(eax)); | 2240 __ mov(ecx, Operand(eax)); |
| 2248 __ cmp(eax, kArgumentsLimit); | 2241 __ cmp(eax, kArgumentsLimit); |
| 2249 build_args.Branch(above); | 2242 build_args.Branch(above); |
| 2250 | 2243 |
| 2251 // Loop through the arguments pushing them onto the execution | 2244 // Loop through the arguments pushing them onto the execution |
| 2252 // stack. We don't inform the virtual frame of the push, so we don't | 2245 // stack. We don't inform the virtual frame of the push, so we don't |
| 2253 // have to worry about getting rid of the elements from the virtual | 2246 // have to worry about getting rid of the elements from the virtual |
| 2254 // frame. | 2247 // frame. |
| 2255 Label loop; | 2248 Label loop; |
| 2256 __ bind(&loop); | 2249 __ bind(&loop); |
| (...skipping 1006 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3263 | 3256 |
| 3264 __ mov(ecx, FieldOperand(ecx, Map::kInstanceDescriptorsOffset)); | 3257 __ mov(ecx, FieldOperand(ecx, Map::kInstanceDescriptorsOffset)); |
| 3265 // Get the bridge array held in the enumeration index field. | 3258 // Get the bridge array held in the enumeration index field. |
| 3266 __ mov(ecx, FieldOperand(ecx, DescriptorArray::kEnumerationIndexOffset)); | 3259 __ mov(ecx, FieldOperand(ecx, DescriptorArray::kEnumerationIndexOffset)); |
| 3267 // Get the cache from the bridge array. | 3260 // Get the cache from the bridge array. |
| 3268 __ mov(edx, FieldOperand(ecx, DescriptorArray::kEnumCacheBridgeCacheOffset)); | 3261 __ mov(edx, FieldOperand(ecx, DescriptorArray::kEnumCacheBridgeCacheOffset)); |
| 3269 | 3262 |
| 3270 frame_->EmitPush(eax); // <- slot 3 | 3263 frame_->EmitPush(eax); // <- slot 3 |
| 3271 frame_->EmitPush(edx); // <- slot 2 | 3264 frame_->EmitPush(edx); // <- slot 2 |
| 3272 __ mov(eax, FieldOperand(edx, FixedArray::kLengthOffset)); | 3265 __ mov(eax, FieldOperand(edx, FixedArray::kLengthOffset)); |
| 3273 __ shl(eax, kSmiTagSize); | 3266 __ SmiTag(eax); |
| 3274 frame_->EmitPush(eax); // <- slot 1 | 3267 frame_->EmitPush(eax); // <- slot 1 |
| 3275 frame_->EmitPush(Immediate(Smi::FromInt(0))); // <- slot 0 | 3268 frame_->EmitPush(Immediate(Smi::FromInt(0))); // <- slot 0 |
| 3276 entry.Jump(); | 3269 entry.Jump(); |
| 3277 | 3270 |
| 3278 fixed_array.Bind(); | 3271 fixed_array.Bind(); |
| 3279 // eax: fixed array (result from call to Runtime::kGetPropertyNamesFast) | 3272 // eax: fixed array (result from call to Runtime::kGetPropertyNamesFast) |
| 3280 frame_->EmitPush(Immediate(Smi::FromInt(0))); // <- slot 3 | 3273 frame_->EmitPush(Immediate(Smi::FromInt(0))); // <- slot 3 |
| 3281 frame_->EmitPush(eax); // <- slot 2 | 3274 frame_->EmitPush(eax); // <- slot 2 |
| 3282 | 3275 |
| 3283 // Push the length of the array and the initial index onto the stack. | 3276 // Push the length of the array and the initial index onto the stack. |
| 3284 __ mov(eax, FieldOperand(eax, FixedArray::kLengthOffset)); | 3277 __ mov(eax, FieldOperand(eax, FixedArray::kLengthOffset)); |
| 3285 __ shl(eax, kSmiTagSize); | 3278 __ SmiTag(eax); |
| 3286 frame_->EmitPush(eax); // <- slot 1 | 3279 frame_->EmitPush(eax); // <- slot 1 |
| 3287 frame_->EmitPush(Immediate(Smi::FromInt(0))); // <- slot 0 | 3280 frame_->EmitPush(Immediate(Smi::FromInt(0))); // <- slot 0 |
| 3288 | 3281 |
| 3289 // Condition. | 3282 // Condition. |
| 3290 entry.Bind(); | 3283 entry.Bind(); |
| 3291 // Grab the current frame's height for the break and continue | 3284 // Grab the current frame's height for the break and continue |
| 3292 // targets only after all the state is pushed on the frame. | 3285 // targets only after all the state is pushed on the frame. |
| 3293 node->break_target()->set_direction(JumpTarget::FORWARD_ONLY); | 3286 node->break_target()->set_direction(JumpTarget::FORWARD_ONLY); |
| 3294 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY); | 3287 node->continue_target()->set_direction(JumpTarget::FORWARD_ONLY); |
| 3295 | 3288 |
| (...skipping 1144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4440 deferred->Branch(equal); | 4433 deferred->Branch(equal); |
| 4441 deferred->BindExit(); | 4434 deferred->BindExit(); |
| 4442 literals.Unuse(); | 4435 literals.Unuse(); |
| 4443 | 4436 |
| 4444 // Push the resulting array literal boilerplate on the stack. | 4437 // Push the resulting array literal boilerplate on the stack. |
| 4445 frame_->Push(&boilerplate); | 4438 frame_->Push(&boilerplate); |
| 4446 | 4439 |
| 4447 // Clone the boilerplate object. | 4440 // Clone the boilerplate object. |
| 4448 int length = node->values()->length(); | 4441 int length = node->values()->length(); |
| 4449 Result clone; | 4442 Result clone; |
| 4450 if (node->depth() == 1 && | 4443 if (node->depth() == 1) { |
| 4451 length <= FastCloneShallowArrayStub::kMaximumLength) { | 4444 if (length <= FastCloneShallowArrayStub::kMaximumLength) { |
| 4452 FastCloneShallowArrayStub stub(length); | 4445 FastCloneShallowArrayStub stub(length); |
| 4453 clone = frame_->CallStub(&stub, 1); | 4446 clone = frame_->CallStub(&stub, 1); |
| 4447 } else { |
| 4448 clone = frame_->CallRuntime(Runtime::kCloneShallowLiteralBoilerplate, 1); |
| 4449 } |
| 4454 } else { | 4450 } else { |
| 4455 clone = frame_->CallRuntime(Runtime::kCloneLiteralBoilerplate, 1); | 4451 clone = frame_->CallRuntime(Runtime::kCloneLiteralBoilerplate, 1); |
| 4456 } | 4452 } |
| 4457 // Push the newly cloned literal object as the result. | 4453 // Push the newly cloned literal object as the result. |
| 4458 frame_->Push(&clone); | 4454 frame_->Push(&clone); |
| 4459 | 4455 |
| 4460 // Generate code to set the elements in the array that are not | 4456 // Generate code to set the elements in the array that are not |
| 4461 // literals. | 4457 // literals. |
| 4462 for (int i = 0; i < length; i++) { | 4458 for (int i = 0; i < length; i++) { |
| 4463 Expression* value = node->values()->at(i); | 4459 Expression* value = node->values()->at(i); |
| (...skipping 542 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5006 __ jmp(&got_char_code); | 5002 __ jmp(&got_char_code); |
| 5007 | 5003 |
| 5008 // ASCII string. | 5004 // ASCII string. |
| 5009 __ bind(&ascii_string); | 5005 __ bind(&ascii_string); |
| 5010 // Load the byte into the temp register. | 5006 // Load the byte into the temp register. |
| 5011 __ movzx_b(temp.reg(), FieldOperand(object.reg(), | 5007 __ movzx_b(temp.reg(), FieldOperand(object.reg(), |
| 5012 index.reg(), | 5008 index.reg(), |
| 5013 times_1, | 5009 times_1, |
| 5014 SeqAsciiString::kHeaderSize)); | 5010 SeqAsciiString::kHeaderSize)); |
| 5015 __ bind(&got_char_code); | 5011 __ bind(&got_char_code); |
| 5016 ASSERT(kSmiTag == 0); | 5012 __ SmiTag(temp.reg()); |
| 5017 __ shl(temp.reg(), kSmiTagSize); | |
| 5018 __ jmp(&end); | 5013 __ jmp(&end); |
| 5019 | 5014 |
| 5020 // Handle non-flat strings. | 5015 // Handle non-flat strings. |
| 5021 __ bind(¬_a_flat_string); | 5016 __ bind(¬_a_flat_string); |
| 5022 __ and_(temp.reg(), kStringRepresentationMask); | 5017 __ and_(temp.reg(), kStringRepresentationMask); |
| 5023 __ cmp(temp.reg(), kConsStringTag); | 5018 __ cmp(temp.reg(), kConsStringTag); |
| 5024 __ j(not_equal, &slow_case); | 5019 __ j(not_equal, &slow_case); |
| 5025 | 5020 |
| 5026 // ConsString. | 5021 // ConsString. |
| 5027 // Check that the right hand side is the empty string (ie if this is really a | 5022 // Check that the right hand side is the empty string (ie if this is really a |
| (...skipping 1993 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7021 switch (op_) { | 7016 switch (op_) { |
| 7022 case Token::ADD: | 7017 case Token::ADD: |
| 7023 case Token::SUB: | 7018 case Token::SUB: |
| 7024 // Do nothing here. | 7019 // Do nothing here. |
| 7025 break; | 7020 break; |
| 7026 | 7021 |
| 7027 case Token::MUL: | 7022 case Token::MUL: |
| 7028 // If the smi tag is 0 we can just leave the tag on one operand. | 7023 // If the smi tag is 0 we can just leave the tag on one operand. |
| 7029 ASSERT(kSmiTag == 0); // adjust code below if not the case | 7024 ASSERT(kSmiTag == 0); // adjust code below if not the case |
| 7030 // Remove tag from one of the operands (but keep sign). | 7025 // Remove tag from one of the operands (but keep sign). |
| 7031 __ sar(eax, kSmiTagSize); | 7026 __ SmiUntag(eax); |
| 7032 // Do multiplication. | 7027 // Do multiplication. |
| 7033 __ imul(eax, Operand(ebx)); // multiplication of smis; result in eax | 7028 __ imul(eax, Operand(ebx)); // multiplication of smis; result in eax |
| 7034 // Go slow on overflows. | 7029 // Go slow on overflows. |
| 7035 __ j(overflow, slow, not_taken); | 7030 __ j(overflow, slow, not_taken); |
| 7036 // Check for negative zero result. | 7031 // Check for negative zero result. |
| 7037 __ NegativeZeroTest(eax, ecx, slow); // use ecx = x | y | 7032 __ NegativeZeroTest(eax, ecx, slow); // use ecx = x | y |
| 7038 break; | 7033 break; |
| 7039 | 7034 |
| 7040 case Token::DIV: | 7035 case Token::DIV: |
| 7041 // Divide edx:eax by ebx. | 7036 // Divide edx:eax by ebx. |
| 7042 __ idiv(ebx); | 7037 __ idiv(ebx); |
| 7043 // Check for the corner case of dividing the most negative smi | 7038 // Check for the corner case of dividing the most negative smi |
| 7044 // by -1. We cannot use the overflow flag, since it is not set | 7039 // by -1. We cannot use the overflow flag, since it is not set |
| 7045 // by idiv instruction. | 7040 // by idiv instruction. |
| 7046 ASSERT(kSmiTag == 0 && kSmiTagSize == 1); | 7041 ASSERT(kSmiTag == 0 && kSmiTagSize == 1); |
| 7047 __ cmp(eax, 0x40000000); | 7042 __ cmp(eax, 0x40000000); |
| 7048 __ j(equal, slow); | 7043 __ j(equal, slow); |
| 7049 // Check for negative zero result. | 7044 // Check for negative zero result. |
| 7050 __ NegativeZeroTest(eax, ecx, slow); // use ecx = x | y | 7045 __ NegativeZeroTest(eax, ecx, slow); // use ecx = x | y |
| 7051 // Check that the remainder is zero. | 7046 // Check that the remainder is zero. |
| 7052 __ test(edx, Operand(edx)); | 7047 __ test(edx, Operand(edx)); |
| 7053 __ j(not_zero, slow); | 7048 __ j(not_zero, slow); |
| 7054 // Tag the result and store it in register eax. | 7049 // Tag the result and store it in register eax. |
| 7055 ASSERT(kSmiTagSize == times_2); // adjust code if not the case | 7050 __ SmiTag(eax); |
| 7056 __ lea(eax, Operand(eax, eax, times_1, kSmiTag)); | |
| 7057 break; | 7051 break; |
| 7058 | 7052 |
| 7059 case Token::MOD: | 7053 case Token::MOD: |
| 7060 // Divide edx:eax by ebx. | 7054 // Divide edx:eax by ebx. |
| 7061 __ idiv(ebx); | 7055 __ idiv(ebx); |
| 7062 // Check for negative zero result. | 7056 // Check for negative zero result. |
| 7063 __ NegativeZeroTest(edx, ecx, slow); // use ecx = x | y | 7057 __ NegativeZeroTest(edx, ecx, slow); // use ecx = x | y |
| 7064 // Move remainder to register eax. | 7058 // Move remainder to register eax. |
| 7065 __ mov(eax, Operand(edx)); | 7059 __ mov(eax, Operand(edx)); |
| 7066 break; | 7060 break; |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7105 case Token::SHL: | 7099 case Token::SHL: |
| 7106 __ shl_cl(eax); | 7100 __ shl_cl(eax); |
| 7107 // Check that the *signed* result fits in a smi. | 7101 // Check that the *signed* result fits in a smi. |
| 7108 __ cmp(eax, 0xc0000000); | 7102 __ cmp(eax, 0xc0000000); |
| 7109 __ j(sign, slow, not_taken); | 7103 __ j(sign, slow, not_taken); |
| 7110 break; | 7104 break; |
| 7111 default: | 7105 default: |
| 7112 UNREACHABLE(); | 7106 UNREACHABLE(); |
| 7113 } | 7107 } |
| 7114 // Tag the result and store it in register eax. | 7108 // Tag the result and store it in register eax. |
| 7115 ASSERT(kSmiTagSize == times_2); // adjust code if not the case | 7109 __ SmiTag(eax); |
| 7116 __ lea(eax, Operand(eax, eax, times_1, kSmiTag)); | |
| 7117 break; | 7110 break; |
| 7118 | 7111 |
| 7119 default: | 7112 default: |
| 7120 UNREACHABLE(); | 7113 UNREACHABLE(); |
| 7121 break; | 7114 break; |
| 7122 } | 7115 } |
| 7123 } | 7116 } |
| 7124 | 7117 |
| 7125 | 7118 |
| 7126 void GenericBinaryOpStub::Generate(MacroAssembler* masm) { | 7119 void GenericBinaryOpStub::Generate(MacroAssembler* masm) { |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7255 if (op_ == Token::SHR) { | 7248 if (op_ == Token::SHR) { |
| 7256 // Check if result is non-negative and fits in a smi. | 7249 // Check if result is non-negative and fits in a smi. |
| 7257 __ test(eax, Immediate(0xc0000000)); | 7250 __ test(eax, Immediate(0xc0000000)); |
| 7258 __ j(not_zero, &non_smi_result); | 7251 __ j(not_zero, &non_smi_result); |
| 7259 } else { | 7252 } else { |
| 7260 // Check if result fits in a smi. | 7253 // Check if result fits in a smi. |
| 7261 __ cmp(eax, 0xc0000000); | 7254 __ cmp(eax, 0xc0000000); |
| 7262 __ j(negative, &non_smi_result); | 7255 __ j(negative, &non_smi_result); |
| 7263 } | 7256 } |
| 7264 // Tag smi result and return. | 7257 // Tag smi result and return. |
| 7265 ASSERT(kSmiTagSize == times_2); // adjust code if not the case | 7258 __ SmiTag(eax); |
| 7266 __ lea(eax, Operand(eax, eax, times_1, kSmiTag)); | |
| 7267 GenerateReturn(masm); | 7259 GenerateReturn(masm); |
| 7268 | 7260 |
| 7269 // All ops except SHR return a signed int32 that we load in a HeapNumber. | 7261 // All ops except SHR return a signed int32 that we load in a HeapNumber. |
| 7270 if (op_ != Token::SHR) { | 7262 if (op_ != Token::SHR) { |
| 7271 __ bind(&non_smi_result); | 7263 __ bind(&non_smi_result); |
| 7272 // Allocate a heap number if needed. | 7264 // Allocate a heap number if needed. |
| 7273 __ mov(ebx, Operand(eax)); // ebx: result | 7265 __ mov(ebx, Operand(eax)); // ebx: result |
| 7274 switch (mode_) { | 7266 switch (mode_) { |
| 7275 case OVERWRITE_LEFT: | 7267 case OVERWRITE_LEFT: |
| 7276 case OVERWRITE_RIGHT: | 7268 case OVERWRITE_RIGHT: |
| (...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7604 __ j(not_equal, not_numbers); // Argument in edx is not a number. | 7596 __ j(not_equal, not_numbers); // Argument in edx is not a number. |
| 7605 __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset)); | 7597 __ movdbl(xmm0, FieldOperand(edx, HeapNumber::kValueOffset)); |
| 7606 __ bind(&load_eax); | 7598 __ bind(&load_eax); |
| 7607 // Load operand in eax into xmm1, or branch to not_numbers. | 7599 // Load operand in eax into xmm1, or branch to not_numbers. |
| 7608 __ test(eax, Immediate(kSmiTagMask)); | 7600 __ test(eax, Immediate(kSmiTagMask)); |
| 7609 __ j(zero, &load_smi_eax, not_taken); // Argument in eax is a smi. | 7601 __ j(zero, &load_smi_eax, not_taken); // Argument in eax is a smi. |
| 7610 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), Factory::heap_number_map()); | 7602 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), Factory::heap_number_map()); |
| 7611 __ j(equal, &load_float_eax); | 7603 __ j(equal, &load_float_eax); |
| 7612 __ jmp(not_numbers); // Argument in eax is not a number. | 7604 __ jmp(not_numbers); // Argument in eax is not a number. |
| 7613 __ bind(&load_smi_edx); | 7605 __ bind(&load_smi_edx); |
| 7614 __ sar(edx, 1); // Untag smi before converting to float. | 7606 __ SmiUntag(edx); // Untag smi before converting to float. |
| 7615 __ cvtsi2sd(xmm0, Operand(edx)); | 7607 __ cvtsi2sd(xmm0, Operand(edx)); |
| 7616 __ shl(edx, 1); // Retag smi for heap number overwriting test. | 7608 __ SmiTag(edx); // Retag smi for heap number overwriting test. |
| 7617 __ jmp(&load_eax); | 7609 __ jmp(&load_eax); |
| 7618 __ bind(&load_smi_eax); | 7610 __ bind(&load_smi_eax); |
| 7619 __ sar(eax, 1); // Untag smi before converting to float. | 7611 __ SmiUntag(eax); // Untag smi before converting to float. |
| 7620 __ cvtsi2sd(xmm1, Operand(eax)); | 7612 __ cvtsi2sd(xmm1, Operand(eax)); |
| 7621 __ shl(eax, 1); // Retag smi for heap number overwriting test. | 7613 __ SmiTag(eax); // Retag smi for heap number overwriting test. |
| 7622 __ jmp(&done); | 7614 __ jmp(&done); |
| 7623 __ bind(&load_float_eax); | 7615 __ bind(&load_float_eax); |
| 7624 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); | 7616 __ movdbl(xmm1, FieldOperand(eax, HeapNumber::kValueOffset)); |
| 7625 __ bind(&done); | 7617 __ bind(&done); |
| 7626 } | 7618 } |
| 7627 | 7619 |
| 7628 | 7620 |
| 7629 void FloatingPointHelper::LoadFloatOperands(MacroAssembler* masm, | 7621 void FloatingPointHelper::LoadFloatOperands(MacroAssembler* masm, |
| 7630 Register scratch) { | 7622 Register scratch) { |
| 7631 Label load_smi_1, load_smi_2, done_load_1, done; | 7623 Label load_smi_1, load_smi_2, done_load_1, done; |
| (...skipping 1280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8912 __ add(Operand(dest), Immediate(2)); | 8904 __ add(Operand(dest), Immediate(2)); |
| 8913 } | 8905 } |
| 8914 __ sub(Operand(count), Immediate(1)); | 8906 __ sub(Operand(count), Immediate(1)); |
| 8915 __ j(not_zero, &loop); | 8907 __ j(not_zero, &loop); |
| 8916 } | 8908 } |
| 8917 | 8909 |
| 8918 | 8910 |
| 8919 #undef __ | 8911 #undef __ |
| 8920 | 8912 |
| 8921 } } // namespace v8::internal | 8913 } } // namespace v8::internal |
| OLD | NEW |