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 1408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1419 TypeInfo left_info, TypeInfo right_info, | 1419 TypeInfo left_info, TypeInfo right_info, |
1420 DeferredInlineBinaryOperation* deferred); | 1420 DeferredInlineBinaryOperation* deferred); |
1421 | 1421 |
1422 | 1422 |
1423 // Implements a binary operation using a deferred code object and some | 1423 // Implements a binary operation using a deferred code object and some |
1424 // inline code to operate on smis quickly. | 1424 // inline code to operate on smis quickly. |
1425 Result CodeGenerator::LikelySmiBinaryOperation(BinaryOperation* expr, | 1425 Result CodeGenerator::LikelySmiBinaryOperation(BinaryOperation* expr, |
1426 Result* left, | 1426 Result* left, |
1427 Result* right, | 1427 Result* right, |
1428 OverwriteMode overwrite_mode) { | 1428 OverwriteMode overwrite_mode) { |
| 1429 // Copy the type info because left and right may be overwritten. |
| 1430 TypeInfo left_type_info = left->type_info(); |
| 1431 TypeInfo right_type_info = right->type_info(); |
1429 Token::Value op = expr->op(); | 1432 Token::Value op = expr->op(); |
1430 Result answer; | 1433 Result answer; |
1431 // Special handling of div and mod because they use fixed registers. | 1434 // Special handling of div and mod because they use fixed registers. |
1432 if (op == Token::DIV || op == Token::MOD) { | 1435 if (op == Token::DIV || op == Token::MOD) { |
1433 // We need eax as the quotient register, edx as the remainder | 1436 // We need eax as the quotient register, edx as the remainder |
1434 // register, neither left nor right in eax or edx, and left copied | 1437 // register, neither left nor right in eax or edx, and left copied |
1435 // to eax. | 1438 // to eax. |
1436 Result quotient; | 1439 Result quotient; |
1437 Result remainder; | 1440 Result remainder; |
1438 bool left_is_in_eax = false; | 1441 bool left_is_in_eax = false; |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1494 right->ToRegister(); | 1497 right->ToRegister(); |
1495 frame_->Spill(eax); | 1498 frame_->Spill(eax); |
1496 frame_->Spill(edx); | 1499 frame_->Spill(edx); |
1497 | 1500 |
1498 // Check that left and right are smi tagged. | 1501 // Check that left and right are smi tagged. |
1499 DeferredInlineBinaryOperation* deferred = | 1502 DeferredInlineBinaryOperation* deferred = |
1500 new DeferredInlineBinaryOperation(op, | 1503 new DeferredInlineBinaryOperation(op, |
1501 (op == Token::DIV) ? eax : edx, | 1504 (op == Token::DIV) ? eax : edx, |
1502 left->reg(), | 1505 left->reg(), |
1503 right->reg(), | 1506 right->reg(), |
1504 left->type_info(), | 1507 left_type_info, |
1505 right->type_info(), | 1508 right_type_info, |
1506 overwrite_mode); | 1509 overwrite_mode); |
1507 if (left->reg().is(right->reg())) { | 1510 if (left->reg().is(right->reg())) { |
1508 __ test(left->reg(), Immediate(kSmiTagMask)); | 1511 __ test(left->reg(), Immediate(kSmiTagMask)); |
1509 } else { | 1512 } else { |
1510 // Use the quotient register as a scratch for the tag check. | 1513 // Use the quotient register as a scratch for the tag check. |
1511 if (!left_is_in_eax) __ mov(eax, left->reg()); | 1514 if (!left_is_in_eax) __ mov(eax, left->reg()); |
1512 left_is_in_eax = false; // About to destroy the value in eax. | 1515 left_is_in_eax = false; // About to destroy the value in eax. |
1513 __ or_(eax, Operand(right->reg())); | 1516 __ or_(eax, Operand(right->reg())); |
1514 ASSERT(kSmiTag == 0); // Adjust test if not the case. | 1517 ASSERT(kSmiTag == 0); // Adjust test if not the case. |
1515 __ test(eax, Immediate(kSmiTagMask)); | 1518 __ test(eax, Immediate(kSmiTagMask)); |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1598 // Use a fresh answer register to avoid spilling the left operand. | 1601 // Use a fresh answer register to avoid spilling the left operand. |
1599 answer = allocator_->Allocate(); | 1602 answer = allocator_->Allocate(); |
1600 ASSERT(answer.is_valid()); | 1603 ASSERT(answer.is_valid()); |
1601 // Check that both operands are smis using the answer register as a | 1604 // Check that both operands are smis using the answer register as a |
1602 // temporary. | 1605 // temporary. |
1603 DeferredInlineBinaryOperation* deferred = | 1606 DeferredInlineBinaryOperation* deferred = |
1604 new DeferredInlineBinaryOperation(op, | 1607 new DeferredInlineBinaryOperation(op, |
1605 answer.reg(), | 1608 answer.reg(), |
1606 left->reg(), | 1609 left->reg(), |
1607 ecx, | 1610 ecx, |
1608 left->type_info(), | 1611 left_type_info, |
1609 right->type_info(), | 1612 right_type_info, |
1610 overwrite_mode); | 1613 overwrite_mode); |
1611 | 1614 |
1612 Label do_op, left_nonsmi; | 1615 Label do_op, left_nonsmi; |
1613 // If right is a smi we make a fast case if left is either a smi | 1616 // If right is a smi we make a fast case if left is either a smi |
1614 // or a heapnumber. | 1617 // or a heapnumber. |
1615 if (CpuFeatures::IsSupported(SSE2) && right->type_info().IsSmi()) { | 1618 if (CpuFeatures::IsSupported(SSE2) && right_type_info.IsSmi()) { |
1616 CpuFeatures::Scope use_sse2(SSE2); | 1619 CpuFeatures::Scope use_sse2(SSE2); |
1617 __ mov(answer.reg(), left->reg()); | 1620 __ mov(answer.reg(), left->reg()); |
1618 // Fast case - both are actually smis. | 1621 // Fast case - both are actually smis. |
1619 if (!left->type_info().IsSmi()) { | 1622 if (!left_type_info.IsSmi()) { |
1620 __ test(answer.reg(), Immediate(kSmiTagMask)); | 1623 __ test(answer.reg(), Immediate(kSmiTagMask)); |
1621 __ j(not_zero, &left_nonsmi); | 1624 __ j(not_zero, &left_nonsmi); |
1622 } else { | 1625 } else { |
1623 if (FLAG_debug_code) __ AbortIfNotSmi(left->reg()); | 1626 if (FLAG_debug_code) __ AbortIfNotSmi(left->reg()); |
1624 } | 1627 } |
1625 if (FLAG_debug_code) __ AbortIfNotSmi(right->reg()); | 1628 if (FLAG_debug_code) __ AbortIfNotSmi(right->reg()); |
1626 __ SmiUntag(answer.reg()); | 1629 __ SmiUntag(answer.reg()); |
1627 __ jmp(&do_op); | 1630 __ jmp(&do_op); |
1628 | 1631 |
1629 __ bind(&left_nonsmi); | 1632 __ bind(&left_nonsmi); |
1630 // Branch if not a heapnumber. | 1633 // Branch if not a heapnumber. |
1631 __ cmp(FieldOperand(answer.reg(), HeapObject::kMapOffset), | 1634 __ cmp(FieldOperand(answer.reg(), HeapObject::kMapOffset), |
1632 Factory::heap_number_map()); | 1635 Factory::heap_number_map()); |
1633 deferred->Branch(not_equal); | 1636 deferred->Branch(not_equal); |
1634 | 1637 |
1635 // Load integer value into answer register using truncation. | 1638 // Load integer value into answer register using truncation. |
1636 __ cvttsd2si(answer.reg(), | 1639 __ cvttsd2si(answer.reg(), |
1637 FieldOperand(answer.reg(), HeapNumber::kValueOffset)); | 1640 FieldOperand(answer.reg(), HeapNumber::kValueOffset)); |
1638 // Branch if we do not fit in a smi. | 1641 // Branch if we do not fit in a smi. |
1639 __ cmp(answer.reg(), 0xc0000000); | 1642 __ cmp(answer.reg(), 0xc0000000); |
1640 deferred->Branch(negative); | 1643 deferred->Branch(negative); |
1641 } else { | 1644 } else { |
1642 CheckTwoForSminess(masm_, left->reg(), right->reg(), answer.reg(), | 1645 CheckTwoForSminess(masm_, left->reg(), right->reg(), answer.reg(), |
1643 left->type_info(), right->type_info(), deferred); | 1646 left_type_info, right_type_info, deferred); |
1644 | 1647 |
1645 // Untag both operands. | 1648 // Untag both operands. |
1646 __ mov(answer.reg(), left->reg()); | 1649 __ mov(answer.reg(), left->reg()); |
1647 __ SmiUntag(answer.reg()); | 1650 __ SmiUntag(answer.reg()); |
1648 } | 1651 } |
1649 | 1652 |
1650 __ bind(&do_op); | 1653 __ bind(&do_op); |
1651 __ SmiUntag(ecx); | 1654 __ SmiUntag(ecx); |
1652 // Perform the operation. | 1655 // Perform the operation. |
1653 switch (op) { | 1656 switch (op) { |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1706 // need to be spilled in the fast case. | 1709 // need to be spilled in the fast case. |
1707 answer = allocator_->Allocate(); | 1710 answer = allocator_->Allocate(); |
1708 ASSERT(answer.is_valid()); | 1711 ASSERT(answer.is_valid()); |
1709 | 1712 |
1710 // Perform the smi tag check. | 1713 // Perform the smi tag check. |
1711 DeferredInlineBinaryOperation* deferred = | 1714 DeferredInlineBinaryOperation* deferred = |
1712 new DeferredInlineBinaryOperation(op, | 1715 new DeferredInlineBinaryOperation(op, |
1713 answer.reg(), | 1716 answer.reg(), |
1714 left->reg(), | 1717 left->reg(), |
1715 right->reg(), | 1718 right->reg(), |
1716 left->type_info(), | 1719 left_type_info, |
1717 right->type_info(), | 1720 right_type_info, |
1718 overwrite_mode); | 1721 overwrite_mode); |
1719 CheckTwoForSminess(masm_, left->reg(), right->reg(), answer.reg(), | 1722 CheckTwoForSminess(masm_, left->reg(), right->reg(), answer.reg(), |
1720 left->type_info(), right->type_info(), deferred); | 1723 left_type_info, right_type_info, deferred); |
1721 | 1724 |
1722 __ mov(answer.reg(), left->reg()); | 1725 __ mov(answer.reg(), left->reg()); |
1723 switch (op) { | 1726 switch (op) { |
1724 case Token::ADD: | 1727 case Token::ADD: |
1725 __ add(answer.reg(), Operand(right->reg())); | 1728 __ add(answer.reg(), Operand(right->reg())); |
1726 deferred->Branch(overflow); | 1729 deferred->Branch(overflow); |
1727 break; | 1730 break; |
1728 | 1731 |
1729 case Token::SUB: | 1732 case Token::SUB: |
1730 __ sub(answer.reg(), Operand(right->reg())); | 1733 __ sub(answer.reg(), Operand(right->reg())); |
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1981 GenericBinaryOpStub igostub( | 1984 GenericBinaryOpStub igostub( |
1982 Token::SUB, | 1985 Token::SUB, |
1983 overwrite_mode_, | 1986 overwrite_mode_, |
1984 NO_SMI_CODE_IN_STUB, | 1987 NO_SMI_CODE_IN_STUB, |
1985 TypeInfo::Combine(TypeInfo::Smi(), type_info_)); | 1988 TypeInfo::Combine(TypeInfo::Smi(), type_info_)); |
1986 igostub.GenerateCall(masm_, dst_, value_); | 1989 igostub.GenerateCall(masm_, dst_, value_); |
1987 if (!dst_.is(eax)) __ mov(dst_, eax); | 1990 if (!dst_.is(eax)) __ mov(dst_, eax); |
1988 } | 1991 } |
1989 | 1992 |
1990 | 1993 |
1991 Result CodeGenerator::ConstantSmiBinaryOperation( | 1994 Result CodeGenerator::ConstantSmiBinaryOperation(BinaryOperation* expr, |
1992 BinaryOperation* expr, | 1995 Result* operand, |
1993 Result* operand, | 1996 Handle<Object> value, |
1994 Handle<Object> value, | 1997 bool reversed, |
1995 bool reversed, | 1998 OverwriteMode overwrite_mode) { |
1996 OverwriteMode overwrite_mode) { | 1999 // Generate inline code for a binary operation when one of the |
1997 // NOTE: This is an attempt to inline (a bit) more of the code for | 2000 // operands is a constant smi. Consumes the argument "operand". |
1998 // some possible smi operations (like + and -) when (at least) one | |
1999 // of the operands is a constant smi. | |
2000 // Consumes the argument "operand". | |
2001 // TODO(199): Optimize some special cases of operations involving a | |
2002 // smi literal (multiply by 2, shift by 0, etc.). | |
2003 if (IsUnsafeSmi(value)) { | 2001 if (IsUnsafeSmi(value)) { |
2004 Result unsafe_operand(value); | 2002 Result unsafe_operand(value); |
2005 if (reversed) { | 2003 if (reversed) { |
2006 return LikelySmiBinaryOperation(expr, &unsafe_operand, operand, | 2004 return LikelySmiBinaryOperation(expr, &unsafe_operand, operand, |
2007 overwrite_mode); | 2005 overwrite_mode); |
2008 } else { | 2006 } else { |
2009 return LikelySmiBinaryOperation(expr, operand, &unsafe_operand, | 2007 return LikelySmiBinaryOperation(expr, operand, &unsafe_operand, |
2010 overwrite_mode); | 2008 overwrite_mode); |
2011 } | 2009 } |
2012 } | 2010 } |
(...skipping 11104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13117 | 13115 |
13118 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) | 13116 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) |
13119 // tagged as a small integer. | 13117 // tagged as a small integer. |
13120 __ bind(&runtime); | 13118 __ bind(&runtime); |
13121 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); | 13119 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); |
13122 } | 13120 } |
13123 | 13121 |
13124 #undef __ | 13122 #undef __ |
13125 | 13123 |
13126 } } // namespace v8::internal | 13124 } } // namespace v8::internal |
OLD | NEW |