| 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 1084 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1095 default: | 1095 default: |
| 1096 UNREACHABLE(); | 1096 UNREACHABLE(); |
| 1097 } | 1097 } |
| 1098 UNREACHABLE(); | 1098 UNREACHABLE(); |
| 1099 return NumberInfo::Unknown(); | 1099 return NumberInfo::Unknown(); |
| 1100 } | 1100 } |
| 1101 | 1101 |
| 1102 | 1102 |
| 1103 void CodeGenerator::GenericBinaryOperation(Token::Value op, | 1103 void CodeGenerator::GenericBinaryOperation(Token::Value op, |
| 1104 StaticType* type, | 1104 StaticType* type, |
| 1105 OverwriteMode overwrite_mode) { | 1105 OverwriteMode overwrite_mode, |
| 1106 bool no_negative_zero) { |
| 1106 Comment cmnt(masm_, "[ BinaryOperation"); | 1107 Comment cmnt(masm_, "[ BinaryOperation"); |
| 1107 Comment cmnt_token(masm_, Token::String(op)); | 1108 Comment cmnt_token(masm_, Token::String(op)); |
| 1108 | 1109 |
| 1109 if (op == Token::COMMA) { | 1110 if (op == Token::COMMA) { |
| 1110 // Simply discard left value. | 1111 // Simply discard left value. |
| 1111 frame_->Nip(1); | 1112 frame_->Nip(1); |
| 1112 return; | 1113 return; |
| 1113 } | 1114 } |
| 1114 | 1115 |
| 1115 Result right = frame_->Pop(); | 1116 Result right = frame_->Pop(); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1163 Result answer; | 1164 Result answer; |
| 1164 if (left_is_non_smi_constant || right_is_non_smi_constant) { | 1165 if (left_is_non_smi_constant || right_is_non_smi_constant) { |
| 1165 // Go straight to the slow case, with no smi code. | 1166 // Go straight to the slow case, with no smi code. |
| 1166 GenericBinaryOpStub stub(op, | 1167 GenericBinaryOpStub stub(op, |
| 1167 overwrite_mode, | 1168 overwrite_mode, |
| 1168 NO_SMI_CODE_IN_STUB, | 1169 NO_SMI_CODE_IN_STUB, |
| 1169 operands_type); | 1170 operands_type); |
| 1170 answer = stub.GenerateCall(masm_, frame_, &left, &right); | 1171 answer = stub.GenerateCall(masm_, frame_, &left, &right); |
| 1171 } else if (right_is_smi_constant) { | 1172 } else if (right_is_smi_constant) { |
| 1172 answer = ConstantSmiBinaryOperation(op, &left, right.handle(), | 1173 answer = ConstantSmiBinaryOperation(op, &left, right.handle(), |
| 1173 type, false, overwrite_mode); | 1174 type, false, overwrite_mode, |
| 1175 no_negative_zero); |
| 1174 } else if (left_is_smi_constant) { | 1176 } else if (left_is_smi_constant) { |
| 1175 answer = ConstantSmiBinaryOperation(op, &right, left.handle(), | 1177 answer = ConstantSmiBinaryOperation(op, &right, left.handle(), |
| 1176 type, true, overwrite_mode); | 1178 type, true, overwrite_mode, |
| 1179 no_negative_zero); |
| 1177 } else { | 1180 } else { |
| 1178 // Set the flags based on the operation, type and loop nesting level. | 1181 // Set the flags based on the operation, type and loop nesting level. |
| 1179 // Bit operations always assume they likely operate on Smis. Still only | 1182 // Bit operations always assume they likely operate on Smis. Still only |
| 1180 // generate the inline Smi check code if this operation is part of a loop. | 1183 // generate the inline Smi check code if this operation is part of a loop. |
| 1181 // For all other operations only inline the Smi check code for likely smis | 1184 // For all other operations only inline the Smi check code for likely smis |
| 1182 // if the operation is part of a loop. | 1185 // if the operation is part of a loop. |
| 1183 if (loop_nesting() > 0 && | 1186 if (loop_nesting() > 0 && |
| 1184 (Token::IsBitOp(op) || | 1187 (Token::IsBitOp(op) || |
| 1185 operands_type.IsInteger32() || | 1188 operands_type.IsInteger32() || |
| 1186 type->IsLikelySmi())) { | 1189 type->IsLikelySmi())) { |
| 1187 answer = LikelySmiBinaryOperation(op, &left, &right, overwrite_mode); | 1190 answer = LikelySmiBinaryOperation(op, &left, &right, |
| 1191 overwrite_mode, no_negative_zero); |
| 1188 } else { | 1192 } else { |
| 1189 GenericBinaryOpStub stub(op, | 1193 GenericBinaryOpStub stub(op, |
| 1190 overwrite_mode, | 1194 overwrite_mode, |
| 1191 NO_GENERIC_BINARY_FLAGS, | 1195 NO_GENERIC_BINARY_FLAGS, |
| 1192 operands_type); | 1196 operands_type); |
| 1193 answer = stub.GenerateCall(masm_, frame_, &left, &right); | 1197 answer = stub.GenerateCall(masm_, frame_, &left, &right); |
| 1194 } | 1198 } |
| 1195 } | 1199 } |
| 1196 | 1200 |
| 1197 answer.set_number_info(result_type); | 1201 answer.set_number_info(result_type); |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1284 Register left, Register right, Register scratch, | 1288 Register left, Register right, Register scratch, |
| 1285 NumberInfo left_info, NumberInfo right_info, | 1289 NumberInfo left_info, NumberInfo right_info, |
| 1286 DeferredInlineBinaryOperation* deferred); | 1290 DeferredInlineBinaryOperation* deferred); |
| 1287 | 1291 |
| 1288 | 1292 |
| 1289 // Implements a binary operation using a deferred code object and some | 1293 // Implements a binary operation using a deferred code object and some |
| 1290 // inline code to operate on smis quickly. | 1294 // inline code to operate on smis quickly. |
| 1291 Result CodeGenerator::LikelySmiBinaryOperation(Token::Value op, | 1295 Result CodeGenerator::LikelySmiBinaryOperation(Token::Value op, |
| 1292 Result* left, | 1296 Result* left, |
| 1293 Result* right, | 1297 Result* right, |
| 1294 OverwriteMode overwrite_mode) { | 1298 OverwriteMode overwrite_mode, |
| 1299 bool no_negative_zero) { |
| 1295 Result answer; | 1300 Result answer; |
| 1296 // Special handling of div and mod because they use fixed registers. | 1301 // Special handling of div and mod because they use fixed registers. |
| 1297 if (op == Token::DIV || op == Token::MOD) { | 1302 if (op == Token::DIV || op == Token::MOD) { |
| 1298 // We need eax as the quotient register, edx as the remainder | 1303 // We need eax as the quotient register, edx as the remainder |
| 1299 // register, neither left nor right in eax or edx, and left copied | 1304 // register, neither left nor right in eax or edx, and left copied |
| 1300 // to eax. | 1305 // to eax. |
| 1301 Result quotient; | 1306 Result quotient; |
| 1302 Result remainder; | 1307 Result remainder; |
| 1303 bool left_is_in_eax = false; | 1308 bool left_is_in_eax = false; |
| 1304 // Step 1: get eax for quotient. | 1309 // Step 1: get eax for quotient. |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1388 __ test(right->reg(), Operand(right->reg())); | 1393 __ test(right->reg(), Operand(right->reg())); |
| 1389 deferred->Branch(zero); | 1394 deferred->Branch(zero); |
| 1390 // Divide edx:eax by the right operand. | 1395 // Divide edx:eax by the right operand. |
| 1391 __ idiv(right->reg()); | 1396 __ idiv(right->reg()); |
| 1392 | 1397 |
| 1393 // Complete the operation. | 1398 // Complete the operation. |
| 1394 if (op == Token::DIV) { | 1399 if (op == Token::DIV) { |
| 1395 // Check for negative zero result. If result is zero, and divisor | 1400 // Check for negative zero result. If result is zero, and divisor |
| 1396 // is negative, return a floating point negative zero. The | 1401 // is negative, return a floating point negative zero. The |
| 1397 // virtual frame is unchanged in this block, so local control flow | 1402 // virtual frame is unchanged in this block, so local control flow |
| 1398 // can use a Label rather than a JumpTarget. | 1403 // can use a Label rather than a JumpTarget. If the context of this |
| 1399 Label non_zero_result; | 1404 // expression will treat -0 like 0, do not do this test. |
| 1400 __ test(left->reg(), Operand(left->reg())); | 1405 if (!no_negative_zero) { |
| 1401 __ j(not_zero, &non_zero_result); | 1406 Label non_zero_result; |
| 1402 __ test(right->reg(), Operand(right->reg())); | 1407 __ test(left->reg(), Operand(left->reg())); |
| 1403 deferred->Branch(negative); | 1408 __ j(not_zero, &non_zero_result); |
| 1404 __ bind(&non_zero_result); | 1409 __ test(right->reg(), Operand(right->reg())); |
| 1410 deferred->Branch(negative); |
| 1411 __ bind(&non_zero_result); |
| 1412 } |
| 1405 // Check for the corner case of dividing the most negative smi by | 1413 // Check for the corner case of dividing the most negative smi by |
| 1406 // -1. We cannot use the overflow flag, since it is not set by | 1414 // -1. We cannot use the overflow flag, since it is not set by |
| 1407 // idiv instruction. | 1415 // idiv instruction. |
| 1408 ASSERT(kSmiTag == 0 && kSmiTagSize == 1); | 1416 ASSERT(kSmiTag == 0 && kSmiTagSize == 1); |
| 1409 __ cmp(eax, 0x40000000); | 1417 __ cmp(eax, 0x40000000); |
| 1410 deferred->Branch(equal); | 1418 deferred->Branch(equal); |
| 1411 // Check that the remainder is zero. | 1419 // Check that the remainder is zero. |
| 1412 __ test(edx, Operand(edx)); | 1420 __ test(edx, Operand(edx)); |
| 1413 deferred->Branch(not_zero); | 1421 deferred->Branch(not_zero); |
| 1414 // Tag the result and store it in the quotient register. | 1422 // Tag the result and store it in the quotient register. |
| 1415 __ SmiTag(eax); | 1423 __ SmiTag(eax); |
| 1416 deferred->BindExit(); | 1424 deferred->BindExit(); |
| 1417 left->Unuse(); | 1425 left->Unuse(); |
| 1418 right->Unuse(); | 1426 right->Unuse(); |
| 1419 answer = quotient; | 1427 answer = quotient; |
| 1420 } else { | 1428 } else { |
| 1421 ASSERT(op == Token::MOD); | 1429 ASSERT(op == Token::MOD); |
| 1422 // Check for a negative zero result. If the result is zero, and | 1430 // Check for a negative zero result. If the result is zero, and |
| 1423 // the dividend is negative, return a floating point negative | 1431 // the dividend is negative, return a floating point negative |
| 1424 // zero. The frame is unchanged in this block, so local control | 1432 // zero. The frame is unchanged in this block, so local control |
| 1425 // flow can use a Label rather than a JumpTarget. | 1433 // flow can use a Label rather than a JumpTarget. |
| 1426 Label non_zero_result; | 1434 if (!no_negative_zero) { |
| 1427 __ test(edx, Operand(edx)); | 1435 Label non_zero_result; |
| 1428 __ j(not_zero, &non_zero_result, taken); | 1436 __ test(edx, Operand(edx)); |
| 1429 __ test(left->reg(), Operand(left->reg())); | 1437 __ j(not_zero, &non_zero_result, taken); |
| 1430 deferred->Branch(negative); | 1438 __ test(left->reg(), Operand(left->reg())); |
| 1431 __ bind(&non_zero_result); | 1439 deferred->Branch(negative); |
| 1440 __ bind(&non_zero_result); |
| 1441 } |
| 1432 deferred->BindExit(); | 1442 deferred->BindExit(); |
| 1433 left->Unuse(); | 1443 left->Unuse(); |
| 1434 right->Unuse(); | 1444 right->Unuse(); |
| 1435 answer = remainder; | 1445 answer = remainder; |
| 1436 } | 1446 } |
| 1437 ASSERT(answer.is_valid()); | 1447 ASSERT(answer.is_valid()); |
| 1438 return answer; | 1448 return answer; |
| 1439 } | 1449 } |
| 1440 | 1450 |
| 1441 // Special handling of shift operations because they use fixed | 1451 // Special handling of shift operations because they use fixed |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1564 // Left-hand operand has been copied into answer. | 1574 // Left-hand operand has been copied into answer. |
| 1565 __ SmiUntag(answer.reg()); | 1575 __ SmiUntag(answer.reg()); |
| 1566 // Do multiplication of smis, leaving result in answer. | 1576 // Do multiplication of smis, leaving result in answer. |
| 1567 __ imul(answer.reg(), Operand(right->reg())); | 1577 __ imul(answer.reg(), Operand(right->reg())); |
| 1568 // Go slow on overflows. | 1578 // Go slow on overflows. |
| 1569 deferred->Branch(overflow); | 1579 deferred->Branch(overflow); |
| 1570 // Check for negative zero result. If product is zero, and one | 1580 // Check for negative zero result. If product is zero, and one |
| 1571 // argument is negative, go to slow case. The frame is unchanged | 1581 // argument is negative, go to slow case. The frame is unchanged |
| 1572 // in this block, so local control flow can use a Label rather | 1582 // in this block, so local control flow can use a Label rather |
| 1573 // than a JumpTarget. | 1583 // than a JumpTarget. |
| 1574 Label non_zero_result; | 1584 if (!no_negative_zero) { |
| 1575 __ test(answer.reg(), Operand(answer.reg())); | 1585 Label non_zero_result; |
| 1576 __ j(not_zero, &non_zero_result, taken); | 1586 __ test(answer.reg(), Operand(answer.reg())); |
| 1577 __ mov(answer.reg(), left->reg()); | 1587 __ j(not_zero, &non_zero_result, taken); |
| 1578 __ or_(answer.reg(), Operand(right->reg())); | 1588 __ mov(answer.reg(), left->reg()); |
| 1579 deferred->Branch(negative); | 1589 __ or_(answer.reg(), Operand(right->reg())); |
| 1580 __ xor_(answer.reg(), Operand(answer.reg())); // Positive 0 is correct. | 1590 deferred->Branch(negative); |
| 1581 __ bind(&non_zero_result); | 1591 __ xor_(answer.reg(), Operand(answer.reg())); // Positive 0 is correct. |
| 1592 __ bind(&non_zero_result); |
| 1593 } |
| 1582 break; | 1594 break; |
| 1583 } | 1595 } |
| 1584 | 1596 |
| 1585 case Token::BIT_OR: | 1597 case Token::BIT_OR: |
| 1586 __ or_(answer.reg(), Operand(right->reg())); | 1598 __ or_(answer.reg(), Operand(right->reg())); |
| 1587 break; | 1599 break; |
| 1588 | 1600 |
| 1589 case Token::BIT_AND: | 1601 case Token::BIT_AND: |
| 1590 __ and_(answer.reg(), Operand(right->reg())); | 1602 __ and_(answer.reg(), Operand(right->reg())); |
| 1591 break; | 1603 break; |
| (...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1810 igostub.GenerateCall(masm_, dst_, value_); | 1822 igostub.GenerateCall(masm_, dst_, value_); |
| 1811 if (!dst_.is(eax)) __ mov(dst_, eax); | 1823 if (!dst_.is(eax)) __ mov(dst_, eax); |
| 1812 } | 1824 } |
| 1813 | 1825 |
| 1814 | 1826 |
| 1815 Result CodeGenerator::ConstantSmiBinaryOperation(Token::Value op, | 1827 Result CodeGenerator::ConstantSmiBinaryOperation(Token::Value op, |
| 1816 Result* operand, | 1828 Result* operand, |
| 1817 Handle<Object> value, | 1829 Handle<Object> value, |
| 1818 StaticType* type, | 1830 StaticType* type, |
| 1819 bool reversed, | 1831 bool reversed, |
| 1820 OverwriteMode overwrite_mode) { | 1832 OverwriteMode overwrite_mode, |
| 1833 bool no_negative_zero) { |
| 1821 // NOTE: This is an attempt to inline (a bit) more of the code for | 1834 // NOTE: This is an attempt to inline (a bit) more of the code for |
| 1822 // some possible smi operations (like + and -) when (at least) one | 1835 // some possible smi operations (like + and -) when (at least) one |
| 1823 // of the operands is a constant smi. | 1836 // of the operands is a constant smi. |
| 1824 // Consumes the argument "operand". | 1837 // Consumes the argument "operand". |
| 1825 // TODO(199): Optimize some special cases of operations involving a | 1838 // TODO(199): Optimize some special cases of operations involving a |
| 1826 // smi literal (multiply by 2, shift by 0, etc.). | 1839 // smi literal (multiply by 2, shift by 0, etc.). |
| 1827 if (IsUnsafeSmi(value)) { | 1840 if (IsUnsafeSmi(value)) { |
| 1828 Result unsafe_operand(value); | 1841 Result unsafe_operand(value); |
| 1829 if (reversed) { | 1842 if (reversed) { |
| 1830 return LikelySmiBinaryOperation(op, &unsafe_operand, operand, | 1843 return LikelySmiBinaryOperation(op, &unsafe_operand, operand, |
| 1831 overwrite_mode); | 1844 overwrite_mode, no_negative_zero); |
| 1832 } else { | 1845 } else { |
| 1833 return LikelySmiBinaryOperation(op, operand, &unsafe_operand, | 1846 return LikelySmiBinaryOperation(op, operand, &unsafe_operand, |
| 1834 overwrite_mode); | 1847 overwrite_mode, no_negative_zero); |
| 1835 } | 1848 } |
| 1836 } | 1849 } |
| 1837 | 1850 |
| 1838 // Get the literal value. | 1851 // Get the literal value. |
| 1839 Smi* smi_value = Smi::cast(*value); | 1852 Smi* smi_value = Smi::cast(*value); |
| 1840 int int_value = smi_value->value(); | 1853 int int_value = smi_value->value(); |
| 1841 | 1854 |
| 1842 Result answer; | 1855 Result answer; |
| 1843 switch (op) { | 1856 switch (op) { |
| 1844 case Token::ADD: { | 1857 case Token::ADD: { |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1904 } | 1917 } |
| 1905 deferred->BindExit(); | 1918 deferred->BindExit(); |
| 1906 operand->Unuse(); | 1919 operand->Unuse(); |
| 1907 break; | 1920 break; |
| 1908 } | 1921 } |
| 1909 | 1922 |
| 1910 case Token::SAR: | 1923 case Token::SAR: |
| 1911 if (reversed) { | 1924 if (reversed) { |
| 1912 Result constant_operand(value); | 1925 Result constant_operand(value); |
| 1913 answer = LikelySmiBinaryOperation(op, &constant_operand, operand, | 1926 answer = LikelySmiBinaryOperation(op, &constant_operand, operand, |
| 1914 overwrite_mode); | 1927 overwrite_mode, no_negative_zero); |
| 1915 } else { | 1928 } else { |
| 1916 // Only the least significant 5 bits of the shift value are used. | 1929 // Only the least significant 5 bits of the shift value are used. |
| 1917 // In the slow case, this masking is done inside the runtime call. | 1930 // In the slow case, this masking is done inside the runtime call. |
| 1918 int shift_value = int_value & 0x1f; | 1931 int shift_value = int_value & 0x1f; |
| 1919 operand->ToRegister(); | 1932 operand->ToRegister(); |
| 1920 frame_->Spill(operand->reg()); | 1933 frame_->Spill(operand->reg()); |
| 1921 if (!operand->number_info().IsSmi()) { | 1934 if (!operand->number_info().IsSmi()) { |
| 1922 DeferredInlineSmiOperation* deferred = | 1935 DeferredInlineSmiOperation* deferred = |
| 1923 new DeferredInlineSmiOperation(op, | 1936 new DeferredInlineSmiOperation(op, |
| 1924 operand->reg(), | 1937 operand->reg(), |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1940 } | 1953 } |
| 1941 } | 1954 } |
| 1942 answer = *operand; | 1955 answer = *operand; |
| 1943 } | 1956 } |
| 1944 break; | 1957 break; |
| 1945 | 1958 |
| 1946 case Token::SHR: | 1959 case Token::SHR: |
| 1947 if (reversed) { | 1960 if (reversed) { |
| 1948 Result constant_operand(value); | 1961 Result constant_operand(value); |
| 1949 answer = LikelySmiBinaryOperation(op, &constant_operand, operand, | 1962 answer = LikelySmiBinaryOperation(op, &constant_operand, operand, |
| 1950 overwrite_mode); | 1963 overwrite_mode, no_negative_zero); |
| 1951 } else { | 1964 } else { |
| 1952 // Only the least significant 5 bits of the shift value are used. | 1965 // Only the least significant 5 bits of the shift value are used. |
| 1953 // In the slow case, this masking is done inside the runtime call. | 1966 // In the slow case, this masking is done inside the runtime call. |
| 1954 int shift_value = int_value & 0x1f; | 1967 int shift_value = int_value & 0x1f; |
| 1955 operand->ToRegister(); | 1968 operand->ToRegister(); |
| 1956 answer = allocator()->Allocate(); | 1969 answer = allocator()->Allocate(); |
| 1957 ASSERT(answer.is_valid()); | 1970 ASSERT(answer.is_valid()); |
| 1958 DeferredInlineSmiOperation* deferred = | 1971 DeferredInlineSmiOperation* deferred = |
| 1959 new DeferredInlineSmiOperation(op, | 1972 new DeferredInlineSmiOperation(op, |
| 1960 answer.reg(), | 1973 answer.reg(), |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2133 deferred->Branch(not_zero); // Branch if non-smi or odd smi. | 2146 deferred->Branch(not_zero); // Branch if non-smi or odd smi. |
| 2134 __ sar(operand->reg(), 1); | 2147 __ sar(operand->reg(), 1); |
| 2135 deferred->BindExit(); | 2148 deferred->BindExit(); |
| 2136 answer = *operand; | 2149 answer = *operand; |
| 2137 } else { | 2150 } else { |
| 2138 // Cannot fall through MOD to default case, so we duplicate the | 2151 // Cannot fall through MOD to default case, so we duplicate the |
| 2139 // default case here. | 2152 // default case here. |
| 2140 Result constant_operand(value); | 2153 Result constant_operand(value); |
| 2141 if (reversed) { | 2154 if (reversed) { |
| 2142 answer = LikelySmiBinaryOperation(op, &constant_operand, operand, | 2155 answer = LikelySmiBinaryOperation(op, &constant_operand, operand, |
| 2143 overwrite_mode); | 2156 overwrite_mode, no_negative_zero); |
| 2144 } else { | 2157 } else { |
| 2145 answer = LikelySmiBinaryOperation(op, operand, &constant_operand, | 2158 answer = LikelySmiBinaryOperation(op, operand, &constant_operand, |
| 2146 overwrite_mode); | 2159 overwrite_mode, no_negative_zero); |
| 2147 } | 2160 } |
| 2148 } | 2161 } |
| 2149 break; | 2162 break; |
| 2150 // Generate inline code for mod of powers of 2 and negative powers of 2. | 2163 // Generate inline code for mod of powers of 2 and negative powers of 2. |
| 2151 case Token::MOD: | 2164 case Token::MOD: |
| 2152 if (!reversed && | 2165 if (!reversed && |
| 2153 int_value != 0 && | 2166 int_value != 0 && |
| 2154 (IsPowerOf2(int_value) || IsPowerOf2(-int_value))) { | 2167 (IsPowerOf2(int_value) || IsPowerOf2(-int_value))) { |
| 2155 operand->ToRegister(); | 2168 operand->ToRegister(); |
| 2156 frame_->Spill(operand->reg()); | 2169 frame_->Spill(operand->reg()); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 2173 deferred->BindExit(); | 2186 deferred->BindExit(); |
| 2174 answer = *operand; | 2187 answer = *operand; |
| 2175 break; | 2188 break; |
| 2176 } | 2189 } |
| 2177 // Fall through if we did not find a power of 2 on the right hand side! | 2190 // Fall through if we did not find a power of 2 on the right hand side! |
| 2178 | 2191 |
| 2179 default: { | 2192 default: { |
| 2180 Result constant_operand(value); | 2193 Result constant_operand(value); |
| 2181 if (reversed) { | 2194 if (reversed) { |
| 2182 answer = LikelySmiBinaryOperation(op, &constant_operand, operand, | 2195 answer = LikelySmiBinaryOperation(op, &constant_operand, operand, |
| 2183 overwrite_mode); | 2196 overwrite_mode, no_negative_zero); |
| 2184 } else { | 2197 } else { |
| 2185 answer = LikelySmiBinaryOperation(op, operand, &constant_operand, | 2198 answer = LikelySmiBinaryOperation(op, operand, &constant_operand, |
| 2186 overwrite_mode); | 2199 overwrite_mode, no_negative_zero); |
| 2187 } | 2200 } |
| 2188 break; | 2201 break; |
| 2189 } | 2202 } |
| 2190 } | 2203 } |
| 2191 ASSERT(answer.is_valid()); | 2204 ASSERT(answer.is_valid()); |
| 2192 return answer; | 2205 return answer; |
| 2193 } | 2206 } |
| 2194 | 2207 |
| 2195 | 2208 |
| 2196 static bool CouldBeNaN(const Result& result) { | 2209 static bool CouldBeNaN(const Result& result) { |
| (...skipping 2746 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4943 if (node->is_compound()) { | 4956 if (node->is_compound()) { |
| 4944 Result result = LoadFromSlotCheckForArguments(slot, NOT_INSIDE_TYPEOF); | 4957 Result result = LoadFromSlotCheckForArguments(slot, NOT_INSIDE_TYPEOF); |
| 4945 frame()->Push(&result); | 4958 frame()->Push(&result); |
| 4946 Load(node->value()); | 4959 Load(node->value()); |
| 4947 | 4960 |
| 4948 bool overwrite_value = | 4961 bool overwrite_value = |
| 4949 (node->value()->AsBinaryOperation() != NULL && | 4962 (node->value()->AsBinaryOperation() != NULL && |
| 4950 node->value()->AsBinaryOperation()->ResultOverwriteAllowed()); | 4963 node->value()->AsBinaryOperation()->ResultOverwriteAllowed()); |
| 4951 GenericBinaryOperation(node->binary_op(), | 4964 GenericBinaryOperation(node->binary_op(), |
| 4952 node->type(), | 4965 node->type(), |
| 4953 overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE); | 4966 overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE, |
| 4967 node->no_negative_zero()); |
| 4954 } else { | 4968 } else { |
| 4955 Load(node->value()); | 4969 Load(node->value()); |
| 4956 } | 4970 } |
| 4957 | 4971 |
| 4958 // Perform the assignment. | 4972 // Perform the assignment. |
| 4959 if (var->mode() != Variable::CONST || node->op() == Token::INIT_CONST) { | 4973 if (var->mode() != Variable::CONST || node->op() == Token::INIT_CONST) { |
| 4960 CodeForSourcePosition(node->position()); | 4974 CodeForSourcePosition(node->position()); |
| 4961 StoreToSlot(slot, | 4975 StoreToSlot(slot, |
| 4962 node->op() == Token::INIT_CONST ? CONST_INIT : NOT_CONST_INIT); | 4976 node->op() == Token::INIT_CONST ? CONST_INIT : NOT_CONST_INIT); |
| 4963 } | 4977 } |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5020 } | 5034 } |
| 5021 Result value = EmitNamedLoad(name, var != NULL); | 5035 Result value = EmitNamedLoad(name, var != NULL); |
| 5022 frame()->Push(&value); | 5036 frame()->Push(&value); |
| 5023 Load(node->value()); | 5037 Load(node->value()); |
| 5024 | 5038 |
| 5025 bool overwrite_value = | 5039 bool overwrite_value = |
| 5026 (node->value()->AsBinaryOperation() != NULL && | 5040 (node->value()->AsBinaryOperation() != NULL && |
| 5027 node->value()->AsBinaryOperation()->ResultOverwriteAllowed()); | 5041 node->value()->AsBinaryOperation()->ResultOverwriteAllowed()); |
| 5028 GenericBinaryOperation(node->binary_op(), | 5042 GenericBinaryOperation(node->binary_op(), |
| 5029 node->type(), | 5043 node->type(), |
| 5030 overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE); | 5044 overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE, |
| 5045 node->no_negative_zero()); |
| 5031 } else { | 5046 } else { |
| 5032 Load(node->value()); | 5047 Load(node->value()); |
| 5033 } | 5048 } |
| 5034 | 5049 |
| 5035 // Perform the assignment. It is safe to ignore constants here. | 5050 // Perform the assignment. It is safe to ignore constants here. |
| 5036 ASSERT(var == NULL || var->mode() != Variable::CONST); | 5051 ASSERT(var == NULL || var->mode() != Variable::CONST); |
| 5037 ASSERT_NE(Token::INIT_CONST, node->op()); | 5052 ASSERT_NE(Token::INIT_CONST, node->op()); |
| 5038 if (is_trivial_receiver) { | 5053 if (is_trivial_receiver) { |
| 5039 Result value = frame()->Pop(); | 5054 Result value = frame()->Pop(); |
| 5040 frame()->Push(prop->obj()); | 5055 frame()->Push(prop->obj()); |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5099 frame()->PushElementAt(1); | 5114 frame()->PushElementAt(1); |
| 5100 Result value = EmitKeyedLoad(); | 5115 Result value = EmitKeyedLoad(); |
| 5101 frame()->Push(&value); | 5116 frame()->Push(&value); |
| 5102 Load(node->value()); | 5117 Load(node->value()); |
| 5103 | 5118 |
| 5104 bool overwrite_value = | 5119 bool overwrite_value = |
| 5105 (node->value()->AsBinaryOperation() != NULL && | 5120 (node->value()->AsBinaryOperation() != NULL && |
| 5106 node->value()->AsBinaryOperation()->ResultOverwriteAllowed()); | 5121 node->value()->AsBinaryOperation()->ResultOverwriteAllowed()); |
| 5107 GenericBinaryOperation(node->binary_op(), | 5122 GenericBinaryOperation(node->binary_op(), |
| 5108 node->type(), | 5123 node->type(), |
| 5109 overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE); | 5124 overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE, |
| 5125 node->no_negative_zero()); |
| 5110 } else { | 5126 } else { |
| 5111 Load(node->value()); | 5127 Load(node->value()); |
| 5112 } | 5128 } |
| 5113 | 5129 |
| 5114 // Perform the assignment. It is safe to ignore constants here. | 5130 // Perform the assignment. It is safe to ignore constants here. |
| 5115 ASSERT(node->op() != Token::INIT_CONST); | 5131 ASSERT(node->op() != Token::INIT_CONST); |
| 5116 CodeForSourcePosition(node->position()); | 5132 CodeForSourcePosition(node->position()); |
| 5117 Result answer = EmitKeyedStore(prop->key()->type()); | 5133 Result answer = EmitKeyedStore(prop->key()->type()); |
| 5118 frame()->Push(&answer); | 5134 frame()->Push(&answer); |
| 5119 | 5135 |
| (...skipping 1741 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6861 | 6877 |
| 6862 if (node->left()->IsTrivial()) { | 6878 if (node->left()->IsTrivial()) { |
| 6863 Load(node->right()); | 6879 Load(node->right()); |
| 6864 Result right = frame_->Pop(); | 6880 Result right = frame_->Pop(); |
| 6865 frame_->Push(node->left()); | 6881 frame_->Push(node->left()); |
| 6866 frame_->Push(&right); | 6882 frame_->Push(&right); |
| 6867 } else { | 6883 } else { |
| 6868 Load(node->left()); | 6884 Load(node->left()); |
| 6869 Load(node->right()); | 6885 Load(node->right()); |
| 6870 } | 6886 } |
| 6871 GenericBinaryOperation(node->op(), node->type(), overwrite_mode); | 6887 GenericBinaryOperation(node->op(), node->type(), |
| 6888 overwrite_mode, node->no_negative_zero()); |
| 6872 } | 6889 } |
| 6873 } | 6890 } |
| 6874 | 6891 |
| 6875 | 6892 |
| 6876 void CodeGenerator::VisitThisFunction(ThisFunction* node) { | 6893 void CodeGenerator::VisitThisFunction(ThisFunction* node) { |
| 6877 frame_->PushFunction(); | 6894 frame_->PushFunction(); |
| 6878 } | 6895 } |
| 6879 | 6896 |
| 6880 | 6897 |
| 6881 void CodeGenerator::VisitCompareOperation(CompareOperation* node) { | 6898 void CodeGenerator::VisitCompareOperation(CompareOperation* node) { |
| (...skipping 4932 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11814 | 11831 |
| 11815 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) | 11832 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) |
| 11816 // tagged as a small integer. | 11833 // tagged as a small integer. |
| 11817 __ bind(&runtime); | 11834 __ bind(&runtime); |
| 11818 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); | 11835 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); |
| 11819 } | 11836 } |
| 11820 | 11837 |
| 11821 #undef __ | 11838 #undef __ |
| 11822 | 11839 |
| 11823 } } // namespace v8::internal | 11840 } } // namespace v8::internal |
| OLD | NEW |