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 |