| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 1190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1201 (StringAddFlags)(STRING_ADD_CHECK_NONE | STRING_ADD_ERECT_FRAME)); | 1201 (StringAddFlags)(STRING_ADD_CHECK_NONE | STRING_ADD_ERECT_FRAME)); |
| 1202 GenerateRegisterArgsPush(masm); | 1202 GenerateRegisterArgsPush(masm); |
| 1203 __ TailCallStub(&string_add_stub); | 1203 __ TailCallStub(&string_add_stub); |
| 1204 | 1204 |
| 1205 __ bind(&call_runtime); | 1205 __ bind(&call_runtime); |
| 1206 GenerateTypeTransition(masm); | 1206 GenerateTypeTransition(masm); |
| 1207 } | 1207 } |
| 1208 | 1208 |
| 1209 | 1209 |
| 1210 static void BinaryOpStub_GenerateHeapResultAllocation(MacroAssembler* masm, | 1210 static void BinaryOpStub_GenerateHeapResultAllocation(MacroAssembler* masm, |
| 1211 Label* alloc_failure, | 1211 Label* alloc_failure); |
| 1212 OverwriteMode mode); | |
| 1213 | 1212 |
| 1214 | 1213 |
| 1215 // Input: | 1214 // Input: |
| 1216 // edx: left operand (tagged) | 1215 // edx: left operand (tagged) |
| 1217 // eax: right operand (tagged) | 1216 // eax: right operand (tagged) |
| 1218 // Output: | 1217 // Output: |
| 1219 // eax: result (tagged) | 1218 // eax: result (tagged) |
| 1220 void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) { | 1219 void BinaryOpStub::GenerateInt32Stub(MacroAssembler* masm) { |
| 1221 Label call_runtime; | 1220 Label call_runtime; |
| 1222 ASSERT(Max(left_type_, right_type_) == BinaryOpIC::INT32); | 1221 ASSERT(Max(left_type_, right_type_) == BinaryOpIC::INT32); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1261 case Token::SUB: __ subsd(xmm0, xmm1); break; | 1260 case Token::SUB: __ subsd(xmm0, xmm1); break; |
| 1262 case Token::MUL: __ mulsd(xmm0, xmm1); break; | 1261 case Token::MUL: __ mulsd(xmm0, xmm1); break; |
| 1263 case Token::DIV: __ divsd(xmm0, xmm1); break; | 1262 case Token::DIV: __ divsd(xmm0, xmm1); break; |
| 1264 default: UNREACHABLE(); | 1263 default: UNREACHABLE(); |
| 1265 } | 1264 } |
| 1266 // Check result type if it is currently Int32. | 1265 // Check result type if it is currently Int32. |
| 1267 if (result_type_ <= BinaryOpIC::INT32) { | 1266 if (result_type_ <= BinaryOpIC::INT32) { |
| 1268 FloatingPointHelper::CheckSSE2OperandIsInt32( | 1267 FloatingPointHelper::CheckSSE2OperandIsInt32( |
| 1269 masm, ¬_int32, xmm0, ecx, ecx, xmm2); | 1268 masm, ¬_int32, xmm0, ecx, ecx, xmm2); |
| 1270 } | 1269 } |
| 1271 BinaryOpStub_GenerateHeapResultAllocation(masm, &call_runtime, mode_); | 1270 BinaryOpStub_GenerateHeapResultAllocation(masm, &call_runtime); |
| 1272 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); | 1271 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); |
| 1273 __ ret(0); | 1272 __ ret(0); |
| 1274 } | 1273 } |
| 1275 } else { // SSE2 not available, use FPU. | 1274 } else { // SSE2 not available, use FPU. |
| 1276 FloatingPointHelper::CheckFloatOperands(masm, ¬_floats, ebx); | 1275 FloatingPointHelper::CheckFloatOperands(masm, ¬_floats, ebx); |
| 1277 FloatingPointHelper::LoadFloatOperands( | 1276 FloatingPointHelper::LoadFloatOperands( |
| 1278 masm, | 1277 masm, |
| 1279 ecx, | 1278 ecx, |
| 1280 FloatingPointHelper::ARGS_IN_REGISTERS); | 1279 FloatingPointHelper::ARGS_IN_REGISTERS); |
| 1281 if (op_ == Token::MOD) { | 1280 if (op_ == Token::MOD) { |
| 1282 // The operands are now on the FPU stack, but we don't need them. | 1281 // The operands are now on the FPU stack, but we don't need them. |
| 1283 __ fstp(0); | 1282 __ fstp(0); |
| 1284 __ fstp(0); | 1283 __ fstp(0); |
| 1285 GenerateRegisterArgsPush(masm); | 1284 GenerateRegisterArgsPush(masm); |
| 1286 __ InvokeBuiltin(Builtins::MOD, JUMP_FUNCTION); | 1285 __ InvokeBuiltin(Builtins::MOD, JUMP_FUNCTION); |
| 1287 } else { | 1286 } else { |
| 1288 switch (op_) { | 1287 switch (op_) { |
| 1289 case Token::ADD: __ faddp(1); break; | 1288 case Token::ADD: __ faddp(1); break; |
| 1290 case Token::SUB: __ fsubp(1); break; | 1289 case Token::SUB: __ fsubp(1); break; |
| 1291 case Token::MUL: __ fmulp(1); break; | 1290 case Token::MUL: __ fmulp(1); break; |
| 1292 case Token::DIV: __ fdivp(1); break; | 1291 case Token::DIV: __ fdivp(1); break; |
| 1293 default: UNREACHABLE(); | 1292 default: UNREACHABLE(); |
| 1294 } | 1293 } |
| 1295 Label after_alloc_failure; | 1294 Label after_alloc_failure; |
| 1296 BinaryOpStub_GenerateHeapResultAllocation( | 1295 BinaryOpStub_GenerateHeapResultAllocation( |
| 1297 masm, &after_alloc_failure, mode_); | 1296 masm, &after_alloc_failure); |
| 1298 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); | 1297 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
| 1299 __ ret(0); | 1298 __ ret(0); |
| 1300 __ bind(&after_alloc_failure); | 1299 __ bind(&after_alloc_failure); |
| 1301 __ fstp(0); // Pop FPU stack before calling runtime. | 1300 __ fstp(0); // Pop FPU stack before calling runtime. |
| 1302 __ jmp(&call_runtime); | 1301 __ jmp(&call_runtime); |
| 1303 } | 1302 } |
| 1304 } | 1303 } |
| 1305 | 1304 |
| 1306 __ bind(¬_floats); | 1305 __ bind(¬_floats); |
| 1307 __ bind(¬_int32); | 1306 __ bind(¬_int32); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1345 __ SmiTag(eax); | 1344 __ SmiTag(eax); |
| 1346 __ ret(2 * kPointerSize); // Drop two pushed arguments from the stack. | 1345 __ ret(2 * kPointerSize); // Drop two pushed arguments from the stack. |
| 1347 | 1346 |
| 1348 // All ops except SHR return a signed int32 that we load in | 1347 // All ops except SHR return a signed int32 that we load in |
| 1349 // a HeapNumber. | 1348 // a HeapNumber. |
| 1350 if (op_ != Token::SHR) { | 1349 if (op_ != Token::SHR) { |
| 1351 __ bind(&non_smi_result); | 1350 __ bind(&non_smi_result); |
| 1352 // Allocate a heap number if needed. | 1351 // Allocate a heap number if needed. |
| 1353 __ mov(ebx, eax); // ebx: result | 1352 __ mov(ebx, eax); // ebx: result |
| 1354 Label skip_allocation; | 1353 Label skip_allocation; |
| 1355 switch (mode_) { | 1354 __ AllocateHeapNumber(eax, ecx, edx, &call_runtime); |
| 1356 case OVERWRITE_LEFT: | 1355 __ bind(&skip_allocation); |
| 1357 case OVERWRITE_RIGHT: | |
| 1358 // If the operand was an object, we skip the | |
| 1359 // allocation of a heap number. | |
| 1360 __ mov(eax, Operand(esp, mode_ == OVERWRITE_RIGHT ? | |
| 1361 1 * kPointerSize : 2 * kPointerSize)); | |
| 1362 __ JumpIfNotSmi(eax, &skip_allocation, Label::kNear); | |
| 1363 // Fall through! | |
| 1364 case NO_OVERWRITE: | |
| 1365 __ AllocateHeapNumber(eax, ecx, edx, &call_runtime); | |
| 1366 __ bind(&skip_allocation); | |
| 1367 break; | |
| 1368 default: UNREACHABLE(); | |
| 1369 } | |
| 1370 // Store the result in the HeapNumber and return. | 1356 // Store the result in the HeapNumber and return. |
| 1371 if (CpuFeatures::IsSupported(SSE2)) { | 1357 if (CpuFeatures::IsSupported(SSE2)) { |
| 1372 CpuFeatureScope use_sse2(masm, SSE2); | 1358 CpuFeatureScope use_sse2(masm, SSE2); |
| 1373 __ Cvtsi2sd(xmm0, ebx); | 1359 __ Cvtsi2sd(xmm0, ebx); |
| 1374 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); | 1360 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); |
| 1375 } else { | 1361 } else { |
| 1376 __ mov(Operand(esp, 1 * kPointerSize), ebx); | 1362 __ mov(Operand(esp, 1 * kPointerSize), ebx); |
| 1377 __ fild_s(Operand(esp, 1 * kPointerSize)); | 1363 __ fild_s(Operand(esp, 1 * kPointerSize)); |
| 1378 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); | 1364 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
| 1379 } | 1365 } |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1490 masm, ¬_floats, xmm1, ecx, ecx, xmm2); | 1476 masm, ¬_floats, xmm1, ecx, ecx, xmm2); |
| 1491 } | 1477 } |
| 1492 | 1478 |
| 1493 switch (op_) { | 1479 switch (op_) { |
| 1494 case Token::ADD: __ addsd(xmm0, xmm1); break; | 1480 case Token::ADD: __ addsd(xmm0, xmm1); break; |
| 1495 case Token::SUB: __ subsd(xmm0, xmm1); break; | 1481 case Token::SUB: __ subsd(xmm0, xmm1); break; |
| 1496 case Token::MUL: __ mulsd(xmm0, xmm1); break; | 1482 case Token::MUL: __ mulsd(xmm0, xmm1); break; |
| 1497 case Token::DIV: __ divsd(xmm0, xmm1); break; | 1483 case Token::DIV: __ divsd(xmm0, xmm1); break; |
| 1498 default: UNREACHABLE(); | 1484 default: UNREACHABLE(); |
| 1499 } | 1485 } |
| 1500 BinaryOpStub_GenerateHeapResultAllocation(masm, &call_runtime, mode_); | 1486 BinaryOpStub_GenerateHeapResultAllocation(masm, &call_runtime); |
| 1501 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); | 1487 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); |
| 1502 __ ret(0); | 1488 __ ret(0); |
| 1503 } else { // SSE2 not available, use FPU. | 1489 } else { // SSE2 not available, use FPU. |
| 1504 FloatingPointHelper::CheckFloatOperands(masm, ¬_floats, ebx); | 1490 FloatingPointHelper::CheckFloatOperands(masm, ¬_floats, ebx); |
| 1505 FloatingPointHelper::LoadFloatOperands( | 1491 FloatingPointHelper::LoadFloatOperands( |
| 1506 masm, | 1492 masm, |
| 1507 ecx, | 1493 ecx, |
| 1508 FloatingPointHelper::ARGS_IN_REGISTERS); | 1494 FloatingPointHelper::ARGS_IN_REGISTERS); |
| 1509 switch (op_) { | 1495 switch (op_) { |
| 1510 case Token::ADD: __ faddp(1); break; | 1496 case Token::ADD: __ faddp(1); break; |
| 1511 case Token::SUB: __ fsubp(1); break; | 1497 case Token::SUB: __ fsubp(1); break; |
| 1512 case Token::MUL: __ fmulp(1); break; | 1498 case Token::MUL: __ fmulp(1); break; |
| 1513 case Token::DIV: __ fdivp(1); break; | 1499 case Token::DIV: __ fdivp(1); break; |
| 1514 default: UNREACHABLE(); | 1500 default: UNREACHABLE(); |
| 1515 } | 1501 } |
| 1516 Label after_alloc_failure; | 1502 Label after_alloc_failure; |
| 1517 BinaryOpStub_GenerateHeapResultAllocation( | 1503 BinaryOpStub_GenerateHeapResultAllocation( |
| 1518 masm, &after_alloc_failure, mode_); | 1504 masm, &after_alloc_failure); |
| 1519 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); | 1505 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
| 1520 __ ret(0); | 1506 __ ret(0); |
| 1521 __ bind(&after_alloc_failure); | 1507 __ bind(&after_alloc_failure); |
| 1522 __ fstp(0); // Pop FPU stack before calling runtime. | 1508 __ fstp(0); // Pop FPU stack before calling runtime. |
| 1523 __ jmp(&call_runtime); | 1509 __ jmp(&call_runtime); |
| 1524 } | 1510 } |
| 1525 | 1511 |
| 1526 __ bind(¬_floats); | 1512 __ bind(¬_floats); |
| 1527 GenerateTypeTransition(masm); | 1513 GenerateTypeTransition(masm); |
| 1528 break; | 1514 break; |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1569 __ SmiTag(eax); | 1555 __ SmiTag(eax); |
| 1570 __ ret(2 * kPointerSize); // Drop two pushed arguments from the stack. | 1556 __ ret(2 * kPointerSize); // Drop two pushed arguments from the stack. |
| 1571 | 1557 |
| 1572 // All ops except SHR return a signed int32 that we load in | 1558 // All ops except SHR return a signed int32 that we load in |
| 1573 // a HeapNumber. | 1559 // a HeapNumber. |
| 1574 if (op_ != Token::SHR) { | 1560 if (op_ != Token::SHR) { |
| 1575 __ bind(&non_smi_result); | 1561 __ bind(&non_smi_result); |
| 1576 // Allocate a heap number if needed. | 1562 // Allocate a heap number if needed. |
| 1577 __ mov(ebx, eax); // ebx: result | 1563 __ mov(ebx, eax); // ebx: result |
| 1578 Label skip_allocation; | 1564 Label skip_allocation; |
| 1579 switch (mode_) { | 1565 __ AllocateHeapNumber(eax, ecx, edx, &call_runtime); |
| 1580 case OVERWRITE_LEFT: | 1566 __ bind(&skip_allocation); |
| 1581 case OVERWRITE_RIGHT: | |
| 1582 // If the operand was an object, we skip the | |
| 1583 // allocation of a heap number. | |
| 1584 __ mov(eax, Operand(esp, mode_ == OVERWRITE_RIGHT ? | |
| 1585 1 * kPointerSize : 2 * kPointerSize)); | |
| 1586 __ JumpIfNotSmi(eax, &skip_allocation, Label::kNear); | |
| 1587 // Fall through! | |
| 1588 case NO_OVERWRITE: | |
| 1589 __ AllocateHeapNumber(eax, ecx, edx, &call_runtime); | |
| 1590 __ bind(&skip_allocation); | |
| 1591 break; | |
| 1592 default: UNREACHABLE(); | |
| 1593 } | |
| 1594 // Store the result in the HeapNumber and return. | 1567 // Store the result in the HeapNumber and return. |
| 1595 if (CpuFeatures::IsSupported(SSE2)) { | 1568 if (CpuFeatures::IsSupported(SSE2)) { |
| 1596 CpuFeatureScope use_sse2(masm, SSE2); | 1569 CpuFeatureScope use_sse2(masm, SSE2); |
| 1597 __ Cvtsi2sd(xmm0, ebx); | 1570 __ Cvtsi2sd(xmm0, ebx); |
| 1598 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); | 1571 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); |
| 1599 } else { | 1572 } else { |
| 1600 __ mov(Operand(esp, 1 * kPointerSize), ebx); | 1573 __ mov(Operand(esp, 1 * kPointerSize), ebx); |
| 1601 __ fild_s(Operand(esp, 1 * kPointerSize)); | 1574 __ fild_s(Operand(esp, 1 * kPointerSize)); |
| 1602 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); | 1575 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
| 1603 } | 1576 } |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1683 CpuFeatureScope use_sse2(masm, SSE2); | 1656 CpuFeatureScope use_sse2(masm, SSE2); |
| 1684 FloatingPointHelper::LoadSSE2Operands(masm, ¬_floats); | 1657 FloatingPointHelper::LoadSSE2Operands(masm, ¬_floats); |
| 1685 | 1658 |
| 1686 switch (op_) { | 1659 switch (op_) { |
| 1687 case Token::ADD: __ addsd(xmm0, xmm1); break; | 1660 case Token::ADD: __ addsd(xmm0, xmm1); break; |
| 1688 case Token::SUB: __ subsd(xmm0, xmm1); break; | 1661 case Token::SUB: __ subsd(xmm0, xmm1); break; |
| 1689 case Token::MUL: __ mulsd(xmm0, xmm1); break; | 1662 case Token::MUL: __ mulsd(xmm0, xmm1); break; |
| 1690 case Token::DIV: __ divsd(xmm0, xmm1); break; | 1663 case Token::DIV: __ divsd(xmm0, xmm1); break; |
| 1691 default: UNREACHABLE(); | 1664 default: UNREACHABLE(); |
| 1692 } | 1665 } |
| 1693 BinaryOpStub_GenerateHeapResultAllocation(masm, &call_runtime, mode_); | 1666 BinaryOpStub_GenerateHeapResultAllocation(masm, &call_runtime); |
| 1694 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); | 1667 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); |
| 1695 __ ret(0); | 1668 __ ret(0); |
| 1696 } else { // SSE2 not available, use FPU. | 1669 } else { // SSE2 not available, use FPU. |
| 1697 FloatingPointHelper::CheckFloatOperands(masm, ¬_floats, ebx); | 1670 FloatingPointHelper::CheckFloatOperands(masm, ¬_floats, ebx); |
| 1698 FloatingPointHelper::LoadFloatOperands( | 1671 FloatingPointHelper::LoadFloatOperands( |
| 1699 masm, | 1672 masm, |
| 1700 ecx, | 1673 ecx, |
| 1701 FloatingPointHelper::ARGS_IN_REGISTERS); | 1674 FloatingPointHelper::ARGS_IN_REGISTERS); |
| 1702 switch (op_) { | 1675 switch (op_) { |
| 1703 case Token::ADD: __ faddp(1); break; | 1676 case Token::ADD: __ faddp(1); break; |
| 1704 case Token::SUB: __ fsubp(1); break; | 1677 case Token::SUB: __ fsubp(1); break; |
| 1705 case Token::MUL: __ fmulp(1); break; | 1678 case Token::MUL: __ fmulp(1); break; |
| 1706 case Token::DIV: __ fdivp(1); break; | 1679 case Token::DIV: __ fdivp(1); break; |
| 1707 default: UNREACHABLE(); | 1680 default: UNREACHABLE(); |
| 1708 } | 1681 } |
| 1709 Label after_alloc_failure; | 1682 Label after_alloc_failure; |
| 1710 BinaryOpStub_GenerateHeapResultAllocation( | 1683 BinaryOpStub_GenerateHeapResultAllocation( |
| 1711 masm, &after_alloc_failure, mode_); | 1684 masm, &after_alloc_failure); |
| 1712 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); | 1685 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
| 1713 __ ret(0); | 1686 __ ret(0); |
| 1714 __ bind(&after_alloc_failure); | 1687 __ bind(&after_alloc_failure); |
| 1715 __ fstp(0); // Pop FPU stack before calling runtime. | 1688 __ fstp(0); // Pop FPU stack before calling runtime. |
| 1716 __ jmp(&call_runtime); | 1689 __ jmp(&call_runtime); |
| 1717 } | 1690 } |
| 1718 __ bind(¬_floats); | 1691 __ bind(¬_floats); |
| 1719 break; | 1692 break; |
| 1720 } | 1693 } |
| 1721 case Token::MOD: { | 1694 case Token::MOD: { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1757 __ SmiTag(eax); | 1730 __ SmiTag(eax); |
| 1758 __ ret(2 * kPointerSize); // Drop the arguments from the stack. | 1731 __ ret(2 * kPointerSize); // Drop the arguments from the stack. |
| 1759 | 1732 |
| 1760 // All ops except SHR return a signed int32 that we load in | 1733 // All ops except SHR return a signed int32 that we load in |
| 1761 // a HeapNumber. | 1734 // a HeapNumber. |
| 1762 if (op_ != Token::SHR) { | 1735 if (op_ != Token::SHR) { |
| 1763 __ bind(&non_smi_result); | 1736 __ bind(&non_smi_result); |
| 1764 // Allocate a heap number if needed. | 1737 // Allocate a heap number if needed. |
| 1765 __ mov(ebx, eax); // ebx: result | 1738 __ mov(ebx, eax); // ebx: result |
| 1766 Label skip_allocation; | 1739 Label skip_allocation; |
| 1767 switch (mode_) { | 1740 __ AllocateHeapNumber(eax, ecx, edx, &call_runtime); |
| 1768 case OVERWRITE_LEFT: | 1741 __ bind(&skip_allocation); |
| 1769 case OVERWRITE_RIGHT: | |
| 1770 // If the operand was an object, we skip the | |
| 1771 // allocation of a heap number. | |
| 1772 __ mov(eax, Operand(esp, mode_ == OVERWRITE_RIGHT ? | |
| 1773 1 * kPointerSize : 2 * kPointerSize)); | |
| 1774 __ JumpIfNotSmi(eax, &skip_allocation, Label::kNear); | |
| 1775 // Fall through! | |
| 1776 case NO_OVERWRITE: | |
| 1777 __ AllocateHeapNumber(eax, ecx, edx, &call_runtime); | |
| 1778 __ bind(&skip_allocation); | |
| 1779 break; | |
| 1780 default: UNREACHABLE(); | |
| 1781 } | |
| 1782 // Store the result in the HeapNumber and return. | 1742 // Store the result in the HeapNumber and return. |
| 1783 if (CpuFeatures::IsSupported(SSE2)) { | 1743 if (CpuFeatures::IsSupported(SSE2)) { |
| 1784 CpuFeatureScope use_sse2(masm, SSE2); | 1744 CpuFeatureScope use_sse2(masm, SSE2); |
| 1785 __ Cvtsi2sd(xmm0, ebx); | 1745 __ Cvtsi2sd(xmm0, ebx); |
| 1786 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); | 1746 __ movdbl(FieldOperand(eax, HeapNumber::kValueOffset), xmm0); |
| 1787 } else { | 1747 } else { |
| 1788 __ mov(Operand(esp, 1 * kPointerSize), ebx); | 1748 __ mov(Operand(esp, 1 * kPointerSize), ebx); |
| 1789 __ fild_s(Operand(esp, 1 * kPointerSize)); | 1749 __ fild_s(Operand(esp, 1 * kPointerSize)); |
| 1790 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); | 1750 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); |
| 1791 } | 1751 } |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1858 (StringAddFlags)(STRING_ADD_CHECK_LEFT | STRING_ADD_ERECT_FRAME)); | 1818 (StringAddFlags)(STRING_ADD_CHECK_LEFT | STRING_ADD_ERECT_FRAME)); |
| 1859 GenerateRegisterArgsPush(masm); | 1819 GenerateRegisterArgsPush(masm); |
| 1860 __ TailCallStub(&string_add_right_stub); | 1820 __ TailCallStub(&string_add_right_stub); |
| 1861 | 1821 |
| 1862 // Neither argument is a string. | 1822 // Neither argument is a string. |
| 1863 __ bind(&call_runtime); | 1823 __ bind(&call_runtime); |
| 1864 } | 1824 } |
| 1865 | 1825 |
| 1866 | 1826 |
| 1867 static void BinaryOpStub_GenerateHeapResultAllocation(MacroAssembler* masm, | 1827 static void BinaryOpStub_GenerateHeapResultAllocation(MacroAssembler* masm, |
| 1868 Label* alloc_failure, | 1828 Label* alloc_failure) { |
| 1869 OverwriteMode mode) { | |
| 1870 Label skip_allocation; | 1829 Label skip_allocation; |
| 1871 switch (mode) { | 1830 // Allocate a heap number for the result. Keep eax and edx intact |
| 1872 case OVERWRITE_LEFT: { | 1831 // for the possible runtime call. |
| 1873 // If the argument in edx is already an object, we skip the | 1832 __ AllocateHeapNumber(ebx, ecx, no_reg, alloc_failure); |
| 1874 // allocation of a heap number. | 1833 // Now eax can be overwritten losing one of the arguments as we are |
| 1875 __ JumpIfNotSmi(edx, &skip_allocation, Label::kNear); | 1834 // now done and will not need it any more. |
| 1876 // Allocate a heap number for the result. Keep eax and edx intact | 1835 __ mov(eax, ebx); |
| 1877 // for the possible runtime call. | 1836 __ bind(&skip_allocation); |
| 1878 __ AllocateHeapNumber(ebx, ecx, no_reg, alloc_failure); | |
| 1879 // Now edx can be overwritten losing one of the arguments as we are | |
| 1880 // now done and will not need it any more. | |
| 1881 __ mov(edx, ebx); | |
| 1882 __ bind(&skip_allocation); | |
| 1883 // Use object in edx as a result holder | |
| 1884 __ mov(eax, edx); | |
| 1885 break; | |
| 1886 } | |
| 1887 case OVERWRITE_RIGHT: | |
| 1888 // If the argument in eax is already an object, we skip the | |
| 1889 // allocation of a heap number. | |
| 1890 __ JumpIfNotSmi(eax, &skip_allocation, Label::kNear); | |
| 1891 // Fall through! | |
| 1892 case NO_OVERWRITE: | |
| 1893 // Allocate a heap number for the result. Keep eax and edx intact | |
| 1894 // for the possible runtime call. | |
| 1895 __ AllocateHeapNumber(ebx, ecx, no_reg, alloc_failure); | |
| 1896 // Now eax can be overwritten losing one of the arguments as we are | |
| 1897 // now done and will not need it any more. | |
| 1898 __ mov(eax, ebx); | |
| 1899 __ bind(&skip_allocation); | |
| 1900 break; | |
| 1901 default: UNREACHABLE(); | |
| 1902 } | |
| 1903 } | 1837 } |
| 1904 | 1838 |
| 1905 | 1839 |
| 1906 void BinaryOpStub::GenerateRegisterArgsPush(MacroAssembler* masm) { | 1840 void BinaryOpStub::GenerateRegisterArgsPush(MacroAssembler* masm) { |
| 1907 __ pop(ecx); | 1841 __ pop(ecx); |
| 1908 __ push(edx); | 1842 __ push(edx); |
| 1909 __ push(eax); | 1843 __ push(eax); |
| 1910 __ push(ecx); | 1844 __ push(ecx); |
| 1911 } | 1845 } |
| 1912 | 1846 |
| (...skipping 5634 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7547 __ bind(&fast_elements_case); | 7481 __ bind(&fast_elements_case); |
| 7548 GenerateCase(masm, FAST_ELEMENTS); | 7482 GenerateCase(masm, FAST_ELEMENTS); |
| 7549 } | 7483 } |
| 7550 | 7484 |
| 7551 | 7485 |
| 7552 #undef __ | 7486 #undef __ |
| 7553 | 7487 |
| 7554 } } // namespace v8::internal | 7488 } } // namespace v8::internal |
| 7555 | 7489 |
| 7556 #endif // V8_TARGET_ARCH_IA32 | 7490 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |