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 |