| OLD | NEW | 
|---|
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 304 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 315 #ifdef ENABLE_DEBUGGER_SUPPORT | 315 #ifdef ENABLE_DEBUGGER_SUPPORT | 
| 316     // Check that the size of the code used for returning is large enough | 316     // Check that the size of the code used for returning is large enough | 
| 317     // for the debugger's requirements. | 317     // for the debugger's requirements. | 
| 318     ASSERT(Assembler::kJSReturnSequenceLength <= | 318     ASSERT(Assembler::kJSReturnSequenceLength <= | 
| 319            masm_->SizeOfCodeGeneratedSince(&check_exit_codesize)); | 319            masm_->SizeOfCodeGeneratedSince(&check_exit_codesize)); | 
| 320 #endif | 320 #endif | 
| 321   } | 321   } | 
| 322 } | 322 } | 
| 323 | 323 | 
| 324 | 324 | 
| 325 FullCodeGenerator::ConstantOperand FullCodeGenerator::GetConstantOperand( |  | 
| 326     Token::Value op, Expression* left, Expression* right) { |  | 
| 327   ASSERT(ShouldInlineSmiCase(op)); |  | 
| 328   if (op == Token::DIV || op == Token::MOD || op == Token::MUL) { |  | 
| 329     // We never generate inlined constant smi operations for these. |  | 
| 330     return kNoConstants; |  | 
| 331   } else if (right->IsSmiLiteral()) { |  | 
| 332     return kRightConstant; |  | 
| 333   } else if (left->IsSmiLiteral() && !Token::IsShiftOp(op)) { |  | 
| 334     // Don't inline shifts with constant left hand side. |  | 
| 335     return kLeftConstant; |  | 
| 336   } else { |  | 
| 337     return kNoConstants; |  | 
| 338   } |  | 
| 339 } |  | 
| 340 |  | 
| 341 |  | 
| 342 void FullCodeGenerator::EffectContext::Plug(Slot* slot) const { | 325 void FullCodeGenerator::EffectContext::Plug(Slot* slot) const { | 
| 343 } | 326 } | 
| 344 | 327 | 
| 345 | 328 | 
| 346 void FullCodeGenerator::AccumulatorValueContext::Plug(Slot* slot) const { | 329 void FullCodeGenerator::AccumulatorValueContext::Plug(Slot* slot) const { | 
| 347   MemOperand slot_operand = codegen()->EmitSlotSearch(slot, result_register()); | 330   MemOperand slot_operand = codegen()->EmitSlotSearch(slot, result_register()); | 
| 348   __ mov(result_register(), slot_operand); | 331   __ mov(result_register(), slot_operand); | 
| 349 } | 332 } | 
| 350 | 333 | 
| 351 | 334 | 
| (...skipping 1213 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1565       } | 1548       } | 
| 1566     } | 1549     } | 
| 1567 | 1550 | 
| 1568     // For property compound assignments we need another deoptimization | 1551     // For property compound assignments we need another deoptimization | 
| 1569     // point after the property load. | 1552     // point after the property load. | 
| 1570     if (property != NULL) { | 1553     if (property != NULL) { | 
| 1571       PrepareForBailoutForId(expr->CompoundLoadId(), TOS_REG); | 1554       PrepareForBailoutForId(expr->CompoundLoadId(), TOS_REG); | 
| 1572     } | 1555     } | 
| 1573 | 1556 | 
| 1574     Token::Value op = expr->binary_op(); | 1557     Token::Value op = expr->binary_op(); | 
| 1575     ConstantOperand constant = ShouldInlineSmiCase(op) | 1558     __ push(eax);  // Left operand goes on the stack. | 
| 1576         ? GetConstantOperand(op, expr->target(), expr->value()) | 1559     VisitForAccumulatorValue(expr->value()); | 
| 1577         : kNoConstants; |  | 
| 1578     ASSERT(constant == kRightConstant || constant == kNoConstants); |  | 
| 1579     if (constant == kNoConstants) { |  | 
| 1580       __ push(eax);  // Left operand goes on the stack. |  | 
| 1581       VisitForAccumulatorValue(expr->value()); |  | 
| 1582     } |  | 
| 1583 | 1560 | 
| 1584     OverwriteMode mode = expr->value()->ResultOverwriteAllowed() | 1561     OverwriteMode mode = expr->value()->ResultOverwriteAllowed() | 
| 1585         ? OVERWRITE_RIGHT | 1562         ? OVERWRITE_RIGHT | 
| 1586         : NO_OVERWRITE; | 1563         : NO_OVERWRITE; | 
| 1587     SetSourcePosition(expr->position() + 1); | 1564     SetSourcePosition(expr->position() + 1); | 
| 1588     AccumulatorValueContext context(this); | 1565     AccumulatorValueContext context(this); | 
| 1589     if (ShouldInlineSmiCase(op)) { | 1566     if (ShouldInlineSmiCase(op)) { | 
| 1590       EmitInlineSmiBinaryOp(expr, | 1567       EmitInlineSmiBinaryOp(expr, | 
| 1591                             op, | 1568                             op, | 
| 1592                             mode, | 1569                             mode, | 
| 1593                             expr->target(), | 1570                             expr->target(), | 
| 1594                             expr->value(), | 1571                             expr->value()); | 
| 1595                             constant); |  | 
| 1596     } else { | 1572     } else { | 
| 1597       EmitBinaryOp(op, mode); | 1573       EmitBinaryOp(op, mode); | 
| 1598     } | 1574     } | 
| 1599 | 1575 | 
| 1600     // Deoptimization point in case the binary operation may have side effects. | 1576     // Deoptimization point in case the binary operation may have side effects. | 
| 1601     PrepareForBailout(expr->binary_operation(), TOS_REG); | 1577     PrepareForBailout(expr->binary_operation(), TOS_REG); | 
| 1602   } else { | 1578   } else { | 
| 1603     VisitForAccumulatorValue(expr->value()); | 1579     VisitForAccumulatorValue(expr->value()); | 
| 1604   } | 1580   } | 
| 1605 | 1581 | 
| (...skipping 27 matching lines...) Expand all  Loading... | 
| 1633 } | 1609 } | 
| 1634 | 1610 | 
| 1635 | 1611 | 
| 1636 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { | 1612 void FullCodeGenerator::EmitKeyedPropertyLoad(Property* prop) { | 
| 1637   SetSourcePosition(prop->position()); | 1613   SetSourcePosition(prop->position()); | 
| 1638   Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 1614   Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 
| 1639   EmitCallIC(ic, RelocInfo::CODE_TARGET); | 1615   EmitCallIC(ic, RelocInfo::CODE_TARGET); | 
| 1640 } | 1616 } | 
| 1641 | 1617 | 
| 1642 | 1618 | 
| 1643 void FullCodeGenerator::EmitConstantSmiAdd(Expression* expr, |  | 
| 1644                                            OverwriteMode mode, |  | 
| 1645                                            bool left_is_constant_smi, |  | 
| 1646                                            Smi* value) { |  | 
| 1647   NearLabel call_stub, done; |  | 
| 1648   // Optimistically add smi value with unknown object. If result overflows or is |  | 
| 1649   // not a smi then we had either a smi overflow or added a smi with a tagged |  | 
| 1650   // pointer. |  | 
| 1651   __ add(Operand(eax), Immediate(value)); |  | 
| 1652   __ j(overflow, &call_stub); |  | 
| 1653   JumpPatchSite patch_site(masm_); |  | 
| 1654   patch_site.EmitJumpIfSmi(eax, &done); |  | 
| 1655 |  | 
| 1656   // Undo the optimistic add operation and call the shared stub. |  | 
| 1657   __ bind(&call_stub); |  | 
| 1658   __ sub(Operand(eax), Immediate(value)); |  | 
| 1659   TypeRecordingBinaryOpStub stub(Token::ADD, mode); |  | 
| 1660   if (left_is_constant_smi) { |  | 
| 1661     __ mov(edx, Immediate(value)); |  | 
| 1662   } else { |  | 
| 1663     __ mov(edx, eax); |  | 
| 1664     __ mov(eax, Immediate(value)); |  | 
| 1665   } |  | 
| 1666   EmitCallIC(stub.GetCode(), &patch_site); |  | 
| 1667 |  | 
| 1668   __ bind(&done); |  | 
| 1669   context()->Plug(eax); |  | 
| 1670 } |  | 
| 1671 |  | 
| 1672 |  | 
| 1673 void FullCodeGenerator::EmitConstantSmiSub(Expression* expr, |  | 
| 1674                                            OverwriteMode mode, |  | 
| 1675                                            bool left_is_constant_smi, |  | 
| 1676                                            Smi* value) { |  | 
| 1677   NearLabel call_stub, done; |  | 
| 1678   // Optimistically subtract smi value with unknown object. If result overflows |  | 
| 1679   // or is not a smi then we had either a smi overflow or added a smi with a |  | 
| 1680   // tagged pointer. |  | 
| 1681   if (left_is_constant_smi) { |  | 
| 1682     __ mov(ecx, eax); |  | 
| 1683     __ mov(eax, Immediate(value)); |  | 
| 1684     __ sub(Operand(eax), ecx); |  | 
| 1685   } else { |  | 
| 1686     __ sub(Operand(eax), Immediate(value)); |  | 
| 1687   } |  | 
| 1688   __ j(overflow, &call_stub); |  | 
| 1689   JumpPatchSite patch_site(masm_); |  | 
| 1690   patch_site.EmitJumpIfSmi(eax, &done); |  | 
| 1691 |  | 
| 1692   __ bind(&call_stub); |  | 
| 1693   if (left_is_constant_smi) { |  | 
| 1694     __ mov(edx, Immediate(value)); |  | 
| 1695     __ mov(eax, ecx); |  | 
| 1696   } else { |  | 
| 1697     __ add(Operand(eax), Immediate(value));  // Undo the subtraction. |  | 
| 1698     __ mov(edx, eax); |  | 
| 1699     __ mov(eax, Immediate(value)); |  | 
| 1700   } |  | 
| 1701   TypeRecordingBinaryOpStub stub(Token::SUB, mode); |  | 
| 1702   EmitCallIC(stub.GetCode(), &patch_site); |  | 
| 1703 |  | 
| 1704   __ bind(&done); |  | 
| 1705   context()->Plug(eax); |  | 
| 1706 } |  | 
| 1707 |  | 
| 1708 |  | 
| 1709 void FullCodeGenerator::EmitConstantSmiShiftOp(Expression* expr, |  | 
| 1710                                                Token::Value op, |  | 
| 1711                                                OverwriteMode mode, |  | 
| 1712                                                Smi* value) { |  | 
| 1713   NearLabel call_stub, smi_case, done; |  | 
| 1714   int shift_value = value->value() & 0x1f; |  | 
| 1715 |  | 
| 1716   JumpPatchSite patch_site(masm_); |  | 
| 1717   patch_site.EmitJumpIfSmi(eax, &smi_case); |  | 
| 1718 |  | 
| 1719   // Call stub. |  | 
| 1720   __ bind(&call_stub); |  | 
| 1721   __ mov(edx, eax); |  | 
| 1722   __ mov(eax, Immediate(value)); |  | 
| 1723   TypeRecordingBinaryOpStub stub(op, mode); |  | 
| 1724   EmitCallIC(stub.GetCode(), &patch_site); |  | 
| 1725   __ jmp(&done); |  | 
| 1726 |  | 
| 1727   // Smi case. |  | 
| 1728   __ bind(&smi_case); |  | 
| 1729   switch (op) { |  | 
| 1730     case Token::SHL: |  | 
| 1731       if (shift_value != 0) { |  | 
| 1732         __ mov(edx, eax); |  | 
| 1733         if (shift_value > 1) { |  | 
| 1734           __ shl(edx, shift_value - 1); |  | 
| 1735         } |  | 
| 1736         // Convert int result to smi, checking that it is in int range. |  | 
| 1737         STATIC_ASSERT(kSmiTagSize == 1);  // Adjust code if not the case. |  | 
| 1738         __ add(edx, Operand(edx)); |  | 
| 1739         __ j(overflow, &call_stub); |  | 
| 1740         __ mov(eax, edx);  // Put result back into eax. |  | 
| 1741       } |  | 
| 1742       break; |  | 
| 1743     case Token::SAR: |  | 
| 1744       if (shift_value != 0) { |  | 
| 1745         __ sar(eax, shift_value); |  | 
| 1746         __ and_(eax, ~kSmiTagMask); |  | 
| 1747       } |  | 
| 1748       break; |  | 
| 1749     case Token::SHR: |  | 
| 1750       // SHR must return a positive value. When shifting by 0 or 1 we need to |  | 
| 1751       // check that smi tagging the result will not create a negative value. |  | 
| 1752       if (shift_value < 2) { |  | 
| 1753         __ mov(edx, eax); |  | 
| 1754         __ SmiUntag(edx); |  | 
| 1755         __ shr(edx, shift_value); |  | 
| 1756         __ test(edx, Immediate(0xc0000000)); |  | 
| 1757         __ j(not_zero, &call_stub); |  | 
| 1758         __ SmiTag(edx); |  | 
| 1759         __ mov(eax, edx);  // Put result back into eax. |  | 
| 1760       } else { |  | 
| 1761         __ SmiUntag(eax); |  | 
| 1762         __ shr(eax, shift_value); |  | 
| 1763         __ SmiTag(eax); |  | 
| 1764       } |  | 
| 1765       break; |  | 
| 1766     default: |  | 
| 1767       UNREACHABLE(); |  | 
| 1768   } |  | 
| 1769 |  | 
| 1770   __ bind(&done); |  | 
| 1771   context()->Plug(eax); |  | 
| 1772 } |  | 
| 1773 |  | 
| 1774 |  | 
| 1775 void FullCodeGenerator::EmitConstantSmiBitOp(Expression* expr, |  | 
| 1776                                              Token::Value op, |  | 
| 1777                                              OverwriteMode mode, |  | 
| 1778                                              Smi* value) { |  | 
| 1779   NearLabel smi_case, done; |  | 
| 1780 |  | 
| 1781   JumpPatchSite patch_site(masm_); |  | 
| 1782   patch_site.EmitJumpIfSmi(eax, &smi_case); |  | 
| 1783 |  | 
| 1784   // The order of the arguments does not matter for bit-ops with a |  | 
| 1785   // constant operand. |  | 
| 1786   __ mov(edx, Immediate(value)); |  | 
| 1787   TypeRecordingBinaryOpStub stub(op, mode); |  | 
| 1788   EmitCallIC(stub.GetCode(), &patch_site); |  | 
| 1789   __ jmp(&done); |  | 
| 1790 |  | 
| 1791   // Smi case. |  | 
| 1792   __ bind(&smi_case); |  | 
| 1793   switch (op) { |  | 
| 1794     case Token::BIT_OR: |  | 
| 1795       __ or_(Operand(eax), Immediate(value)); |  | 
| 1796       break; |  | 
| 1797     case Token::BIT_XOR: |  | 
| 1798       __ xor_(Operand(eax), Immediate(value)); |  | 
| 1799       break; |  | 
| 1800     case Token::BIT_AND: |  | 
| 1801       __ and_(Operand(eax), Immediate(value)); |  | 
| 1802       break; |  | 
| 1803     default: |  | 
| 1804       UNREACHABLE(); |  | 
| 1805   } |  | 
| 1806 |  | 
| 1807   __ bind(&done); |  | 
| 1808   context()->Plug(eax); |  | 
| 1809 } |  | 
| 1810 |  | 
| 1811 |  | 
| 1812 void FullCodeGenerator::EmitConstantSmiBinaryOp(Expression* expr, |  | 
| 1813                                                 Token::Value op, |  | 
| 1814                                                 OverwriteMode mode, |  | 
| 1815                                                 bool left_is_constant_smi, |  | 
| 1816                                                 Smi* value) { |  | 
| 1817   switch (op) { |  | 
| 1818     case Token::BIT_OR: |  | 
| 1819     case Token::BIT_XOR: |  | 
| 1820     case Token::BIT_AND: |  | 
| 1821       EmitConstantSmiBitOp(expr, op, mode, value); |  | 
| 1822       break; |  | 
| 1823     case Token::SHL: |  | 
| 1824     case Token::SAR: |  | 
| 1825     case Token::SHR: |  | 
| 1826       ASSERT(!left_is_constant_smi); |  | 
| 1827       EmitConstantSmiShiftOp(expr, op, mode, value); |  | 
| 1828       break; |  | 
| 1829     case Token::ADD: |  | 
| 1830       EmitConstantSmiAdd(expr, mode, left_is_constant_smi, value); |  | 
| 1831       break; |  | 
| 1832     case Token::SUB: |  | 
| 1833       EmitConstantSmiSub(expr, mode, left_is_constant_smi, value); |  | 
| 1834       break; |  | 
| 1835     default: |  | 
| 1836       UNREACHABLE(); |  | 
| 1837   } |  | 
| 1838 } |  | 
| 1839 |  | 
| 1840 |  | 
| 1841 void FullCodeGenerator::EmitInlineSmiBinaryOp(Expression* expr, | 1619 void FullCodeGenerator::EmitInlineSmiBinaryOp(Expression* expr, | 
| 1842                                               Token::Value op, | 1620                                               Token::Value op, | 
| 1843                                               OverwriteMode mode, | 1621                                               OverwriteMode mode, | 
| 1844                                               Expression* left, | 1622                                               Expression* left, | 
| 1845                                               Expression* right, | 1623                                               Expression* right) { | 
| 1846                                               ConstantOperand constant) { |  | 
| 1847   if (constant == kRightConstant) { |  | 
| 1848     Smi* value =  Smi::cast(*right->AsLiteral()->handle()); |  | 
| 1849     EmitConstantSmiBinaryOp(expr, op, mode, false, value); |  | 
| 1850     return; |  | 
| 1851   } else if (constant == kLeftConstant) { |  | 
| 1852     Smi* value =  Smi::cast(*left->AsLiteral()->handle()); |  | 
| 1853     EmitConstantSmiBinaryOp(expr, op, mode, true, value); |  | 
| 1854     return; |  | 
| 1855   } |  | 
| 1856 |  | 
| 1857   // Do combined smi check of the operands. Left operand is on the | 1624   // Do combined smi check of the operands. Left operand is on the | 
| 1858   // stack. Right operand is in eax. | 1625   // stack. Right operand is in eax. | 
| 1859   NearLabel done, smi_case, stub_call; | 1626   NearLabel done, smi_case, stub_call; | 
| 1860   __ pop(edx); | 1627   __ pop(edx); | 
| 1861   __ mov(ecx, eax); | 1628   __ mov(ecx, eax); | 
| 1862   __ or_(eax, Operand(edx)); | 1629   __ or_(eax, Operand(edx)); | 
| 1863   JumpPatchSite patch_site(masm_); | 1630   JumpPatchSite patch_site(masm_); | 
| 1864   patch_site.EmitJumpIfSmi(eax, &smi_case); | 1631   patch_site.EmitJumpIfSmi(eax, &smi_case); | 
| 1865 | 1632 | 
| 1866   __ bind(&stub_call); | 1633   __ bind(&stub_call); | 
| (...skipping 2586 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 4453   // And return. | 4220   // And return. | 
| 4454   __ ret(0); | 4221   __ ret(0); | 
| 4455 } | 4222 } | 
| 4456 | 4223 | 
| 4457 | 4224 | 
| 4458 #undef __ | 4225 #undef __ | 
| 4459 | 4226 | 
| 4460 } }  // namespace v8::internal | 4227 } }  // namespace v8::internal | 
| 4461 | 4228 | 
| 4462 #endif  // V8_TARGET_ARCH_IA32 | 4229 #endif  // V8_TARGET_ARCH_IA32 | 
| OLD | NEW | 
|---|