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 1203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1214 // Result is always a number. | 1214 // Result is always a number. |
1215 return TypeInfo::Number(); | 1215 return TypeInfo::Number(); |
1216 default: | 1216 default: |
1217 UNREACHABLE(); | 1217 UNREACHABLE(); |
1218 } | 1218 } |
1219 UNREACHABLE(); | 1219 UNREACHABLE(); |
1220 return TypeInfo::Unknown(); | 1220 return TypeInfo::Unknown(); |
1221 } | 1221 } |
1222 | 1222 |
1223 | 1223 |
1224 void CodeGenerator::GenericBinaryOperation(Token::Value op, | 1224 void CodeGenerator::GenericBinaryOperation(BinaryOperation* expr, |
1225 StaticType* type, | 1225 OverwriteMode overwrite_mode) { |
1226 OverwriteMode overwrite_mode, | |
1227 bool no_negative_zero) { | |
1228 Comment cmnt(masm_, "[ BinaryOperation"); | 1226 Comment cmnt(masm_, "[ BinaryOperation"); |
| 1227 Token::Value op = expr->op(); |
1229 Comment cmnt_token(masm_, Token::String(op)); | 1228 Comment cmnt_token(masm_, Token::String(op)); |
1230 | 1229 |
1231 if (op == Token::COMMA) { | 1230 if (op == Token::COMMA) { |
1232 // Simply discard left value. | 1231 // Simply discard left value. |
1233 frame_->Nip(1); | 1232 frame_->Nip(1); |
1234 return; | 1233 return; |
1235 } | 1234 } |
1236 | 1235 |
1237 Result right = frame_->Pop(); | 1236 Result right = frame_->Pop(); |
1238 Result left = frame_->Pop(); | 1237 Result left = frame_->Pop(); |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1291 | 1290 |
1292 Result answer; | 1291 Result answer; |
1293 if (left_is_non_smi_constant || right_is_non_smi_constant) { | 1292 if (left_is_non_smi_constant || right_is_non_smi_constant) { |
1294 // Go straight to the slow case, with no smi code. | 1293 // Go straight to the slow case, with no smi code. |
1295 GenericBinaryOpStub stub(op, | 1294 GenericBinaryOpStub stub(op, |
1296 overwrite_mode, | 1295 overwrite_mode, |
1297 NO_SMI_CODE_IN_STUB, | 1296 NO_SMI_CODE_IN_STUB, |
1298 operands_type); | 1297 operands_type); |
1299 answer = stub.GenerateCall(masm_, frame_, &left, &right); | 1298 answer = stub.GenerateCall(masm_, frame_, &left, &right); |
1300 } else if (right_is_smi_constant) { | 1299 } else if (right_is_smi_constant) { |
1301 answer = ConstantSmiBinaryOperation(op, &left, right.handle(), | 1300 answer = ConstantSmiBinaryOperation(expr, &left, right.handle(), |
1302 type, false, overwrite_mode, | 1301 false, overwrite_mode); |
1303 no_negative_zero); | |
1304 } else if (left_is_smi_constant) { | 1302 } else if (left_is_smi_constant) { |
1305 answer = ConstantSmiBinaryOperation(op, &right, left.handle(), | 1303 answer = ConstantSmiBinaryOperation(expr, &right, left.handle(), |
1306 type, true, overwrite_mode, | 1304 true, overwrite_mode); |
1307 no_negative_zero); | |
1308 } else { | 1305 } else { |
1309 // Set the flags based on the operation, type and loop nesting level. | 1306 // Set the flags based on the operation, type and loop nesting level. |
1310 // Bit operations always assume they likely operate on Smis. Still only | 1307 // Bit operations always assume they likely operate on Smis. Still only |
1311 // generate the inline Smi check code if this operation is part of a loop. | 1308 // generate the inline Smi check code if this operation is part of a loop. |
1312 // For all other operations only inline the Smi check code for likely smis | 1309 // For all other operations only inline the Smi check code for likely smis |
1313 // if the operation is part of a loop. | 1310 // if the operation is part of a loop. |
1314 if (loop_nesting() > 0 && | 1311 if (loop_nesting() > 0 && |
1315 (Token::IsBitOp(op) || | 1312 (Token::IsBitOp(op) || |
1316 operands_type.IsInteger32() || | 1313 operands_type.IsInteger32() || |
1317 type->IsLikelySmi())) { | 1314 expr->type()->IsLikelySmi())) { |
1318 answer = LikelySmiBinaryOperation(op, &left, &right, | 1315 answer = LikelySmiBinaryOperation(expr, &left, &right, overwrite_mode); |
1319 overwrite_mode, no_negative_zero); | |
1320 } else { | 1316 } else { |
1321 GenericBinaryOpStub stub(op, | 1317 GenericBinaryOpStub stub(op, |
1322 overwrite_mode, | 1318 overwrite_mode, |
1323 NO_GENERIC_BINARY_FLAGS, | 1319 NO_GENERIC_BINARY_FLAGS, |
1324 operands_type); | 1320 operands_type); |
1325 answer = stub.GenerateCall(masm_, frame_, &left, &right); | 1321 answer = stub.GenerateCall(masm_, frame_, &left, &right); |
1326 } | 1322 } |
1327 } | 1323 } |
1328 | 1324 |
1329 answer.set_type_info(result_type); | 1325 answer.set_type_info(result_type); |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1413 | 1409 |
1414 | 1410 |
1415 static void CheckTwoForSminess(MacroAssembler* masm, | 1411 static void CheckTwoForSminess(MacroAssembler* masm, |
1416 Register left, Register right, Register scratch, | 1412 Register left, Register right, Register scratch, |
1417 TypeInfo left_info, TypeInfo right_info, | 1413 TypeInfo left_info, TypeInfo right_info, |
1418 DeferredInlineBinaryOperation* deferred); | 1414 DeferredInlineBinaryOperation* deferred); |
1419 | 1415 |
1420 | 1416 |
1421 // Implements a binary operation using a deferred code object and some | 1417 // Implements a binary operation using a deferred code object and some |
1422 // inline code to operate on smis quickly. | 1418 // inline code to operate on smis quickly. |
1423 Result CodeGenerator::LikelySmiBinaryOperation(Token::Value op, | 1419 Result CodeGenerator::LikelySmiBinaryOperation(BinaryOperation* expr, |
1424 Result* left, | 1420 Result* left, |
1425 Result* right, | 1421 Result* right, |
1426 OverwriteMode overwrite_mode, | 1422 OverwriteMode overwrite_mode) { |
1427 bool no_negative_zero) { | 1423 Token::Value op = expr->op(); |
1428 Result answer; | 1424 Result answer; |
1429 // Special handling of div and mod because they use fixed registers. | 1425 // Special handling of div and mod because they use fixed registers. |
1430 if (op == Token::DIV || op == Token::MOD) { | 1426 if (op == Token::DIV || op == Token::MOD) { |
1431 // We need eax as the quotient register, edx as the remainder | 1427 // We need eax as the quotient register, edx as the remainder |
1432 // register, neither left nor right in eax or edx, and left copied | 1428 // register, neither left nor right in eax or edx, and left copied |
1433 // to eax. | 1429 // to eax. |
1434 Result quotient; | 1430 Result quotient; |
1435 Result remainder; | 1431 Result remainder; |
1436 bool left_is_in_eax = false; | 1432 bool left_is_in_eax = false; |
1437 // Step 1: get eax for quotient. | 1433 // Step 1: get eax for quotient. |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1523 // Divide edx:eax by the right operand. | 1519 // Divide edx:eax by the right operand. |
1524 __ idiv(right->reg()); | 1520 __ idiv(right->reg()); |
1525 | 1521 |
1526 // Complete the operation. | 1522 // Complete the operation. |
1527 if (op == Token::DIV) { | 1523 if (op == Token::DIV) { |
1528 // Check for negative zero result. If result is zero, and divisor | 1524 // Check for negative zero result. If result is zero, and divisor |
1529 // is negative, return a floating point negative zero. The | 1525 // is negative, return a floating point negative zero. The |
1530 // virtual frame is unchanged in this block, so local control flow | 1526 // virtual frame is unchanged in this block, so local control flow |
1531 // can use a Label rather than a JumpTarget. If the context of this | 1527 // can use a Label rather than a JumpTarget. If the context of this |
1532 // expression will treat -0 like 0, do not do this test. | 1528 // expression will treat -0 like 0, do not do this test. |
1533 if (!no_negative_zero) { | 1529 if (!expr->no_negative_zero()) { |
1534 Label non_zero_result; | 1530 Label non_zero_result; |
1535 __ test(left->reg(), Operand(left->reg())); | 1531 __ test(left->reg(), Operand(left->reg())); |
1536 __ j(not_zero, &non_zero_result); | 1532 __ j(not_zero, &non_zero_result); |
1537 __ test(right->reg(), Operand(right->reg())); | 1533 __ test(right->reg(), Operand(right->reg())); |
1538 deferred->Branch(negative); | 1534 deferred->Branch(negative); |
1539 __ bind(&non_zero_result); | 1535 __ bind(&non_zero_result); |
1540 } | 1536 } |
1541 // Check for the corner case of dividing the most negative smi by | 1537 // Check for the corner case of dividing the most negative smi by |
1542 // -1. We cannot use the overflow flag, since it is not set by | 1538 // -1. We cannot use the overflow flag, since it is not set by |
1543 // idiv instruction. | 1539 // idiv instruction. |
1544 ASSERT(kSmiTag == 0 && kSmiTagSize == 1); | 1540 ASSERT(kSmiTag == 0 && kSmiTagSize == 1); |
1545 __ cmp(eax, 0x40000000); | 1541 __ cmp(eax, 0x40000000); |
1546 deferred->Branch(equal); | 1542 deferred->Branch(equal); |
1547 // Check that the remainder is zero. | 1543 // Check that the remainder is zero. |
1548 __ test(edx, Operand(edx)); | 1544 __ test(edx, Operand(edx)); |
1549 deferred->Branch(not_zero); | 1545 deferred->Branch(not_zero); |
1550 // Tag the result and store it in the quotient register. | 1546 // Tag the result and store it in the quotient register. |
1551 __ SmiTag(eax); | 1547 __ SmiTag(eax); |
1552 deferred->BindExit(); | 1548 deferred->BindExit(); |
1553 left->Unuse(); | 1549 left->Unuse(); |
1554 right->Unuse(); | 1550 right->Unuse(); |
1555 answer = quotient; | 1551 answer = quotient; |
1556 } else { | 1552 } else { |
1557 ASSERT(op == Token::MOD); | 1553 ASSERT(op == Token::MOD); |
1558 // Check for a negative zero result. If the result is zero, and | 1554 // Check for a negative zero result. If the result is zero, and |
1559 // the dividend is negative, return a floating point negative | 1555 // the dividend is negative, return a floating point negative |
1560 // zero. The frame is unchanged in this block, so local control | 1556 // zero. The frame is unchanged in this block, so local control |
1561 // flow can use a Label rather than a JumpTarget. | 1557 // flow can use a Label rather than a JumpTarget. |
1562 if (!no_negative_zero) { | 1558 if (!expr->no_negative_zero()) { |
1563 Label non_zero_result; | 1559 Label non_zero_result; |
1564 __ test(edx, Operand(edx)); | 1560 __ test(edx, Operand(edx)); |
1565 __ j(not_zero, &non_zero_result, taken); | 1561 __ j(not_zero, &non_zero_result, taken); |
1566 __ test(left->reg(), Operand(left->reg())); | 1562 __ test(left->reg(), Operand(left->reg())); |
1567 deferred->Branch(negative); | 1563 deferred->Branch(negative); |
1568 __ bind(&non_zero_result); | 1564 __ bind(&non_zero_result); |
1569 } | 1565 } |
1570 deferred->BindExit(); | 1566 deferred->BindExit(); |
1571 left->Unuse(); | 1567 left->Unuse(); |
1572 right->Unuse(); | 1568 right->Unuse(); |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1736 // Left-hand operand has been copied into answer. | 1732 // Left-hand operand has been copied into answer. |
1737 __ SmiUntag(answer.reg()); | 1733 __ SmiUntag(answer.reg()); |
1738 // Do multiplication of smis, leaving result in answer. | 1734 // Do multiplication of smis, leaving result in answer. |
1739 __ imul(answer.reg(), Operand(right->reg())); | 1735 __ imul(answer.reg(), Operand(right->reg())); |
1740 // Go slow on overflows. | 1736 // Go slow on overflows. |
1741 deferred->Branch(overflow); | 1737 deferred->Branch(overflow); |
1742 // Check for negative zero result. If product is zero, and one | 1738 // Check for negative zero result. If product is zero, and one |
1743 // argument is negative, go to slow case. The frame is unchanged | 1739 // argument is negative, go to slow case. The frame is unchanged |
1744 // in this block, so local control flow can use a Label rather | 1740 // in this block, so local control flow can use a Label rather |
1745 // than a JumpTarget. | 1741 // than a JumpTarget. |
1746 if (!no_negative_zero) { | 1742 if (!expr->no_negative_zero()) { |
1747 Label non_zero_result; | 1743 Label non_zero_result; |
1748 __ test(answer.reg(), Operand(answer.reg())); | 1744 __ test(answer.reg(), Operand(answer.reg())); |
1749 __ j(not_zero, &non_zero_result, taken); | 1745 __ j(not_zero, &non_zero_result, taken); |
1750 __ mov(answer.reg(), left->reg()); | 1746 __ mov(answer.reg(), left->reg()); |
1751 __ or_(answer.reg(), Operand(right->reg())); | 1747 __ or_(answer.reg(), Operand(right->reg())); |
1752 deferred->Branch(negative); | 1748 deferred->Branch(negative); |
1753 __ xor_(answer.reg(), Operand(answer.reg())); // Positive 0 is correct. | 1749 __ xor_(answer.reg(), Operand(answer.reg())); // Positive 0 is correct. |
1754 __ bind(&non_zero_result); | 1750 __ bind(&non_zero_result); |
1755 } | 1751 } |
1756 break; | 1752 break; |
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1979 GenericBinaryOpStub igostub( | 1975 GenericBinaryOpStub igostub( |
1980 Token::SUB, | 1976 Token::SUB, |
1981 overwrite_mode_, | 1977 overwrite_mode_, |
1982 NO_SMI_CODE_IN_STUB, | 1978 NO_SMI_CODE_IN_STUB, |
1983 TypeInfo::Combine(TypeInfo::Smi(), type_info_)); | 1979 TypeInfo::Combine(TypeInfo::Smi(), type_info_)); |
1984 igostub.GenerateCall(masm_, dst_, value_); | 1980 igostub.GenerateCall(masm_, dst_, value_); |
1985 if (!dst_.is(eax)) __ mov(dst_, eax); | 1981 if (!dst_.is(eax)) __ mov(dst_, eax); |
1986 } | 1982 } |
1987 | 1983 |
1988 | 1984 |
1989 Result CodeGenerator::ConstantSmiBinaryOperation(Token::Value op, | 1985 Result CodeGenerator::ConstantSmiBinaryOperation( |
1990 Result* operand, | 1986 BinaryOperation* expr, |
1991 Handle<Object> value, | 1987 Result* operand, |
1992 StaticType* type, | 1988 Handle<Object> value, |
1993 bool reversed, | 1989 bool reversed, |
1994 OverwriteMode overwrite_mode, | 1990 OverwriteMode overwrite_mode) { |
1995 bool no_negative_zero) { | |
1996 // NOTE: This is an attempt to inline (a bit) more of the code for | 1991 // NOTE: This is an attempt to inline (a bit) more of the code for |
1997 // some possible smi operations (like + and -) when (at least) one | 1992 // some possible smi operations (like + and -) when (at least) one |
1998 // of the operands is a constant smi. | 1993 // of the operands is a constant smi. |
1999 // Consumes the argument "operand". | 1994 // Consumes the argument "operand". |
2000 // TODO(199): Optimize some special cases of operations involving a | 1995 // TODO(199): Optimize some special cases of operations involving a |
2001 // smi literal (multiply by 2, shift by 0, etc.). | 1996 // smi literal (multiply by 2, shift by 0, etc.). |
2002 if (IsUnsafeSmi(value)) { | 1997 if (IsUnsafeSmi(value)) { |
2003 Result unsafe_operand(value); | 1998 Result unsafe_operand(value); |
2004 if (reversed) { | 1999 if (reversed) { |
2005 return LikelySmiBinaryOperation(op, &unsafe_operand, operand, | 2000 return LikelySmiBinaryOperation(expr, &unsafe_operand, operand, |
2006 overwrite_mode, no_negative_zero); | 2001 overwrite_mode); |
2007 } else { | 2002 } else { |
2008 return LikelySmiBinaryOperation(op, operand, &unsafe_operand, | 2003 return LikelySmiBinaryOperation(expr, operand, &unsafe_operand, |
2009 overwrite_mode, no_negative_zero); | 2004 overwrite_mode); |
2010 } | 2005 } |
2011 } | 2006 } |
2012 | 2007 |
2013 // Get the literal value. | 2008 // Get the literal value. |
2014 Smi* smi_value = Smi::cast(*value); | 2009 Smi* smi_value = Smi::cast(*value); |
2015 int int_value = smi_value->value(); | 2010 int int_value = smi_value->value(); |
2016 | 2011 |
| 2012 Token::Value op = expr->op(); |
2017 Result answer; | 2013 Result answer; |
2018 switch (op) { | 2014 switch (op) { |
2019 case Token::ADD: { | 2015 case Token::ADD: { |
2020 operand->ToRegister(); | 2016 operand->ToRegister(); |
2021 frame_->Spill(operand->reg()); | 2017 frame_->Spill(operand->reg()); |
2022 | 2018 |
2023 // Optimistically add. Call the specialized add stub if the | 2019 // Optimistically add. Call the specialized add stub if the |
2024 // result is not a smi or overflows. | 2020 // result is not a smi or overflows. |
2025 DeferredCode* deferred = NULL; | 2021 DeferredCode* deferred = NULL; |
2026 if (reversed) { | 2022 if (reversed) { |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2082 if (FLAG_debug_code) __ AbortIfNotSmi(operand->reg()); | 2078 if (FLAG_debug_code) __ AbortIfNotSmi(operand->reg()); |
2083 } | 2079 } |
2084 deferred->BindExit(); | 2080 deferred->BindExit(); |
2085 operand->Unuse(); | 2081 operand->Unuse(); |
2086 break; | 2082 break; |
2087 } | 2083 } |
2088 | 2084 |
2089 case Token::SAR: | 2085 case Token::SAR: |
2090 if (reversed) { | 2086 if (reversed) { |
2091 Result constant_operand(value); | 2087 Result constant_operand(value); |
2092 answer = LikelySmiBinaryOperation(op, &constant_operand, operand, | 2088 answer = LikelySmiBinaryOperation(expr, &constant_operand, operand, |
2093 overwrite_mode, no_negative_zero); | 2089 overwrite_mode); |
2094 } else { | 2090 } else { |
2095 // Only the least significant 5 bits of the shift value are used. | 2091 // Only the least significant 5 bits of the shift value are used. |
2096 // In the slow case, this masking is done inside the runtime call. | 2092 // In the slow case, this masking is done inside the runtime call. |
2097 int shift_value = int_value & 0x1f; | 2093 int shift_value = int_value & 0x1f; |
2098 operand->ToRegister(); | 2094 operand->ToRegister(); |
2099 frame_->Spill(operand->reg()); | 2095 frame_->Spill(operand->reg()); |
2100 if (!operand->type_info().IsSmi()) { | 2096 if (!operand->type_info().IsSmi()) { |
2101 DeferredInlineSmiOperation* deferred = | 2097 DeferredInlineSmiOperation* deferred = |
2102 new DeferredInlineSmiOperation(op, | 2098 new DeferredInlineSmiOperation(op, |
2103 operand->reg(), | 2099 operand->reg(), |
(...skipping 15 matching lines...) Expand all Loading... |
2119 __ and_(operand->reg(), ~kSmiTagMask); | 2115 __ and_(operand->reg(), ~kSmiTagMask); |
2120 } | 2116 } |
2121 } | 2117 } |
2122 answer = *operand; | 2118 answer = *operand; |
2123 } | 2119 } |
2124 break; | 2120 break; |
2125 | 2121 |
2126 case Token::SHR: | 2122 case Token::SHR: |
2127 if (reversed) { | 2123 if (reversed) { |
2128 Result constant_operand(value); | 2124 Result constant_operand(value); |
2129 answer = LikelySmiBinaryOperation(op, &constant_operand, operand, | 2125 answer = LikelySmiBinaryOperation(expr, &constant_operand, operand, |
2130 overwrite_mode, no_negative_zero); | 2126 overwrite_mode); |
2131 } else { | 2127 } else { |
2132 // Only the least significant 5 bits of the shift value are used. | 2128 // Only the least significant 5 bits of the shift value are used. |
2133 // In the slow case, this masking is done inside the runtime call. | 2129 // In the slow case, this masking is done inside the runtime call. |
2134 int shift_value = int_value & 0x1f; | 2130 int shift_value = int_value & 0x1f; |
2135 operand->ToRegister(); | 2131 operand->ToRegister(); |
2136 answer = allocator()->Allocate(); | 2132 answer = allocator()->Allocate(); |
2137 ASSERT(answer.is_valid()); | 2133 ASSERT(answer.is_valid()); |
2138 DeferredInlineSmiOperation* deferred = | 2134 DeferredInlineSmiOperation* deferred = |
2139 new DeferredInlineSmiOperation(op, | 2135 new DeferredInlineSmiOperation(op, |
2140 answer.reg(), | 2136 answer.reg(), |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2320 __ test(operand->reg(), Immediate(3)); | 2316 __ test(operand->reg(), Immediate(3)); |
2321 deferred->Branch(not_zero); // Branch if non-smi or odd smi. | 2317 deferred->Branch(not_zero); // Branch if non-smi or odd smi. |
2322 __ sar(operand->reg(), 1); | 2318 __ sar(operand->reg(), 1); |
2323 deferred->BindExit(); | 2319 deferred->BindExit(); |
2324 answer = *operand; | 2320 answer = *operand; |
2325 } else { | 2321 } else { |
2326 // Cannot fall through MOD to default case, so we duplicate the | 2322 // Cannot fall through MOD to default case, so we duplicate the |
2327 // default case here. | 2323 // default case here. |
2328 Result constant_operand(value); | 2324 Result constant_operand(value); |
2329 if (reversed) { | 2325 if (reversed) { |
2330 answer = LikelySmiBinaryOperation(op, &constant_operand, operand, | 2326 answer = LikelySmiBinaryOperation(expr, &constant_operand, operand, |
2331 overwrite_mode, no_negative_zero); | 2327 overwrite_mode); |
2332 } else { | 2328 } else { |
2333 answer = LikelySmiBinaryOperation(op, operand, &constant_operand, | 2329 answer = LikelySmiBinaryOperation(expr, operand, &constant_operand, |
2334 overwrite_mode, no_negative_zero); | 2330 overwrite_mode); |
2335 } | 2331 } |
2336 } | 2332 } |
2337 break; | 2333 break; |
2338 // Generate inline code for mod of powers of 2 and negative powers of 2. | 2334 // Generate inline code for mod of powers of 2 and negative powers of 2. |
2339 case Token::MOD: | 2335 case Token::MOD: |
2340 if (!reversed && | 2336 if (!reversed && |
2341 int_value != 0 && | 2337 int_value != 0 && |
2342 (IsPowerOf2(int_value) || IsPowerOf2(-int_value))) { | 2338 (IsPowerOf2(int_value) || IsPowerOf2(-int_value))) { |
2343 operand->ToRegister(); | 2339 operand->ToRegister(); |
2344 frame_->Spill(operand->reg()); | 2340 frame_->Spill(operand->reg()); |
(...skipping 15 matching lines...) Expand all Loading... |
2360 } | 2356 } |
2361 deferred->BindExit(); | 2357 deferred->BindExit(); |
2362 answer = *operand; | 2358 answer = *operand; |
2363 break; | 2359 break; |
2364 } | 2360 } |
2365 // Fall through if we did not find a power of 2 on the right hand side! | 2361 // Fall through if we did not find a power of 2 on the right hand side! |
2366 | 2362 |
2367 default: { | 2363 default: { |
2368 Result constant_operand(value); | 2364 Result constant_operand(value); |
2369 if (reversed) { | 2365 if (reversed) { |
2370 answer = LikelySmiBinaryOperation(op, &constant_operand, operand, | 2366 answer = LikelySmiBinaryOperation(expr, &constant_operand, operand, |
2371 overwrite_mode, no_negative_zero); | 2367 overwrite_mode); |
2372 } else { | 2368 } else { |
2373 answer = LikelySmiBinaryOperation(op, operand, &constant_operand, | 2369 answer = LikelySmiBinaryOperation(expr, operand, &constant_operand, |
2374 overwrite_mode, no_negative_zero); | 2370 overwrite_mode); |
2375 } | 2371 } |
2376 break; | 2372 break; |
2377 } | 2373 } |
2378 } | 2374 } |
2379 ASSERT(answer.is_valid()); | 2375 ASSERT(answer.is_valid()); |
2380 return answer; | 2376 return answer; |
2381 } | 2377 } |
2382 | 2378 |
2383 | 2379 |
2384 static bool CouldBeNaN(const Result& result) { | 2380 static bool CouldBeNaN(const Result& result) { |
(...skipping 2979 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5364 | 5360 |
5365 // Evaluate the right-hand side. | 5361 // Evaluate the right-hand side. |
5366 if (node->is_compound()) { | 5362 if (node->is_compound()) { |
5367 Result result = LoadFromSlotCheckForArguments(slot, NOT_INSIDE_TYPEOF); | 5363 Result result = LoadFromSlotCheckForArguments(slot, NOT_INSIDE_TYPEOF); |
5368 frame()->Push(&result); | 5364 frame()->Push(&result); |
5369 Load(node->value()); | 5365 Load(node->value()); |
5370 | 5366 |
5371 bool overwrite_value = | 5367 bool overwrite_value = |
5372 (node->value()->AsBinaryOperation() != NULL && | 5368 (node->value()->AsBinaryOperation() != NULL && |
5373 node->value()->AsBinaryOperation()->ResultOverwriteAllowed()); | 5369 node->value()->AsBinaryOperation()->ResultOverwriteAllowed()); |
5374 GenericBinaryOperation(node->binary_op(), | 5370 // Construct the implicit binary operation. |
5375 node->type(), | 5371 BinaryOperation expr(node, node->binary_op(), node->target(), |
5376 overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE, | 5372 node->value()); |
5377 node->no_negative_zero()); | 5373 GenericBinaryOperation(&expr, |
| 5374 overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE); |
5378 } else { | 5375 } else { |
5379 Load(node->value()); | 5376 Load(node->value()); |
5380 } | 5377 } |
5381 | 5378 |
5382 // Perform the assignment. | 5379 // Perform the assignment. |
5383 if (var->mode() != Variable::CONST || node->op() == Token::INIT_CONST) { | 5380 if (var->mode() != Variable::CONST || node->op() == Token::INIT_CONST) { |
5384 CodeForSourcePosition(node->position()); | 5381 CodeForSourcePosition(node->position()); |
5385 StoreToSlot(slot, | 5382 StoreToSlot(slot, |
5386 node->op() == Token::INIT_CONST ? CONST_INIT : NOT_CONST_INIT); | 5383 node->op() == Token::INIT_CONST ? CONST_INIT : NOT_CONST_INIT); |
5387 } | 5384 } |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5442 } else { | 5439 } else { |
5443 frame()->Dup(); | 5440 frame()->Dup(); |
5444 } | 5441 } |
5445 Result value = EmitNamedLoad(name, var != NULL); | 5442 Result value = EmitNamedLoad(name, var != NULL); |
5446 frame()->Push(&value); | 5443 frame()->Push(&value); |
5447 Load(node->value()); | 5444 Load(node->value()); |
5448 | 5445 |
5449 bool overwrite_value = | 5446 bool overwrite_value = |
5450 (node->value()->AsBinaryOperation() != NULL && | 5447 (node->value()->AsBinaryOperation() != NULL && |
5451 node->value()->AsBinaryOperation()->ResultOverwriteAllowed()); | 5448 node->value()->AsBinaryOperation()->ResultOverwriteAllowed()); |
5452 GenericBinaryOperation(node->binary_op(), | 5449 // Construct the implicit binary operation. |
5453 node->type(), | 5450 BinaryOperation expr(node, node->binary_op(), node->target(), |
5454 overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE, | 5451 node->value()); |
5455 node->no_negative_zero()); | 5452 GenericBinaryOperation(&expr, |
| 5453 overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE); |
5456 } else { | 5454 } else { |
5457 Load(node->value()); | 5455 Load(node->value()); |
5458 } | 5456 } |
5459 | 5457 |
5460 // Perform the assignment. It is safe to ignore constants here. | 5458 // Perform the assignment. It is safe to ignore constants here. |
5461 ASSERT(var == NULL || var->mode() != Variable::CONST); | 5459 ASSERT(var == NULL || var->mode() != Variable::CONST); |
5462 ASSERT_NE(Token::INIT_CONST, node->op()); | 5460 ASSERT_NE(Token::INIT_CONST, node->op()); |
5463 if (is_trivial_receiver) { | 5461 if (is_trivial_receiver) { |
5464 Result value = frame()->Pop(); | 5462 Result value = frame()->Pop(); |
5465 frame()->Push(prop->obj()); | 5463 frame()->Push(prop->obj()); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5522 // Duplicate receiver and key. | 5520 // Duplicate receiver and key. |
5523 frame()->PushElementAt(1); | 5521 frame()->PushElementAt(1); |
5524 frame()->PushElementAt(1); | 5522 frame()->PushElementAt(1); |
5525 Result value = EmitKeyedLoad(); | 5523 Result value = EmitKeyedLoad(); |
5526 frame()->Push(&value); | 5524 frame()->Push(&value); |
5527 Load(node->value()); | 5525 Load(node->value()); |
5528 | 5526 |
5529 bool overwrite_value = | 5527 bool overwrite_value = |
5530 (node->value()->AsBinaryOperation() != NULL && | 5528 (node->value()->AsBinaryOperation() != NULL && |
5531 node->value()->AsBinaryOperation()->ResultOverwriteAllowed()); | 5529 node->value()->AsBinaryOperation()->ResultOverwriteAllowed()); |
5532 GenericBinaryOperation(node->binary_op(), | 5530 BinaryOperation expr(node, node->binary_op(), node->target(), |
5533 node->type(), | 5531 node->value()); |
5534 overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE, | 5532 GenericBinaryOperation(&expr, |
5535 node->no_negative_zero()); | 5533 overwrite_value ? OVERWRITE_RIGHT : NO_OVERWRITE); |
5536 } else { | 5534 } else { |
5537 Load(node->value()); | 5535 Load(node->value()); |
5538 } | 5536 } |
5539 | 5537 |
5540 // Perform the assignment. It is safe to ignore constants here. | 5538 // Perform the assignment. It is safe to ignore constants here. |
5541 ASSERT(node->op() != Token::INIT_CONST); | 5539 ASSERT(node->op() != Token::INIT_CONST); |
5542 CodeForSourcePosition(node->position()); | 5540 CodeForSourcePosition(node->position()); |
5543 Result answer = EmitKeyedStore(prop->key()->type()); | 5541 Result answer = EmitKeyedStore(prop->key()->type()); |
5544 frame()->Push(&answer); | 5542 frame()->Push(&answer); |
5545 | 5543 |
(...skipping 2083 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7629 | 7627 |
7630 if (node->left()->IsTrivial()) { | 7628 if (node->left()->IsTrivial()) { |
7631 Load(node->right()); | 7629 Load(node->right()); |
7632 Result right = frame_->Pop(); | 7630 Result right = frame_->Pop(); |
7633 frame_->Push(node->left()); | 7631 frame_->Push(node->left()); |
7634 frame_->Push(&right); | 7632 frame_->Push(&right); |
7635 } else { | 7633 } else { |
7636 Load(node->left()); | 7634 Load(node->left()); |
7637 Load(node->right()); | 7635 Load(node->right()); |
7638 } | 7636 } |
7639 GenericBinaryOperation(node->op(), node->type(), | 7637 GenericBinaryOperation(node, overwrite_mode); |
7640 overwrite_mode, node->no_negative_zero()); | |
7641 } | 7638 } |
7642 } | 7639 } |
7643 | 7640 |
7644 | 7641 |
7645 void CodeGenerator::VisitThisFunction(ThisFunction* node) { | 7642 void CodeGenerator::VisitThisFunction(ThisFunction* node) { |
7646 ASSERT(!in_safe_int32_mode()); | 7643 ASSERT(!in_safe_int32_mode()); |
7647 frame_->PushFunction(); | 7644 frame_->PushFunction(); |
7648 } | 7645 } |
7649 | 7646 |
7650 | 7647 |
(...skipping 4953 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12604 | 12601 |
12605 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) | 12602 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) |
12606 // tagged as a small integer. | 12603 // tagged as a small integer. |
12607 __ bind(&runtime); | 12604 __ bind(&runtime); |
12608 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); | 12605 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); |
12609 } | 12606 } |
12610 | 12607 |
12611 #undef __ | 12608 #undef __ |
12612 | 12609 |
12613 } } // namespace v8::internal | 12610 } } // namespace v8::internal |
OLD | NEW |