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 |