| OLD | NEW |
| 1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 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 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 262 break; | 262 break; |
| 263 case kStack: | 263 case kStack: |
| 264 __ push(reg); | 264 __ push(reg); |
| 265 break; | 265 break; |
| 266 } | 266 } |
| 267 break; | 267 break; |
| 268 | 268 |
| 269 case Expression::kTest: | 269 case Expression::kTest: |
| 270 // For simplicity we always test the accumulator register. | 270 // For simplicity we always test the accumulator register. |
| 271 if (!reg.is(result_register())) __ mov(result_register(), reg); | 271 if (!reg.is(result_register())) __ mov(result_register(), reg); |
| 272 DoTest(true_label_, false_label_, NULL); | 272 DoTest(true_label_, false_label_, fall_through_); |
| 273 break; | 273 break; |
| 274 } | 274 } |
| 275 } | 275 } |
| 276 | 276 |
| 277 | 277 |
| 278 void FullCodeGenerator::Apply(Expression::Context context, Slot* slot) { | 278 void FullCodeGenerator::Apply(Expression::Context context, Slot* slot) { |
| 279 switch (context) { | 279 switch (context) { |
| 280 case Expression::kUninitialized: | 280 case Expression::kUninitialized: |
| 281 UNREACHABLE(); | 281 UNREACHABLE(); |
| 282 case Expression::kEffect: | 282 case Expression::kEffect: |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 325 case kAccumulator: | 325 case kAccumulator: |
| 326 __ pop(result_register()); | 326 __ pop(result_register()); |
| 327 break; | 327 break; |
| 328 case kStack: | 328 case kStack: |
| 329 break; | 329 break; |
| 330 } | 330 } |
| 331 break; | 331 break; |
| 332 | 332 |
| 333 case Expression::kTest: | 333 case Expression::kTest: |
| 334 __ pop(result_register()); | 334 __ pop(result_register()); |
| 335 DoTest(true_label_, false_label_, NULL); | 335 DoTest(true_label_, false_label_, fall_through_); |
| 336 break; | 336 break; |
| 337 } | 337 } |
| 338 } | 338 } |
| 339 | 339 |
| 340 | 340 |
| 341 void FullCodeGenerator::DropAndApply(int count, | 341 void FullCodeGenerator::DropAndApply(int count, |
| 342 Expression::Context context, | 342 Expression::Context context, |
| 343 Register reg) { | 343 Register reg) { |
| 344 ASSERT(count > 0); | 344 ASSERT(count > 0); |
| 345 ASSERT(!reg.is(sp)); | 345 ASSERT(!reg.is(sp)); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 360 case kStack: | 360 case kStack: |
| 361 if (count > 1) __ Drop(count - 1); | 361 if (count > 1) __ Drop(count - 1); |
| 362 __ str(reg, MemOperand(sp)); | 362 __ str(reg, MemOperand(sp)); |
| 363 break; | 363 break; |
| 364 } | 364 } |
| 365 break; | 365 break; |
| 366 | 366 |
| 367 case Expression::kTest: | 367 case Expression::kTest: |
| 368 __ Drop(count); | 368 __ Drop(count); |
| 369 if (!reg.is(result_register())) __ mov(result_register(), reg); | 369 if (!reg.is(result_register())) __ mov(result_register(), reg); |
| 370 DoTest(true_label_, false_label_, NULL); | 370 DoTest(true_label_, false_label_, fall_through_); |
| 371 break; | |
| 372 } | |
| 373 } | |
| 374 | |
| 375 void FullCodeGenerator::PrepareTest(Label* materialize_true, | |
| 376 Label* materialize_false, | |
| 377 Label** if_true, | |
| 378 Label** if_false) { | |
| 379 switch (context_) { | |
| 380 case Expression::kUninitialized: | |
| 381 UNREACHABLE(); | |
| 382 break; | |
| 383 case Expression::kEffect: | |
| 384 // In an effect context, the true and the false case branch to the | |
| 385 // same label. | |
| 386 *if_true = *if_false = materialize_true; | |
| 387 break; | |
| 388 case Expression::kValue: | |
| 389 *if_true = materialize_true; | |
| 390 *if_false = materialize_false; | |
| 391 break; | |
| 392 case Expression::kTest: | |
| 393 *if_true = true_label_; | |
| 394 *if_false = false_label_; | |
| 395 break; | 371 break; |
| 396 } | 372 } |
| 397 } | 373 } |
| 398 | 374 |
| 399 | 375 |
| 400 void FullCodeGenerator::Apply(Expression::Context context, | 376 void FullCodeGenerator::Apply(Expression::Context context, |
| 401 Label* materialize_true, | 377 Label* materialize_true, |
| 402 Label* materialize_false) { | 378 Label* materialize_false) { |
| 403 switch (context) { | 379 switch (context) { |
| 404 case Expression::kUninitialized: | 380 case Expression::kUninitialized: |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 455 __ LoadRoot(result_register(), value_root_index); | 431 __ LoadRoot(result_register(), value_root_index); |
| 456 break; | 432 break; |
| 457 case kStack: | 433 case kStack: |
| 458 __ LoadRoot(ip, value_root_index); | 434 __ LoadRoot(ip, value_root_index); |
| 459 __ push(ip); | 435 __ push(ip); |
| 460 break; | 436 break; |
| 461 } | 437 } |
| 462 break; | 438 break; |
| 463 } | 439 } |
| 464 case Expression::kTest: | 440 case Expression::kTest: |
| 465 __ b(flag ? true_label_ : false_label_); | 441 if (flag) { |
| 442 if (true_label_ != fall_through_) __ b(true_label_); |
| 443 } else { |
| 444 if (false_label_ != fall_through_) __ b(false_label_); |
| 445 } |
| 466 break; | 446 break; |
| 467 } | 447 } |
| 468 } | 448 } |
| 469 | 449 |
| 470 | 450 |
| 471 void FullCodeGenerator::DoTest(Label* if_true, | 451 void FullCodeGenerator::DoTest(Label* if_true, |
| 472 Label* if_false, | 452 Label* if_false, |
| 473 Label* fall_through) { | 453 Label* fall_through) { |
| 474 // Call the runtime to find the boolean value of the source and then | 454 // Call the runtime to find the boolean value of the source and then |
| 475 // translate it into control flow to the pair of labels. | 455 // translate it into control flow to the pair of labels. |
| (...skipping 1252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1728 | 1708 |
| 1729 | 1709 |
| 1730 void FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) { | 1710 void FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) { |
| 1731 ASSERT(args->length() == 1); | 1711 ASSERT(args->length() == 1); |
| 1732 | 1712 |
| 1733 VisitForValue(args->at(0), kAccumulator); | 1713 VisitForValue(args->at(0), kAccumulator); |
| 1734 | 1714 |
| 1735 Label materialize_true, materialize_false; | 1715 Label materialize_true, materialize_false; |
| 1736 Label* if_true = NULL; | 1716 Label* if_true = NULL; |
| 1737 Label* if_false = NULL; | 1717 Label* if_false = NULL; |
| 1738 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1718 Label* fall_through = NULL; |
| 1719 PrepareTest(&materialize_true, &materialize_false, |
| 1720 &if_true, &if_false, &fall_through); |
| 1739 | 1721 |
| 1740 __ BranchOnSmi(r0, if_true); | 1722 __ BranchOnSmi(r0, if_true); |
| 1741 __ b(if_false); | 1723 __ b(if_false); |
| 1742 | 1724 |
| 1743 Apply(context_, if_true, if_false); | 1725 Apply(context_, if_true, if_false); |
| 1744 } | 1726 } |
| 1745 | 1727 |
| 1746 | 1728 |
| 1747 void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) { | 1729 void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) { |
| 1748 ASSERT(args->length() == 1); | 1730 ASSERT(args->length() == 1); |
| 1749 | 1731 |
| 1750 VisitForValue(args->at(0), kAccumulator); | 1732 VisitForValue(args->at(0), kAccumulator); |
| 1751 | 1733 |
| 1752 Label materialize_true, materialize_false; | 1734 Label materialize_true, materialize_false; |
| 1753 Label* if_true = NULL; | 1735 Label* if_true = NULL; |
| 1754 Label* if_false = NULL; | 1736 Label* if_false = NULL; |
| 1755 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1737 Label* fall_through = NULL; |
| 1738 PrepareTest(&materialize_true, &materialize_false, |
| 1739 &if_true, &if_false, &fall_through); |
| 1756 | 1740 |
| 1757 __ tst(r0, Operand(kSmiTagMask | 0x80000000)); | 1741 __ tst(r0, Operand(kSmiTagMask | 0x80000000)); |
| 1758 Split(eq, if_true, if_false, NULL); | 1742 Split(eq, if_true, if_false, fall_through); |
| 1759 | 1743 |
| 1760 Apply(context_, if_true, if_false); | 1744 Apply(context_, if_true, if_false); |
| 1761 } | 1745 } |
| 1762 | 1746 |
| 1763 | 1747 |
| 1764 void FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) { | 1748 void FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) { |
| 1765 ASSERT(args->length() == 1); | 1749 ASSERT(args->length() == 1); |
| 1766 | 1750 |
| 1767 VisitForValue(args->at(0), kAccumulator); | 1751 VisitForValue(args->at(0), kAccumulator); |
| 1768 | 1752 |
| 1769 Label materialize_true, materialize_false; | 1753 Label materialize_true, materialize_false; |
| 1770 Label* if_true = NULL; | 1754 Label* if_true = NULL; |
| 1771 Label* if_false = NULL; | 1755 Label* if_false = NULL; |
| 1772 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1756 Label* fall_through = NULL; |
| 1757 PrepareTest(&materialize_true, &materialize_false, |
| 1758 &if_true, &if_false, &fall_through); |
| 1759 |
| 1773 __ BranchOnSmi(r0, if_false); | 1760 __ BranchOnSmi(r0, if_false); |
| 1774 __ LoadRoot(ip, Heap::kNullValueRootIndex); | 1761 __ LoadRoot(ip, Heap::kNullValueRootIndex); |
| 1775 __ cmp(r0, ip); | 1762 __ cmp(r0, ip); |
| 1776 __ b(eq, if_true); | 1763 __ b(eq, if_true); |
| 1777 __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset)); | 1764 __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset)); |
| 1778 // Undetectable objects behave like undefined when tested with typeof. | 1765 // Undetectable objects behave like undefined when tested with typeof. |
| 1779 __ ldrb(r1, FieldMemOperand(r2, Map::kBitFieldOffset)); | 1766 __ ldrb(r1, FieldMemOperand(r2, Map::kBitFieldOffset)); |
| 1780 __ tst(r1, Operand(1 << Map::kIsUndetectable)); | 1767 __ tst(r1, Operand(1 << Map::kIsUndetectable)); |
| 1781 __ b(ne, if_false); | 1768 __ b(ne, if_false); |
| 1782 __ ldrb(r1, FieldMemOperand(r2, Map::kInstanceTypeOffset)); | 1769 __ ldrb(r1, FieldMemOperand(r2, Map::kInstanceTypeOffset)); |
| 1783 __ cmp(r1, Operand(FIRST_JS_OBJECT_TYPE)); | 1770 __ cmp(r1, Operand(FIRST_JS_OBJECT_TYPE)); |
| 1784 __ b(lt, if_false); | 1771 __ b(lt, if_false); |
| 1785 __ cmp(r1, Operand(LAST_JS_OBJECT_TYPE)); | 1772 __ cmp(r1, Operand(LAST_JS_OBJECT_TYPE)); |
| 1786 Split(le, if_true, if_false, NULL); | 1773 Split(le, if_true, if_false, fall_through); |
| 1787 | 1774 |
| 1788 Apply(context_, if_true, if_false); | 1775 Apply(context_, if_true, if_false); |
| 1789 } | 1776 } |
| 1790 | 1777 |
| 1791 | 1778 |
| 1792 void FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) { | 1779 void FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) { |
| 1793 ASSERT(args->length() == 1); | 1780 ASSERT(args->length() == 1); |
| 1794 | 1781 |
| 1795 VisitForValue(args->at(0), kAccumulator); | 1782 VisitForValue(args->at(0), kAccumulator); |
| 1796 | 1783 |
| 1797 Label materialize_true, materialize_false; | 1784 Label materialize_true, materialize_false; |
| 1798 Label* if_true = NULL; | 1785 Label* if_true = NULL; |
| 1799 Label* if_false = NULL; | 1786 Label* if_false = NULL; |
| 1800 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1787 Label* fall_through = NULL; |
| 1788 PrepareTest(&materialize_true, &materialize_false, |
| 1789 &if_true, &if_false, &fall_through); |
| 1801 | 1790 |
| 1802 __ BranchOnSmi(r0, if_false); | 1791 __ BranchOnSmi(r0, if_false); |
| 1803 __ CompareObjectType(r0, r1, r1, FIRST_JS_OBJECT_TYPE); | 1792 __ CompareObjectType(r0, r1, r1, FIRST_JS_OBJECT_TYPE); |
| 1804 Split(ge, if_true, if_false, NULL); | 1793 Split(ge, if_true, if_false, fall_through); |
| 1805 | 1794 |
| 1806 Apply(context_, if_true, if_false); | 1795 Apply(context_, if_true, if_false); |
| 1807 } | 1796 } |
| 1808 | 1797 |
| 1809 | 1798 |
| 1810 void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) { | 1799 void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) { |
| 1811 ASSERT(args->length() == 1); | 1800 ASSERT(args->length() == 1); |
| 1812 | 1801 |
| 1813 VisitForValue(args->at(0), kAccumulator); | 1802 VisitForValue(args->at(0), kAccumulator); |
| 1814 | 1803 |
| 1815 Label materialize_true, materialize_false; | 1804 Label materialize_true, materialize_false; |
| 1816 Label* if_true = NULL; | 1805 Label* if_true = NULL; |
| 1817 Label* if_false = NULL; | 1806 Label* if_false = NULL; |
| 1818 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1807 Label* fall_through = NULL; |
| 1808 PrepareTest(&materialize_true, &materialize_false, |
| 1809 &if_true, &if_false, &fall_through); |
| 1819 | 1810 |
| 1820 __ BranchOnSmi(r0, if_false); | 1811 __ BranchOnSmi(r0, if_false); |
| 1821 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); | 1812 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); |
| 1822 __ ldrb(r1, FieldMemOperand(r1, Map::kBitFieldOffset)); | 1813 __ ldrb(r1, FieldMemOperand(r1, Map::kBitFieldOffset)); |
| 1823 __ tst(r1, Operand(1 << Map::kIsUndetectable)); | 1814 __ tst(r1, Operand(1 << Map::kIsUndetectable)); |
| 1824 Split(ne, if_true, if_false, NULL); | 1815 Split(ne, if_true, if_false, fall_through); |
| 1825 | 1816 |
| 1826 Apply(context_, if_true, if_false); | 1817 Apply(context_, if_true, if_false); |
| 1827 } | 1818 } |
| 1828 | 1819 |
| 1829 | 1820 |
| 1830 void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( | 1821 void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( |
| 1831 ZoneList<Expression*>* args) { | 1822 ZoneList<Expression*>* args) { |
| 1832 | 1823 |
| 1833 ASSERT(args->length() == 1); | 1824 ASSERT(args->length() == 1); |
| 1834 | 1825 |
| 1835 VisitForValue(args->at(0), kAccumulator); | 1826 VisitForValue(args->at(0), kAccumulator); |
| 1836 | 1827 |
| 1837 Label materialize_true, materialize_false; | 1828 Label materialize_true, materialize_false; |
| 1838 Label* if_true = NULL; | 1829 Label* if_true = NULL; |
| 1839 Label* if_false = NULL; | 1830 Label* if_false = NULL; |
| 1840 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1831 Label* fall_through = NULL; |
| 1832 PrepareTest(&materialize_true, &materialize_false, |
| 1833 &if_true, &if_false, &fall_through); |
| 1841 | 1834 |
| 1842 // Just indicate false, as %_IsStringWrapperSafeForDefaultValueOf() is only | 1835 // Just indicate false, as %_IsStringWrapperSafeForDefaultValueOf() is only |
| 1843 // used in a few functions in runtime.js which should not normally be hit by | 1836 // used in a few functions in runtime.js which should not normally be hit by |
| 1844 // this compiler. | 1837 // this compiler. |
| 1845 __ jmp(if_false); | 1838 __ jmp(if_false); |
| 1846 Apply(context_, if_true, if_false); | 1839 Apply(context_, if_true, if_false); |
| 1847 } | 1840 } |
| 1848 | 1841 |
| 1849 | 1842 |
| 1850 void FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) { | 1843 void FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) { |
| 1851 ASSERT(args->length() == 1); | 1844 ASSERT(args->length() == 1); |
| 1852 | 1845 |
| 1853 VisitForValue(args->at(0), kAccumulator); | 1846 VisitForValue(args->at(0), kAccumulator); |
| 1854 | 1847 |
| 1855 Label materialize_true, materialize_false; | 1848 Label materialize_true, materialize_false; |
| 1856 Label* if_true = NULL; | 1849 Label* if_true = NULL; |
| 1857 Label* if_false = NULL; | 1850 Label* if_false = NULL; |
| 1858 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1851 Label* fall_through = NULL; |
| 1852 PrepareTest(&materialize_true, &materialize_false, |
| 1853 &if_true, &if_false, &fall_through); |
| 1859 | 1854 |
| 1860 __ BranchOnSmi(r0, if_false); | 1855 __ BranchOnSmi(r0, if_false); |
| 1861 __ CompareObjectType(r0, r1, r1, JS_FUNCTION_TYPE); | 1856 __ CompareObjectType(r0, r1, r1, JS_FUNCTION_TYPE); |
| 1862 Split(eq, if_true, if_false, NULL); | 1857 Split(eq, if_true, if_false, fall_through); |
| 1863 | 1858 |
| 1864 Apply(context_, if_true, if_false); | 1859 Apply(context_, if_true, if_false); |
| 1865 } | 1860 } |
| 1866 | 1861 |
| 1867 | 1862 |
| 1868 void FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) { | 1863 void FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) { |
| 1869 ASSERT(args->length() == 1); | 1864 ASSERT(args->length() == 1); |
| 1870 | 1865 |
| 1871 VisitForValue(args->at(0), kAccumulator); | 1866 VisitForValue(args->at(0), kAccumulator); |
| 1872 | 1867 |
| 1873 Label materialize_true, materialize_false; | 1868 Label materialize_true, materialize_false; |
| 1874 Label* if_true = NULL; | 1869 Label* if_true = NULL; |
| 1875 Label* if_false = NULL; | 1870 Label* if_false = NULL; |
| 1876 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1871 Label* fall_through = NULL; |
| 1872 PrepareTest(&materialize_true, &materialize_false, |
| 1873 &if_true, &if_false, &fall_through); |
| 1877 | 1874 |
| 1878 __ BranchOnSmi(r0, if_false); | 1875 __ BranchOnSmi(r0, if_false); |
| 1879 __ CompareObjectType(r0, r1, r1, JS_ARRAY_TYPE); | 1876 __ CompareObjectType(r0, r1, r1, JS_ARRAY_TYPE); |
| 1880 Split(eq, if_true, if_false, NULL); | 1877 Split(eq, if_true, if_false, fall_through); |
| 1881 | 1878 |
| 1882 Apply(context_, if_true, if_false); | 1879 Apply(context_, if_true, if_false); |
| 1883 } | 1880 } |
| 1884 | 1881 |
| 1885 | 1882 |
| 1886 void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) { | 1883 void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) { |
| 1887 ASSERT(args->length() == 1); | 1884 ASSERT(args->length() == 1); |
| 1888 | 1885 |
| 1889 VisitForValue(args->at(0), kAccumulator); | 1886 VisitForValue(args->at(0), kAccumulator); |
| 1890 | 1887 |
| 1891 Label materialize_true, materialize_false; | 1888 Label materialize_true, materialize_false; |
| 1892 Label* if_true = NULL; | 1889 Label* if_true = NULL; |
| 1893 Label* if_false = NULL; | 1890 Label* if_false = NULL; |
| 1894 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1891 Label* fall_through = NULL; |
| 1892 PrepareTest(&materialize_true, &materialize_false, |
| 1893 &if_true, &if_false, &fall_through); |
| 1895 | 1894 |
| 1896 __ BranchOnSmi(r0, if_false); | 1895 __ BranchOnSmi(r0, if_false); |
| 1897 __ CompareObjectType(r0, r1, r1, JS_REGEXP_TYPE); | 1896 __ CompareObjectType(r0, r1, r1, JS_REGEXP_TYPE); |
| 1898 Split(eq, if_true, if_false, NULL); | 1897 Split(eq, if_true, if_false, fall_through); |
| 1899 | 1898 |
| 1900 Apply(context_, if_true, if_false); | 1899 Apply(context_, if_true, if_false); |
| 1901 } | 1900 } |
| 1902 | 1901 |
| 1903 | 1902 |
| 1904 | 1903 |
| 1905 void FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) { | 1904 void FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) { |
| 1906 ASSERT(args->length() == 0); | 1905 ASSERT(args->length() == 0); |
| 1907 | 1906 |
| 1908 Label materialize_true, materialize_false; | 1907 Label materialize_true, materialize_false; |
| 1909 Label* if_true = NULL; | 1908 Label* if_true = NULL; |
| 1910 Label* if_false = NULL; | 1909 Label* if_false = NULL; |
| 1911 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1910 Label* fall_through = NULL; |
| 1911 PrepareTest(&materialize_true, &materialize_false, |
| 1912 &if_true, &if_false, &fall_through); |
| 1912 | 1913 |
| 1913 // Get the frame pointer for the calling frame. | 1914 // Get the frame pointer for the calling frame. |
| 1914 __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); | 1915 __ ldr(r2, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
| 1915 | 1916 |
| 1916 // Skip the arguments adaptor frame if it exists. | 1917 // Skip the arguments adaptor frame if it exists. |
| 1917 Label check_frame_marker; | 1918 Label check_frame_marker; |
| 1918 __ ldr(r1, MemOperand(r2, StandardFrameConstants::kContextOffset)); | 1919 __ ldr(r1, MemOperand(r2, StandardFrameConstants::kContextOffset)); |
| 1919 __ cmp(r1, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | 1920 __ cmp(r1, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
| 1920 __ b(ne, &check_frame_marker); | 1921 __ b(ne, &check_frame_marker); |
| 1921 __ ldr(r2, MemOperand(r2, StandardFrameConstants::kCallerFPOffset)); | 1922 __ ldr(r2, MemOperand(r2, StandardFrameConstants::kCallerFPOffset)); |
| 1922 | 1923 |
| 1923 // Check the marker in the calling frame. | 1924 // Check the marker in the calling frame. |
| 1924 __ bind(&check_frame_marker); | 1925 __ bind(&check_frame_marker); |
| 1925 __ ldr(r1, MemOperand(r2, StandardFrameConstants::kMarkerOffset)); | 1926 __ ldr(r1, MemOperand(r2, StandardFrameConstants::kMarkerOffset)); |
| 1926 __ cmp(r1, Operand(Smi::FromInt(StackFrame::CONSTRUCT))); | 1927 __ cmp(r1, Operand(Smi::FromInt(StackFrame::CONSTRUCT))); |
| 1927 Split(eq, if_true, if_false, NULL); | 1928 Split(eq, if_true, if_false, fall_through); |
| 1928 | 1929 |
| 1929 Apply(context_, if_true, if_false); | 1930 Apply(context_, if_true, if_false); |
| 1930 } | 1931 } |
| 1931 | 1932 |
| 1932 | 1933 |
| 1933 void FullCodeGenerator::EmitObjectEquals(ZoneList<Expression*>* args) { | 1934 void FullCodeGenerator::EmitObjectEquals(ZoneList<Expression*>* args) { |
| 1934 ASSERT(args->length() == 2); | 1935 ASSERT(args->length() == 2); |
| 1935 | 1936 |
| 1936 // Load the two objects into registers and perform the comparison. | 1937 // Load the two objects into registers and perform the comparison. |
| 1937 VisitForValue(args->at(0), kStack); | 1938 VisitForValue(args->at(0), kStack); |
| 1938 VisitForValue(args->at(1), kAccumulator); | 1939 VisitForValue(args->at(1), kAccumulator); |
| 1939 | 1940 |
| 1940 Label materialize_true, materialize_false; | 1941 Label materialize_true, materialize_false; |
| 1941 Label* if_true = NULL; | 1942 Label* if_true = NULL; |
| 1942 Label* if_false = NULL; | 1943 Label* if_false = NULL; |
| 1943 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1944 Label* fall_through = NULL; |
| 1945 PrepareTest(&materialize_true, &materialize_false, |
| 1946 &if_true, &if_false, &fall_through); |
| 1944 | 1947 |
| 1945 __ pop(r1); | 1948 __ pop(r1); |
| 1946 __ cmp(r0, r1); | 1949 __ cmp(r0, r1); |
| 1947 Split(eq, if_true, if_false, NULL); | 1950 Split(eq, if_true, if_false, fall_through); |
| 1948 | 1951 |
| 1949 Apply(context_, if_true, if_false); | 1952 Apply(context_, if_true, if_false); |
| 1950 } | 1953 } |
| 1951 | 1954 |
| 1952 | 1955 |
| 1953 void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) { | 1956 void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) { |
| 1954 ASSERT(args->length() == 1); | 1957 ASSERT(args->length() == 1); |
| 1955 | 1958 |
| 1956 // ArgumentsAccessStub expects the key in edx and the formal | 1959 // ArgumentsAccessStub expects the key in edx and the formal |
| 1957 // parameter count in eax. | 1960 // parameter count in eax. |
| (...skipping 652 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2610 break; | 2613 break; |
| 2611 } | 2614 } |
| 2612 break; | 2615 break; |
| 2613 } | 2616 } |
| 2614 | 2617 |
| 2615 case Token::NOT: { | 2618 case Token::NOT: { |
| 2616 Comment cmnt(masm_, "[ UnaryOperation (NOT)"); | 2619 Comment cmnt(masm_, "[ UnaryOperation (NOT)"); |
| 2617 Label materialize_true, materialize_false; | 2620 Label materialize_true, materialize_false; |
| 2618 Label* if_true = NULL; | 2621 Label* if_true = NULL; |
| 2619 Label* if_false = NULL; | 2622 Label* if_false = NULL; |
| 2623 Label* fall_through = NULL; |
| 2620 | 2624 |
| 2621 // Notice that the labels are swapped. | 2625 // Notice that the labels are swapped. |
| 2622 PrepareTest(&materialize_true, &materialize_false, &if_false, &if_true); | 2626 PrepareTest(&materialize_true, &materialize_false, |
| 2623 | 2627 &if_false, &if_true, &fall_through); |
| 2624 VisitForControl(expr->expression(), if_true, if_false); | 2628 VisitForControl(expr->expression(), if_true, if_false, fall_through); |
| 2625 | |
| 2626 Apply(context_, if_false, if_true); // Labels swapped. | 2629 Apply(context_, if_false, if_true); // Labels swapped. |
| 2627 break; | 2630 break; |
| 2628 } | 2631 } |
| 2629 | 2632 |
| 2630 case Token::TYPEOF: { | 2633 case Token::TYPEOF: { |
| 2631 Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)"); | 2634 Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)"); |
| 2632 VisitForTypeofValue(expr->expression(), kStack); | 2635 VisitForTypeofValue(expr->expression(), kStack); |
| 2633 __ CallRuntime(Runtime::kTypeof, 1); | 2636 __ CallRuntime(Runtime::kTypeof, 1); |
| 2634 Apply(context_, r0); | 2637 Apply(context_, r0); |
| 2635 break; | 2638 break; |
| (...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2972 void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { | 2975 void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { |
| 2973 Comment cmnt(masm_, "[ CompareOperation"); | 2976 Comment cmnt(masm_, "[ CompareOperation"); |
| 2974 SetSourcePosition(expr->position()); | 2977 SetSourcePosition(expr->position()); |
| 2975 | 2978 |
| 2976 // Always perform the comparison for its control flow. Pack the result | 2979 // Always perform the comparison for its control flow. Pack the result |
| 2977 // into the expression's context after the comparison is performed. | 2980 // into the expression's context after the comparison is performed. |
| 2978 | 2981 |
| 2979 Label materialize_true, materialize_false; | 2982 Label materialize_true, materialize_false; |
| 2980 Label* if_true = NULL; | 2983 Label* if_true = NULL; |
| 2981 Label* if_false = NULL; | 2984 Label* if_false = NULL; |
| 2982 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 2985 Label* fall_through = NULL; |
| 2986 PrepareTest(&materialize_true, &materialize_false, |
| 2987 &if_true, &if_false, &fall_through); |
| 2983 | 2988 |
| 2984 // First we try a fast inlined version of the compare when one of | 2989 // First we try a fast inlined version of the compare when one of |
| 2985 // the operands is a literal. | 2990 // the operands is a literal. |
| 2986 Token::Value op = expr->op(); | 2991 Token::Value op = expr->op(); |
| 2987 Expression* left = expr->left(); | 2992 Expression* left = expr->left(); |
| 2988 Expression* right = expr->right(); | 2993 Expression* right = expr->right(); |
| 2989 if (TryLiteralCompare(op, left, right, if_true, if_false, NULL)) { | 2994 if (TryLiteralCompare(op, left, right, if_true, if_false, fall_through)) { |
| 2990 Apply(context_, if_true, if_false); | 2995 Apply(context_, if_true, if_false); |
| 2991 return; | 2996 return; |
| 2992 } | 2997 } |
| 2993 | 2998 |
| 2994 VisitForValue(expr->left(), kStack); | 2999 VisitForValue(expr->left(), kStack); |
| 2995 switch (expr->op()) { | 3000 switch (expr->op()) { |
| 2996 case Token::IN: | 3001 case Token::IN: |
| 2997 VisitForValue(expr->right(), kStack); | 3002 VisitForValue(expr->right(), kStack); |
| 2998 __ InvokeBuiltin(Builtins::IN, CALL_JS); | 3003 __ InvokeBuiltin(Builtins::IN, CALL_JS); |
| 2999 __ LoadRoot(ip, Heap::kTrueValueRootIndex); | 3004 __ LoadRoot(ip, Heap::kTrueValueRootIndex); |
| 3000 __ cmp(r0, ip); | 3005 __ cmp(r0, ip); |
| 3001 Split(eq, if_true, if_false, NULL); | 3006 Split(eq, if_true, if_false, fall_through); |
| 3002 break; | 3007 break; |
| 3003 | 3008 |
| 3004 case Token::INSTANCEOF: { | 3009 case Token::INSTANCEOF: { |
| 3005 VisitForValue(expr->right(), kStack); | 3010 VisitForValue(expr->right(), kStack); |
| 3006 InstanceofStub stub; | 3011 InstanceofStub stub; |
| 3007 __ CallStub(&stub); | 3012 __ CallStub(&stub); |
| 3008 // The stub returns 0 for true. | 3013 // The stub returns 0 for true. |
| 3009 __ tst(r0, r0); | 3014 __ tst(r0, r0); |
| 3010 Split(eq, if_true, if_false, NULL); | 3015 Split(eq, if_true, if_false, fall_through); |
| 3011 break; | 3016 break; |
| 3012 } | 3017 } |
| 3013 | 3018 |
| 3014 default: { | 3019 default: { |
| 3015 VisitForValue(expr->right(), kAccumulator); | 3020 VisitForValue(expr->right(), kAccumulator); |
| 3016 Condition cc = eq; | 3021 Condition cc = eq; |
| 3017 bool strict = false; | 3022 bool strict = false; |
| 3018 switch (expr->op()) { | 3023 switch (expr->op()) { |
| 3019 case Token::EQ_STRICT: | 3024 case Token::EQ_STRICT: |
| 3020 strict = true; | 3025 strict = true; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3055 __ orr(r2, r0, Operand(r1)); | 3060 __ orr(r2, r0, Operand(r1)); |
| 3056 __ BranchOnNotSmi(r2, &slow_case); | 3061 __ BranchOnNotSmi(r2, &slow_case); |
| 3057 __ cmp(r1, r0); | 3062 __ cmp(r1, r0); |
| 3058 __ b(cc, if_true); | 3063 __ b(cc, if_true); |
| 3059 __ jmp(if_false); | 3064 __ jmp(if_false); |
| 3060 | 3065 |
| 3061 __ bind(&slow_case); | 3066 __ bind(&slow_case); |
| 3062 CompareStub stub(cc, strict, kBothCouldBeNaN, true, r1, r0); | 3067 CompareStub stub(cc, strict, kBothCouldBeNaN, true, r1, r0); |
| 3063 __ CallStub(&stub); | 3068 __ CallStub(&stub); |
| 3064 __ cmp(r0, Operand(0)); | 3069 __ cmp(r0, Operand(0)); |
| 3065 Split(cc, if_true, if_false, NULL); | 3070 Split(cc, if_true, if_false, fall_through); |
| 3066 } | 3071 } |
| 3067 } | 3072 } |
| 3068 | 3073 |
| 3069 // Convert the result of the comparison into one expected for this | 3074 // Convert the result of the comparison into one expected for this |
| 3070 // expression's context. | 3075 // expression's context. |
| 3071 Apply(context_, if_true, if_false); | 3076 Apply(context_, if_true, if_false); |
| 3072 } | 3077 } |
| 3073 | 3078 |
| 3074 | 3079 |
| 3075 void FullCodeGenerator::VisitCompareToNull(CompareToNull* expr) { | 3080 void FullCodeGenerator::VisitCompareToNull(CompareToNull* expr) { |
| 3076 Comment cmnt(masm_, "[ CompareToNull"); | 3081 Comment cmnt(masm_, "[ CompareToNull"); |
| 3077 Label materialize_true, materialize_false; | 3082 Label materialize_true, materialize_false; |
| 3078 Label* if_true = NULL; | 3083 Label* if_true = NULL; |
| 3079 Label* if_false = NULL; | 3084 Label* if_false = NULL; |
| 3080 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 3085 Label* fall_through = NULL; |
| 3086 PrepareTest(&materialize_true, &materialize_false, |
| 3087 &if_true, &if_false, &fall_through); |
| 3081 | 3088 |
| 3082 VisitForValue(expr->expression(), kAccumulator); | 3089 VisitForValue(expr->expression(), kAccumulator); |
| 3083 __ LoadRoot(r1, Heap::kNullValueRootIndex); | 3090 __ LoadRoot(r1, Heap::kNullValueRootIndex); |
| 3084 __ cmp(r0, r1); | 3091 __ cmp(r0, r1); |
| 3085 if (expr->is_strict()) { | 3092 if (expr->is_strict()) { |
| 3086 Split(eq, if_true, if_false, NULL); | 3093 Split(eq, if_true, if_false, fall_through); |
| 3087 } else { | 3094 } else { |
| 3088 __ b(eq, if_true); | 3095 __ b(eq, if_true); |
| 3089 __ LoadRoot(r1, Heap::kUndefinedValueRootIndex); | 3096 __ LoadRoot(r1, Heap::kUndefinedValueRootIndex); |
| 3090 __ cmp(r0, r1); | 3097 __ cmp(r0, r1); |
| 3091 __ b(eq, if_true); | 3098 __ b(eq, if_true); |
| 3092 __ tst(r0, Operand(kSmiTagMask)); | 3099 __ tst(r0, Operand(kSmiTagMask)); |
| 3093 __ b(eq, if_false); | 3100 __ b(eq, if_false); |
| 3094 // It can be an undetectable object. | 3101 // It can be an undetectable object. |
| 3095 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); | 3102 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); |
| 3096 __ ldrb(r1, FieldMemOperand(r1, Map::kBitFieldOffset)); | 3103 __ ldrb(r1, FieldMemOperand(r1, Map::kBitFieldOffset)); |
| 3097 __ and_(r1, r1, Operand(1 << Map::kIsUndetectable)); | 3104 __ and_(r1, r1, Operand(1 << Map::kIsUndetectable)); |
| 3098 __ cmp(r1, Operand(1 << Map::kIsUndetectable)); | 3105 __ cmp(r1, Operand(1 << Map::kIsUndetectable)); |
| 3099 Split(eq, if_true, if_false, NULL); | 3106 Split(eq, if_true, if_false, fall_through); |
| 3100 } | 3107 } |
| 3101 Apply(context_, if_true, if_false); | 3108 Apply(context_, if_true, if_false); |
| 3102 } | 3109 } |
| 3103 | 3110 |
| 3104 | 3111 |
| 3105 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { | 3112 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { |
| 3106 __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 3113 __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
| 3107 Apply(context_, r0); | 3114 Apply(context_, r0); |
| 3108 } | 3115 } |
| 3109 | 3116 |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3151 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. | 3158 __ mov(r1, Operand(r1, ASR, 1)); // Un-smi-tag value. |
| 3152 __ add(pc, r1, Operand(masm_->CodeObject())); | 3159 __ add(pc, r1, Operand(masm_->CodeObject())); |
| 3153 } | 3160 } |
| 3154 | 3161 |
| 3155 | 3162 |
| 3156 #undef __ | 3163 #undef __ |
| 3157 | 3164 |
| 3158 } } // namespace v8::internal | 3165 } } // namespace v8::internal |
| 3159 | 3166 |
| 3160 #endif // V8_TARGET_ARCH_ARM | 3167 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |