| 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 23 matching lines...) Expand all  Loading... | 
| 34 #include "compiler.h" | 34 #include "compiler.h" | 
| 35 #include "debug.h" | 35 #include "debug.h" | 
| 36 #include "full-codegen.h" | 36 #include "full-codegen.h" | 
| 37 #include "parser.h" | 37 #include "parser.h" | 
| 38 #include "scopes.h" | 38 #include "scopes.h" | 
| 39 #include "stub-cache.h" | 39 #include "stub-cache.h" | 
| 40 | 40 | 
| 41 namespace v8 { | 41 namespace v8 { | 
| 42 namespace internal { | 42 namespace internal { | 
| 43 | 43 | 
| 44 |  | 
| 45 class JumpPatchSite BASE_EMBEDDED { |  | 
| 46  public: |  | 
| 47   explicit JumpPatchSite(MacroAssembler* masm) |  | 
| 48       : masm_(masm) { |  | 
| 49 #ifdef DEBUG |  | 
| 50     info_emitted_ = false; |  | 
| 51 #endif |  | 
| 52   } |  | 
| 53 |  | 
| 54   ~JumpPatchSite() { |  | 
| 55     ASSERT(patch_site_.is_bound() == info_emitted_); |  | 
| 56   } |  | 
| 57 |  | 
| 58   void EmitJump(NearLabel* target) { |  | 
| 59     ASSERT(!patch_site_.is_bound() && !info_emitted_); |  | 
| 60     masm_->bind(&patch_site_); |  | 
| 61     masm_->jmp(target); |  | 
| 62   } |  | 
| 63 |  | 
| 64   void EmitPatchInfo() { |  | 
| 65     int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(&patch_site_); |  | 
| 66     ASSERT(is_int8(delta_to_patch_site)); |  | 
| 67     masm_->test(eax, Immediate(delta_to_patch_site)); |  | 
| 68 #ifdef DEBUG |  | 
| 69     info_emitted_ = true; |  | 
| 70 #endif |  | 
| 71   } |  | 
| 72 |  | 
| 73   bool is_bound() const { return patch_site_.is_bound(); } |  | 
| 74 |  | 
| 75  private: |  | 
| 76   MacroAssembler* masm_; |  | 
| 77   Label patch_site_; |  | 
| 78 #ifdef DEBUG |  | 
| 79   bool info_emitted_; |  | 
| 80 #endif |  | 
| 81 }; |  | 
| 82 |  | 
| 83 |  | 
| 84 #define __ ACCESS_MASM(masm_) | 44 #define __ ACCESS_MASM(masm_) | 
| 85 | 45 | 
| 86 // Generate code for a JS function.  On entry to the function the receiver | 46 // Generate code for a JS function.  On entry to the function the receiver | 
| 87 // and arguments have been pushed on the stack left to right, with the | 47 // and arguments have been pushed on the stack left to right, with the | 
| 88 // return address on top of them.  The actual argument count matches the | 48 // return address on top of them.  The actual argument count matches the | 
| 89 // formal parameter count expected by the function. | 49 // formal parameter count expected by the function. | 
| 90 // | 50 // | 
| 91 // The live registers are: | 51 // The live registers are: | 
| 92 //   o edi: the JS function object being called (ie, ourselves) | 52 //   o edi: the JS function object being called (ie, ourselves) | 
| 93 //   o esi: our context | 53 //   o esi: our context | 
| (...skipping 654 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 748     Comment cmnt(masm_, "[ Case comparison"); | 708     Comment cmnt(masm_, "[ Case comparison"); | 
| 749     __ bind(&next_test); | 709     __ bind(&next_test); | 
| 750     next_test.Unuse(); | 710     next_test.Unuse(); | 
| 751 | 711 | 
| 752     // Compile the label expression. | 712     // Compile the label expression. | 
| 753     VisitForAccumulatorValue(clause->label()); | 713     VisitForAccumulatorValue(clause->label()); | 
| 754 | 714 | 
| 755     // Perform the comparison as if via '==='. | 715     // Perform the comparison as if via '==='. | 
| 756     __ mov(edx, Operand(esp, 0));  // Switch value. | 716     __ mov(edx, Operand(esp, 0));  // Switch value. | 
| 757     bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT); | 717     bool inline_smi_code = ShouldInlineSmiCase(Token::EQ_STRICT); | 
| 758     JumpPatchSite patch_site(masm_); |  | 
| 759     if (inline_smi_code) { | 718     if (inline_smi_code) { | 
| 760       NearLabel slow_case; | 719       NearLabel slow_case; | 
| 761       __ mov(ecx, edx); | 720       __ mov(ecx, edx); | 
| 762       __ or_(ecx, Operand(eax)); | 721       __ or_(ecx, Operand(eax)); | 
| 763       __ test(ecx, Immediate(kSmiTagMask)); | 722       __ test(ecx, Immediate(kSmiTagMask)); | 
| 764       patch_site.EmitJump(&slow_case); | 723       __ j(not_zero, &slow_case, not_taken); | 
| 765       __ cmp(edx, Operand(eax)); | 724       __ cmp(edx, Operand(eax)); | 
| 766       __ j(not_equal, &next_test); | 725       __ j(not_equal, &next_test); | 
| 767       __ Drop(1);  // Switch value is no longer needed. | 726       __ Drop(1);  // Switch value is no longer needed. | 
| 768       __ jmp(clause->body_target()->entry_label()); | 727       __ jmp(clause->body_target()->entry_label()); | 
| 769       __ bind(&slow_case); | 728       __ bind(&slow_case); | 
| 770     } | 729     } | 
| 771 | 730 | 
| 772     // Record position before stub call for type feedback. | 731     // Record position before stub call for type feedback. | 
| 773     SetSourcePosition(clause->position()); | 732     SetSourcePosition(clause->position()); | 
|  | 733 | 
| 774     Handle<Code> ic = CompareIC::GetUninitialized(Token::EQ_STRICT); | 734     Handle<Code> ic = CompareIC::GetUninitialized(Token::EQ_STRICT); | 
| 775     EmitCallIC(ic, &patch_site); | 735     __ call(ic, RelocInfo::CODE_TARGET); | 
| 776 | 736 | 
| 777     __ test(eax, Operand(eax)); | 737     __ test(eax, Operand(eax)); | 
| 778     __ j(not_equal, &next_test); | 738     __ j(not_equal, &next_test); | 
| 779     __ Drop(1);  // Switch value is no longer needed. | 739     __ Drop(1);  // Switch value is no longer needed. | 
| 780     __ jmp(clause->body_target()->entry_label()); | 740     __ jmp(clause->body_target()->entry_label()); | 
| 781   } | 741   } | 
| 782 | 742 | 
| 783   // Discard the test value and jump to the default if present, otherwise to | 743   // Discard the test value and jump to the default if present, otherwise to | 
| 784   // the end of the statement. | 744   // the end of the statement. | 
| 785   __ bind(&next_test); | 745   __ bind(&next_test); | 
| (...skipping 799 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1585   SetSourcePosition(prop->position()); | 1545   SetSourcePosition(prop->position()); | 
| 1586   Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 1546   Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 
| 1587   EmitCallIC(ic, RelocInfo::CODE_TARGET); | 1547   EmitCallIC(ic, RelocInfo::CODE_TARGET); | 
| 1588 } | 1548 } | 
| 1589 | 1549 | 
| 1590 | 1550 | 
| 1591 void FullCodeGenerator::EmitConstantSmiAdd(Expression* expr, | 1551 void FullCodeGenerator::EmitConstantSmiAdd(Expression* expr, | 
| 1592                                            OverwriteMode mode, | 1552                                            OverwriteMode mode, | 
| 1593                                            bool left_is_constant_smi, | 1553                                            bool left_is_constant_smi, | 
| 1594                                            Smi* value) { | 1554                                            Smi* value) { | 
| 1595   NearLabel call_stub, done; | 1555   NearLabel call_stub; | 
|  | 1556   Label done; | 
| 1596   __ add(Operand(eax), Immediate(value)); | 1557   __ add(Operand(eax), Immediate(value)); | 
| 1597   __ j(overflow, &call_stub); | 1558   __ j(overflow, &call_stub); | 
| 1598   __ test(eax, Immediate(kSmiTagMask)); | 1559   __ test(eax, Immediate(kSmiTagMask)); | 
| 1599   JumpPatchSite patch_site(masm_); | 1560   __ j(zero, &done); | 
| 1600   patch_site.EmitJump(&call_stub); |  | 
| 1601   __ jmp(&done); |  | 
| 1602 | 1561 | 
| 1603   // Undo the optimistic add operation and call the shared stub. | 1562   // Undo the optimistic add operation and call the shared stub. | 
| 1604   __ bind(&call_stub); | 1563   __ bind(&call_stub); | 
| 1605   __ sub(Operand(eax), Immediate(value)); | 1564   __ sub(Operand(eax), Immediate(value)); | 
| 1606   Token::Value op = Token::ADD; | 1565   Token::Value op = Token::ADD; | 
| 1607   TypeRecordingBinaryOpStub stub(op, mode); | 1566   TypeRecordingBinaryOpStub stub(op, mode); | 
| 1608   if (left_is_constant_smi) { | 1567   if (left_is_constant_smi) { | 
| 1609     __ mov(edx, Immediate(value)); | 1568     __ mov(edx, Immediate(value)); | 
| 1610   } else { | 1569   } else { | 
| 1611     __ mov(edx, eax); | 1570     __ mov(edx, eax); | 
| 1612     __ mov(eax, Immediate(value)); | 1571     __ mov(eax, Immediate(value)); | 
| 1613   } | 1572   } | 
| 1614   EmitCallIC(stub.GetCode(), &patch_site); | 1573   __ CallStub(&stub); | 
| 1615 |  | 
| 1616   __ bind(&done); | 1574   __ bind(&done); | 
| 1617   context()->Plug(eax); | 1575   context()->Plug(eax); | 
| 1618 } | 1576 } | 
| 1619 | 1577 | 
| 1620 | 1578 | 
| 1621 void FullCodeGenerator::EmitConstantSmiSub(Expression* expr, | 1579 void FullCodeGenerator::EmitConstantSmiSub(Expression* expr, | 
| 1622                                            OverwriteMode mode, | 1580                                            OverwriteMode mode, | 
| 1623                                            bool left_is_constant_smi, | 1581                                            bool left_is_constant_smi, | 
| 1624                                            Smi* value) { | 1582                                            Smi* value) { | 
| 1625   NearLabel call_stub, done; | 1583   Label call_stub, done; | 
| 1626   if (left_is_constant_smi) { | 1584   if (left_is_constant_smi) { | 
| 1627     __ mov(ecx, eax); | 1585     __ mov(ecx, eax); | 
| 1628     __ mov(eax, Immediate(value)); | 1586     __ mov(eax, Immediate(value)); | 
| 1629     __ sub(Operand(eax), ecx); | 1587     __ sub(Operand(eax), ecx); | 
| 1630   } else { | 1588   } else { | 
| 1631     __ sub(Operand(eax), Immediate(value)); | 1589     __ sub(Operand(eax), Immediate(value)); | 
| 1632   } | 1590   } | 
| 1633   __ j(overflow, &call_stub); | 1591   __ j(overflow, &call_stub); | 
| 1634   __ test(eax, Immediate(kSmiTagMask)); | 1592   __ test(eax, Immediate(kSmiTagMask)); | 
| 1635   JumpPatchSite patch_site(masm_); | 1593   __ j(zero, &done); | 
| 1636   patch_site.EmitJump(&call_stub); |  | 
| 1637   __ jmp(&done); |  | 
| 1638 | 1594 | 
| 1639   __ bind(&call_stub); | 1595   __ bind(&call_stub); | 
| 1640   if (left_is_constant_smi) { | 1596   if (left_is_constant_smi) { | 
| 1641     __ mov(edx, Immediate(value)); | 1597     __ mov(edx, Immediate(value)); | 
| 1642     __ mov(eax, ecx); | 1598     __ mov(eax, ecx); | 
| 1643   } else { | 1599   } else { | 
| 1644     __ add(Operand(eax), Immediate(value));  // Undo the subtraction. | 1600     __ add(Operand(eax), Immediate(value));  // Undo the subtraction. | 
| 1645     __ mov(edx, eax); | 1601     __ mov(edx, eax); | 
| 1646     __ mov(eax, Immediate(value)); | 1602     __ mov(eax, Immediate(value)); | 
| 1647   } | 1603   } | 
| 1648   Token::Value op = Token::SUB; | 1604   Token::Value op = Token::SUB; | 
| 1649   TypeRecordingBinaryOpStub stub(op, mode); | 1605   TypeRecordingBinaryOpStub stub(op, mode); | 
| 1650   EmitCallIC(stub.GetCode(), &patch_site); | 1606   __ CallStub(&stub); | 
| 1651 |  | 
| 1652   __ bind(&done); | 1607   __ bind(&done); | 
| 1653   context()->Plug(eax); | 1608   context()->Plug(eax); | 
| 1654 } | 1609 } | 
| 1655 | 1610 | 
| 1656 | 1611 | 
| 1657 void FullCodeGenerator::EmitConstantSmiShiftOp(Expression* expr, | 1612 void FullCodeGenerator::EmitConstantSmiShiftOp(Expression* expr, | 
| 1658                                                Token::Value op, | 1613                                                Token::Value op, | 
| 1659                                                OverwriteMode mode, | 1614                                                OverwriteMode mode, | 
| 1660                                                Smi* value) { | 1615                                                Smi* value) { | 
| 1661   NearLabel call_stub, done; | 1616   Label call_stub, smi_case, done; | 
| 1662   int shift_value = value->value() & 0x1f; | 1617   int shift_value = value->value() & 0x1f; | 
| 1663 | 1618 | 
| 1664   __ test(eax, Immediate(kSmiTagMask)); | 1619   __ test(eax, Immediate(kSmiTagMask)); | 
| 1665   // Patch site. | 1620   __ j(zero, &smi_case); | 
| 1666   JumpPatchSite patch_site(masm_); |  | 
| 1667   patch_site.EmitJump(&call_stub); |  | 
| 1668 | 1621 | 
| 1669   // Smi case. | 1622   __ bind(&call_stub); | 
|  | 1623   __ mov(edx, eax); | 
|  | 1624   __ mov(eax, Immediate(value)); | 
|  | 1625   TypeRecordingBinaryOpStub stub(op, mode); | 
|  | 1626   __ CallStub(&stub); | 
|  | 1627   __ jmp(&done); | 
|  | 1628 | 
|  | 1629   __ bind(&smi_case); | 
| 1670   switch (op) { | 1630   switch (op) { | 
| 1671     case Token::SHL: | 1631     case Token::SHL: | 
| 1672       if (shift_value != 0) { | 1632       if (shift_value != 0) { | 
| 1673         __ mov(edx, eax); | 1633         __ mov(edx, eax); | 
| 1674         if (shift_value > 1) { | 1634         if (shift_value > 1) { | 
| 1675           __ shl(edx, shift_value - 1); | 1635           __ shl(edx, shift_value - 1); | 
| 1676         } | 1636         } | 
| 1677         // Convert int result to smi, checking that it is in int range. | 1637         // Convert int result to smi, checking that it is in int range. | 
| 1678         ASSERT(kSmiTagSize == 1);  // Adjust code if not the case. | 1638         ASSERT(kSmiTagSize == 1);  // Adjust code if not the case. | 
| 1679         __ add(edx, Operand(edx)); | 1639         __ add(edx, Operand(edx)); | 
| (...skipping 18 matching lines...) Expand all  Loading... | 
| 1698         __ mov(eax, edx);  // Put result back into eax. | 1658         __ mov(eax, edx);  // Put result back into eax. | 
| 1699       } else { | 1659       } else { | 
| 1700         __ SmiUntag(eax); | 1660         __ SmiUntag(eax); | 
| 1701         __ shr(eax, shift_value); | 1661         __ shr(eax, shift_value); | 
| 1702         __ SmiTag(eax); | 1662         __ SmiTag(eax); | 
| 1703       } | 1663       } | 
| 1704       break; | 1664       break; | 
| 1705     default: | 1665     default: | 
| 1706       UNREACHABLE(); | 1666       UNREACHABLE(); | 
| 1707   } | 1667   } | 
| 1708   __ jmp(&done); |  | 
| 1709 |  | 
| 1710   // Call stub. |  | 
| 1711   __ bind(&call_stub); |  | 
| 1712   __ mov(edx, eax); |  | 
| 1713   __ mov(eax, Immediate(value)); |  | 
| 1714   TypeRecordingBinaryOpStub stub(op, mode); |  | 
| 1715   EmitCallIC(stub.GetCode(), &patch_site); |  | 
| 1716 | 1668 | 
| 1717   __ bind(&done); | 1669   __ bind(&done); | 
| 1718   context()->Plug(eax); | 1670   context()->Plug(eax); | 
| 1719 } | 1671 } | 
| 1720 | 1672 | 
| 1721 | 1673 | 
| 1722 void FullCodeGenerator::EmitConstantSmiBitOp(Expression* expr, | 1674 void FullCodeGenerator::EmitConstantSmiBitOp(Expression* expr, | 
| 1723                                              Token::Value op, | 1675                                              Token::Value op, | 
| 1724                                              OverwriteMode mode, | 1676                                              OverwriteMode mode, | 
| 1725                                              Smi* value) { | 1677                                              Smi* value) { | 
| 1726   NearLabel call_stub, done; | 1678   Label smi_case, done; | 
| 1727   __ test(eax, Immediate(kSmiTagMask)); | 1679   __ test(eax, Immediate(kSmiTagMask)); | 
| 1728   // Patch site. The first invocation of the stub will be patch the jmp with | 1680   __ j(zero, &smi_case); | 
| 1729   // the required conditional jump. |  | 
| 1730   JumpPatchSite patch_site(masm_); |  | 
| 1731   patch_site.EmitJump(&call_stub); |  | 
| 1732 | 1681 | 
| 1733   // Smi case. | 1682   // The order of the arguments does not matter for bit-ops with a | 
|  | 1683   // constant operand. | 
|  | 1684   __ mov(edx, Immediate(value)); | 
|  | 1685   TypeRecordingBinaryOpStub stub(op, mode); | 
|  | 1686   __ CallStub(&stub); | 
|  | 1687   __ jmp(&done); | 
|  | 1688 | 
|  | 1689   __ bind(&smi_case); | 
| 1734   switch (op) { | 1690   switch (op) { | 
| 1735     case Token::BIT_OR: | 1691     case Token::BIT_OR: | 
| 1736       __ or_(Operand(eax), Immediate(value)); | 1692       __ or_(Operand(eax), Immediate(value)); | 
| 1737       break; | 1693       break; | 
| 1738     case Token::BIT_XOR: | 1694     case Token::BIT_XOR: | 
| 1739       __ xor_(Operand(eax), Immediate(value)); | 1695       __ xor_(Operand(eax), Immediate(value)); | 
| 1740       break; | 1696       break; | 
| 1741     case Token::BIT_AND: | 1697     case Token::BIT_AND: | 
| 1742       __ and_(Operand(eax), Immediate(value)); | 1698       __ and_(Operand(eax), Immediate(value)); | 
| 1743       break; | 1699       break; | 
| 1744     default: | 1700     default: | 
| 1745       UNREACHABLE(); | 1701       UNREACHABLE(); | 
| 1746   } | 1702   } | 
| 1747   __ jmp(&done); |  | 
| 1748 |  | 
| 1749   // The order of the arguments does not matter for bit-ops with a |  | 
| 1750   // constant operand. |  | 
| 1751   __ bind(&call_stub); |  | 
| 1752   __ mov(edx, Immediate(value)); |  | 
| 1753   TypeRecordingBinaryOpStub stub(op, mode); |  | 
| 1754   EmitCallIC(stub.GetCode(), &patch_site); |  | 
| 1755 | 1703 | 
| 1756   __ bind(&done); | 1704   __ bind(&done); | 
| 1757   context()->Plug(eax); | 1705   context()->Plug(eax); | 
| 1758 } | 1706 } | 
| 1759 | 1707 | 
| 1760 | 1708 | 
| 1761 void FullCodeGenerator::EmitConstantSmiBinaryOp(Expression* expr, | 1709 void FullCodeGenerator::EmitConstantSmiBinaryOp(Expression* expr, | 
| 1762                                                 Token::Value op, | 1710                                                 Token::Value op, | 
| 1763                                                 OverwriteMode mode, | 1711                                                 OverwriteMode mode, | 
| 1764                                                 bool left_is_constant_smi, | 1712                                                 bool left_is_constant_smi, | 
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1798     EmitConstantSmiBinaryOp(expr, op, mode, false, value); | 1746     EmitConstantSmiBinaryOp(expr, op, mode, false, value); | 
| 1799     return; | 1747     return; | 
| 1800   } else if (constant == kLeftConstant) { | 1748   } else if (constant == kLeftConstant) { | 
| 1801     Smi* value =  Smi::cast(*left->AsLiteral()->handle()); | 1749     Smi* value =  Smi::cast(*left->AsLiteral()->handle()); | 
| 1802     EmitConstantSmiBinaryOp(expr, op, mode, true, value); | 1750     EmitConstantSmiBinaryOp(expr, op, mode, true, value); | 
| 1803     return; | 1751     return; | 
| 1804   } | 1752   } | 
| 1805 | 1753 | 
| 1806   // Do combined smi check of the operands. Left operand is on the | 1754   // Do combined smi check of the operands. Left operand is on the | 
| 1807   // stack. Right operand is in eax. | 1755   // stack. Right operand is in eax. | 
| 1808   NearLabel done, stub_call; | 1756   Label done, stub_call, smi_case; | 
| 1809   __ pop(edx); | 1757   __ pop(edx); | 
| 1810   __ mov(ecx, eax); | 1758   __ mov(ecx, eax); | 
| 1811   __ or_(eax, Operand(edx)); | 1759   __ or_(eax, Operand(edx)); | 
| 1812   __ test(eax, Immediate(kSmiTagMask)); | 1760   __ test(eax, Immediate(kSmiTagMask)); | 
| 1813   JumpPatchSite patch_site(masm_); | 1761   __ j(zero, &smi_case); | 
| 1814   patch_site.EmitJump(&stub_call); |  | 
| 1815 | 1762 | 
| 1816   // Smi case. | 1763   __ bind(&stub_call); | 
|  | 1764   __ mov(eax, ecx); | 
|  | 1765   TypeRecordingBinaryOpStub stub(op, mode); | 
|  | 1766   __ CallStub(&stub); | 
|  | 1767   __ jmp(&done); | 
|  | 1768 | 
|  | 1769   __ bind(&smi_case); | 
| 1817   __ mov(eax, edx);  // Copy left operand in case of a stub call. | 1770   __ mov(eax, edx);  // Copy left operand in case of a stub call. | 
| 1818 | 1771 | 
| 1819   switch (op) { | 1772   switch (op) { | 
| 1820     case Token::SAR: | 1773     case Token::SAR: | 
| 1821       __ SmiUntag(eax); | 1774       __ SmiUntag(eax); | 
| 1822       __ SmiUntag(ecx); | 1775       __ SmiUntag(ecx); | 
| 1823       __ sar_cl(eax);  // No checks of result necessary | 1776       __ sar_cl(eax);  // No checks of result necessary | 
| 1824       __ SmiTag(eax); | 1777       __ SmiTag(eax); | 
| 1825       break; | 1778       break; | 
| 1826     case Token::SHL: { | 1779     case Token::SHL: { | 
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1874       break; | 1827       break; | 
| 1875     case Token::BIT_AND: | 1828     case Token::BIT_AND: | 
| 1876       __ and_(eax, Operand(ecx)); | 1829       __ and_(eax, Operand(ecx)); | 
| 1877       break; | 1830       break; | 
| 1878     case Token::BIT_XOR: | 1831     case Token::BIT_XOR: | 
| 1879       __ xor_(eax, Operand(ecx)); | 1832       __ xor_(eax, Operand(ecx)); | 
| 1880       break; | 1833       break; | 
| 1881     default: | 1834     default: | 
| 1882       UNREACHABLE(); | 1835       UNREACHABLE(); | 
| 1883   } | 1836   } | 
| 1884   __ jmp(&done); |  | 
| 1885 |  | 
| 1886   __ bind(&stub_call); |  | 
| 1887   __ mov(eax, ecx); |  | 
| 1888   TypeRecordingBinaryOpStub stub(op, mode); |  | 
| 1889   EmitCallIC(stub.GetCode(), &patch_site); |  | 
| 1890 | 1837 | 
| 1891   __ bind(&done); | 1838   __ bind(&done); | 
| 1892   context()->Plug(eax); | 1839   context()->Plug(eax); | 
| 1893 } | 1840 } | 
| 1894 | 1841 | 
| 1895 | 1842 | 
| 1896 void FullCodeGenerator::EmitBinaryOp(Token::Value op, | 1843 void FullCodeGenerator::EmitBinaryOp(Token::Value op, | 
| 1897                                      OverwriteMode mode) { | 1844                                      OverwriteMode mode) { | 
| 1898   __ pop(edx); | 1845   __ pop(edx); | 
| 1899   TypeRecordingBinaryOpStub stub(op, mode); | 1846   TypeRecordingBinaryOpStub stub(op, mode); | 
| 1900   EmitCallIC(stub.GetCode(), NULL);  // NULL signals no inlined smi code. | 1847   __ CallStub(&stub); | 
| 1901   context()->Plug(eax); | 1848   context()->Plug(eax); | 
| 1902 } | 1849 } | 
| 1903 | 1850 | 
| 1904 | 1851 | 
| 1905 void FullCodeGenerator::EmitAssignment(Expression* expr) { | 1852 void FullCodeGenerator::EmitAssignment(Expression* expr) { | 
| 1906   // Invalid left-hand sides are rewritten to have a 'throw | 1853   // Invalid left-hand sides are rewritten to have a 'throw | 
| 1907   // ReferenceError' on the left-hand side. | 1854   // ReferenceError' on the left-hand side. | 
| 1908   if (!expr->IsValidLeftHandSide()) { | 1855   if (!expr->IsValidLeftHandSide()) { | 
| 1909     VisitForEffect(expr); | 1856     VisitForEffect(expr); | 
| 1910     return; | 1857     return; | 
| (...skipping 1844 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 3755           break; | 3702           break; | 
| 3756         case KEYED_PROPERTY: | 3703         case KEYED_PROPERTY: | 
| 3757           __ mov(Operand(esp, 2 * kPointerSize), eax); | 3704           __ mov(Operand(esp, 2 * kPointerSize), eax); | 
| 3758           break; | 3705           break; | 
| 3759       } | 3706       } | 
| 3760     } | 3707     } | 
| 3761   } | 3708   } | 
| 3762 | 3709 | 
| 3763   // Inline smi case if we are in a loop. | 3710   // Inline smi case if we are in a loop. | 
| 3764   NearLabel stub_call; | 3711   NearLabel stub_call; | 
| 3765   JumpPatchSite patch_site(masm_); |  | 
| 3766   Label done; | 3712   Label done; | 
| 3767   if (ShouldInlineSmiCase(expr->op())) { | 3713   if (ShouldInlineSmiCase(expr->op())) { | 
| 3768     if (expr->op() == Token::INC) { | 3714     if (expr->op() == Token::INC) { | 
| 3769       __ add(Operand(eax), Immediate(Smi::FromInt(1))); | 3715       __ add(Operand(eax), Immediate(Smi::FromInt(1))); | 
| 3770     } else { | 3716     } else { | 
| 3771       __ sub(Operand(eax), Immediate(Smi::FromInt(1))); | 3717       __ sub(Operand(eax), Immediate(Smi::FromInt(1))); | 
| 3772     } | 3718     } | 
| 3773     __ j(overflow, &stub_call); | 3719     __ j(overflow, &stub_call); | 
| 3774     // We could eliminate this smi check if we split the code at | 3720     // We could eliminate this smi check if we split the code at | 
| 3775     // the first smi check before calling ToNumber. | 3721     // the first smi check before calling ToNumber. | 
| 3776     __ test(eax, Immediate(kSmiTagMask)); | 3722     __ test(eax, Immediate(kSmiTagMask)); | 
| 3777     patch_site.EmitJump(&stub_call); | 3723     __ j(zero, &done); | 
| 3778     __ jmp(&done); |  | 
| 3779 |  | 
| 3780     __ bind(&stub_call); | 3724     __ bind(&stub_call); | 
| 3781     // Call stub. Undo operation first. | 3725     // Call stub. Undo operation first. | 
| 3782     if (expr->op() == Token::INC) { | 3726     if (expr->op() == Token::INC) { | 
| 3783       __ sub(Operand(eax), Immediate(Smi::FromInt(1))); | 3727       __ sub(Operand(eax), Immediate(Smi::FromInt(1))); | 
| 3784     } else { | 3728     } else { | 
| 3785       __ add(Operand(eax), Immediate(Smi::FromInt(1))); | 3729       __ add(Operand(eax), Immediate(Smi::FromInt(1))); | 
| 3786     } | 3730     } | 
| 3787   } | 3731   } | 
| 3788 | 3732 | 
| 3789   // Record position before stub call. | 3733   // Record position before stub call. | 
| 3790   SetSourcePosition(expr->position()); | 3734   SetSourcePosition(expr->position()); | 
| 3791 | 3735 | 
| 3792   // Call stub for +1/-1. | 3736   // Call stub for +1/-1. | 
| 3793   __ mov(edx, eax); | 3737   __ mov(edx, eax); | 
| 3794   __ mov(eax, Immediate(Smi::FromInt(1))); | 3738   __ mov(eax, Immediate(Smi::FromInt(1))); | 
| 3795   TypeRecordingBinaryOpStub stub(expr->binary_op(), | 3739   TypeRecordingBinaryOpStub stub(expr->binary_op(), | 
| 3796                                  NO_OVERWRITE); | 3740                                  NO_OVERWRITE); | 
| 3797   EmitCallIC(stub.GetCode(), &patch_site); | 3741   __ CallStub(&stub); | 
|  | 3742   __ bind(&done); | 
| 3798 | 3743 | 
| 3799   __ bind(&done); |  | 
| 3800   // Store the value returned in eax. | 3744   // Store the value returned in eax. | 
| 3801   switch (assign_type) { | 3745   switch (assign_type) { | 
| 3802     case VARIABLE: | 3746     case VARIABLE: | 
| 3803       if (expr->is_postfix()) { | 3747       if (expr->is_postfix()) { | 
| 3804         // Perform the assignment as if via '='. | 3748         // Perform the assignment as if via '='. | 
| 3805         { EffectContext context(this); | 3749         { EffectContext context(this); | 
| 3806           EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 3750           EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(), | 
| 3807                                  Token::ASSIGN); | 3751                                  Token::ASSIGN); | 
| 3808         } | 3752         } | 
| 3809         // For all contexts except EffectContext We have the result on | 3753         // For all contexts except EffectContext We have the result on | 
| (...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 4054           cc = greater_equal; | 3998           cc = greater_equal; | 
| 4055           __ pop(edx); | 3999           __ pop(edx); | 
| 4056           break; | 4000           break; | 
| 4057         case Token::IN: | 4001         case Token::IN: | 
| 4058         case Token::INSTANCEOF: | 4002         case Token::INSTANCEOF: | 
| 4059         default: | 4003         default: | 
| 4060           UNREACHABLE(); | 4004           UNREACHABLE(); | 
| 4061       } | 4005       } | 
| 4062 | 4006 | 
| 4063       bool inline_smi_code = ShouldInlineSmiCase(op); | 4007       bool inline_smi_code = ShouldInlineSmiCase(op); | 
| 4064       JumpPatchSite patch_site(masm_); |  | 
| 4065       if (inline_smi_code) { | 4008       if (inline_smi_code) { | 
| 4066         NearLabel slow_case; | 4009         NearLabel slow_case; | 
| 4067         __ mov(ecx, Operand(edx)); | 4010         __ mov(ecx, Operand(edx)); | 
| 4068         __ or_(ecx, Operand(eax)); | 4011         __ or_(ecx, Operand(eax)); | 
| 4069         __ test(ecx, Immediate(kSmiTagMask)); | 4012         __ test(ecx, Immediate(kSmiTagMask)); | 
| 4070         patch_site.EmitJump(&slow_case); | 4013         __ j(not_zero, &slow_case, not_taken); | 
| 4071         __ cmp(edx, Operand(eax)); | 4014         __ cmp(edx, Operand(eax)); | 
| 4072         Split(cc, if_true, if_false, NULL); | 4015         Split(cc, if_true, if_false, NULL); | 
| 4073         __ bind(&slow_case); | 4016         __ bind(&slow_case); | 
| 4074       } | 4017       } | 
| 4075 | 4018 | 
| 4076       // Record position and call the compare IC. | 4019       // Record position and call the compare IC. | 
|  | 4020       Handle<Code> ic = CompareIC::GetUninitialized(op); | 
| 4077       SetSourcePosition(expr->position()); | 4021       SetSourcePosition(expr->position()); | 
| 4078       Handle<Code> ic = CompareIC::GetUninitialized(op); | 4022       __ call(ic, RelocInfo::CODE_TARGET); | 
| 4079       EmitCallIC(ic, &patch_site); |  | 
| 4080 |  | 
| 4081       PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); | 4023       PrepareForBailoutBeforeSplit(TOS_REG, true, if_true, if_false); | 
| 4082       __ test(eax, Operand(eax)); | 4024       __ test(eax, Operand(eax)); | 
| 4083       Split(cc, if_true, if_false, fall_through); | 4025       Split(cc, if_true, if_false, fall_through); | 
| 4084     } | 4026     } | 
| 4085   } | 4027   } | 
| 4086 | 4028 | 
| 4087   // Convert the result of the comparison into one expected for this | 4029   // Convert the result of the comparison into one expected for this | 
| 4088   // expression's context. | 4030   // expression's context. | 
| 4089   context()->Plug(if_true, if_false); | 4031   context()->Plug(if_true, if_false); | 
| 4090 } | 4032 } | 
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 4174     case Code::KEYED_STORE_IC: | 4116     case Code::KEYED_STORE_IC: | 
| 4175       __ nop();  // Signals no inlined code. | 4117       __ nop();  // Signals no inlined code. | 
| 4176       break; | 4118       break; | 
| 4177     default: | 4119     default: | 
| 4178       // Do nothing. | 4120       // Do nothing. | 
| 4179       break; | 4121       break; | 
| 4180   } | 4122   } | 
| 4181 } | 4123 } | 
| 4182 | 4124 | 
| 4183 | 4125 | 
| 4184 void FullCodeGenerator::EmitCallIC(Handle<Code> ic, JumpPatchSite* patch_site) { |  | 
| 4185   __ call(ic, RelocInfo::CODE_TARGET); |  | 
| 4186   if (patch_site != NULL && patch_site->is_bound()) { |  | 
| 4187     patch_site->EmitPatchInfo(); |  | 
| 4188   } else { |  | 
| 4189     __ nop();  // Signals no inlined code. |  | 
| 4190   } |  | 
| 4191 } |  | 
| 4192 |  | 
| 4193 |  | 
| 4194 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { | 4126 void FullCodeGenerator::StoreToFrameField(int frame_offset, Register value) { | 
| 4195   ASSERT_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset); | 4127   ASSERT_EQ(POINTER_SIZE_ALIGN(frame_offset), frame_offset); | 
| 4196   __ mov(Operand(ebp, frame_offset), value); | 4128   __ mov(Operand(ebp, frame_offset), value); | 
| 4197 } | 4129 } | 
| 4198 | 4130 | 
| 4199 | 4131 | 
| 4200 void FullCodeGenerator::LoadContextField(Register dst, int context_index) { | 4132 void FullCodeGenerator::LoadContextField(Register dst, int context_index) { | 
| 4201   __ mov(dst, ContextOperand(esi, context_index)); | 4133   __ mov(dst, ContextOperand(esi, context_index)); | 
| 4202 } | 4134 } | 
| 4203 | 4135 | 
| (...skipping 27 matching lines...) Expand all  Loading... | 
| 4231   // And return. | 4163   // And return. | 
| 4232   __ ret(0); | 4164   __ ret(0); | 
| 4233 } | 4165 } | 
| 4234 | 4166 | 
| 4235 | 4167 | 
| 4236 #undef __ | 4168 #undef __ | 
| 4237 | 4169 | 
| 4238 } }  // namespace v8::internal | 4170 } }  // namespace v8::internal | 
| 4239 | 4171 | 
| 4240 #endif  // V8_TARGET_ARCH_IA32 | 4172 #endif  // V8_TARGET_ARCH_IA32 | 
| OLD | NEW | 
|---|