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 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
246 break; | 246 break; |
247 case kStack: | 247 case kStack: |
248 __ push(reg); | 248 __ push(reg); |
249 break; | 249 break; |
250 } | 250 } |
251 break; | 251 break; |
252 | 252 |
253 case Expression::kTest: | 253 case Expression::kTest: |
254 // For simplicity we always test the accumulator register. | 254 // For simplicity we always test the accumulator register. |
255 if (!reg.is(result_register())) __ movq(result_register(), reg); | 255 if (!reg.is(result_register())) __ movq(result_register(), reg); |
256 DoTest(true_label_, false_label_, NULL); | 256 DoTest(true_label_, false_label_, fall_through_); |
257 break; | 257 break; |
258 } | 258 } |
259 } | 259 } |
260 | 260 |
261 | 261 |
262 void FullCodeGenerator::Apply(Expression::Context context, Slot* slot) { | 262 void FullCodeGenerator::Apply(Expression::Context context, Slot* slot) { |
263 switch (context) { | 263 switch (context) { |
264 case Expression::kUninitialized: | 264 case Expression::kUninitialized: |
265 UNREACHABLE(); | 265 UNREACHABLE(); |
266 case Expression::kEffect: | 266 case Expression::kEffect: |
267 // Nothing to do. | 267 // Nothing to do. |
268 break; | 268 break; |
269 case Expression::kValue: { | 269 case Expression::kValue: { |
270 MemOperand slot_operand = EmitSlotSearch(slot, result_register()); | 270 MemOperand slot_operand = EmitSlotSearch(slot, result_register()); |
271 switch (location_) { | 271 switch (location_) { |
272 case kAccumulator: | 272 case kAccumulator: |
273 __ movq(result_register(), slot_operand); | 273 __ movq(result_register(), slot_operand); |
274 break; | 274 break; |
275 case kStack: | 275 case kStack: |
276 // Memory operands can be pushed directly. | 276 // Memory operands can be pushed directly. |
277 __ push(slot_operand); | 277 __ push(slot_operand); |
278 break; | 278 break; |
279 } | 279 } |
280 break; | 280 break; |
281 } | 281 } |
282 | 282 |
283 case Expression::kTest: | 283 case Expression::kTest: |
284 Move(result_register(), slot); | 284 Move(result_register(), slot); |
285 DoTest(true_label_, false_label_, NULL); | 285 DoTest(true_label_, false_label_, fall_through_); |
286 break; | 286 break; |
287 } | 287 } |
288 } | 288 } |
289 | 289 |
290 | 290 |
291 void FullCodeGenerator::Apply(Expression::Context context, Literal* lit) { | 291 void FullCodeGenerator::Apply(Expression::Context context, Literal* lit) { |
292 switch (context) { | 292 switch (context) { |
293 case Expression::kUninitialized: | 293 case Expression::kUninitialized: |
294 UNREACHABLE(); | 294 UNREACHABLE(); |
295 case Expression::kEffect: | 295 case Expression::kEffect: |
296 // Nothing to do. | 296 // Nothing to do. |
297 break; | 297 break; |
298 case Expression::kValue: | 298 case Expression::kValue: |
299 switch (location_) { | 299 switch (location_) { |
300 case kAccumulator: | 300 case kAccumulator: |
301 __ Move(result_register(), lit->handle()); | 301 __ Move(result_register(), lit->handle()); |
302 break; | 302 break; |
303 case kStack: | 303 case kStack: |
304 __ Push(lit->handle()); | 304 __ Push(lit->handle()); |
305 break; | 305 break; |
306 } | 306 } |
307 break; | 307 break; |
308 | 308 |
309 case Expression::kTest: | 309 case Expression::kTest: |
310 __ Move(result_register(), lit->handle()); | 310 __ Move(result_register(), lit->handle()); |
311 DoTest(true_label_, false_label_, NULL); | 311 DoTest(true_label_, false_label_, fall_through_); |
312 break; | 312 break; |
313 } | 313 } |
314 } | 314 } |
315 | 315 |
316 | 316 |
317 void FullCodeGenerator::ApplyTOS(Expression::Context context) { | 317 void FullCodeGenerator::ApplyTOS(Expression::Context context) { |
318 switch (context) { | 318 switch (context) { |
319 case Expression::kUninitialized: | 319 case Expression::kUninitialized: |
320 UNREACHABLE(); | 320 UNREACHABLE(); |
321 | 321 |
322 case Expression::kEffect: | 322 case Expression::kEffect: |
323 __ Drop(1); | 323 __ Drop(1); |
324 break; | 324 break; |
325 | 325 |
326 case Expression::kValue: | 326 case Expression::kValue: |
327 switch (location_) { | 327 switch (location_) { |
328 case kAccumulator: | 328 case kAccumulator: |
329 __ pop(result_register()); | 329 __ pop(result_register()); |
330 break; | 330 break; |
331 case kStack: | 331 case kStack: |
332 break; | 332 break; |
333 } | 333 } |
334 break; | 334 break; |
335 | 335 |
336 case Expression::kTest: | 336 case Expression::kTest: |
337 __ pop(result_register()); | 337 __ pop(result_register()); |
338 DoTest(true_label_, false_label_, NULL); | 338 DoTest(true_label_, false_label_, fall_through_); |
339 break; | 339 break; |
340 } | 340 } |
341 } | 341 } |
342 | 342 |
343 | 343 |
344 void FullCodeGenerator::DropAndApply(int count, | 344 void FullCodeGenerator::DropAndApply(int count, |
345 Expression::Context context, | 345 Expression::Context context, |
346 Register reg) { | 346 Register reg) { |
347 ASSERT(count > 0); | 347 ASSERT(count > 0); |
348 ASSERT(!reg.is(rsp)); | 348 ASSERT(!reg.is(rsp)); |
(...skipping 14 matching lines...) Expand all Loading... |
363 case kStack: | 363 case kStack: |
364 if (count > 1) __ Drop(count - 1); | 364 if (count > 1) __ Drop(count - 1); |
365 __ movq(Operand(rsp, 0), reg); | 365 __ movq(Operand(rsp, 0), reg); |
366 break; | 366 break; |
367 } | 367 } |
368 break; | 368 break; |
369 | 369 |
370 case Expression::kTest: | 370 case Expression::kTest: |
371 __ Drop(count); | 371 __ Drop(count); |
372 if (!reg.is(result_register())) __ movq(result_register(), reg); | 372 if (!reg.is(result_register())) __ movq(result_register(), reg); |
373 DoTest(true_label_, false_label_, NULL); | 373 DoTest(true_label_, false_label_, fall_through_); |
374 break; | |
375 } | |
376 } | |
377 | |
378 | |
379 void FullCodeGenerator::PrepareTest(Label* materialize_true, | |
380 Label* materialize_false, | |
381 Label** if_true, | |
382 Label** if_false) { | |
383 switch (context_) { | |
384 case Expression::kUninitialized: | |
385 UNREACHABLE(); | |
386 break; | |
387 case Expression::kEffect: | |
388 // In an effect context, the true and the false case branch to the | |
389 // same label. | |
390 *if_true = *if_false = materialize_true; | |
391 break; | |
392 case Expression::kValue: | |
393 *if_true = materialize_true; | |
394 *if_false = materialize_false; | |
395 break; | |
396 case Expression::kTest: | |
397 *if_true = true_label_; | |
398 *if_false = false_label_; | |
399 break; | 374 break; |
400 } | 375 } |
401 } | 376 } |
402 | 377 |
403 | 378 |
404 void FullCodeGenerator::Apply(Expression::Context context, | 379 void FullCodeGenerator::Apply(Expression::Context context, |
405 Label* materialize_true, | 380 Label* materialize_true, |
406 Label* materialize_false) { | 381 Label* materialize_false) { |
407 switch (context) { | 382 switch (context) { |
408 case Expression::kUninitialized: | 383 case Expression::kUninitialized: |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
456 case kAccumulator: | 431 case kAccumulator: |
457 __ LoadRoot(result_register(), value_root_index); | 432 __ LoadRoot(result_register(), value_root_index); |
458 break; | 433 break; |
459 case kStack: | 434 case kStack: |
460 __ PushRoot(value_root_index); | 435 __ PushRoot(value_root_index); |
461 break; | 436 break; |
462 } | 437 } |
463 break; | 438 break; |
464 } | 439 } |
465 case Expression::kTest: | 440 case Expression::kTest: |
466 __ jmp(flag ? true_label_ : false_label_); | 441 if (flag) { |
| 442 if (true_label_ != fall_through_) __ jmp(true_label_); |
| 443 } else { |
| 444 if (false_label_ != fall_through_) __ jmp(false_label_); |
| 445 } |
467 break; | 446 break; |
468 } | 447 } |
469 } | 448 } |
470 | 449 |
471 | 450 |
472 void FullCodeGenerator::DoTest(Label* if_true, | 451 void FullCodeGenerator::DoTest(Label* if_true, |
473 Label* if_false, | 452 Label* if_false, |
474 Label* fall_through) { | 453 Label* fall_through) { |
475 // Emit the inlined tests assumed by the stub. | 454 // Emit the inlined tests assumed by the stub. |
476 __ CompareRoot(result_register(), Heap::kUndefinedValueRootIndex); | 455 __ CompareRoot(result_register(), Heap::kUndefinedValueRootIndex); |
(...skipping 1260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1737 | 1716 |
1738 | 1717 |
1739 void FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) { | 1718 void FullCodeGenerator::EmitIsSmi(ZoneList<Expression*>* args) { |
1740 ASSERT(args->length() == 1); | 1719 ASSERT(args->length() == 1); |
1741 | 1720 |
1742 VisitForValue(args->at(0), kAccumulator); | 1721 VisitForValue(args->at(0), kAccumulator); |
1743 | 1722 |
1744 Label materialize_true, materialize_false; | 1723 Label materialize_true, materialize_false; |
1745 Label* if_true = NULL; | 1724 Label* if_true = NULL; |
1746 Label* if_false = NULL; | 1725 Label* if_false = NULL; |
1747 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1726 Label* fall_through = NULL; |
| 1727 PrepareTest(&materialize_true, &materialize_false, |
| 1728 &if_true, &if_false, &fall_through); |
1748 | 1729 |
1749 __ JumpIfSmi(rax, if_true); | 1730 __ JumpIfSmi(rax, if_true); |
1750 __ jmp(if_false); | 1731 __ jmp(if_false); |
1751 | 1732 |
1752 Apply(context_, if_true, if_false); | 1733 Apply(context_, if_true, if_false); |
1753 } | 1734 } |
1754 | 1735 |
1755 | 1736 |
1756 void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) { | 1737 void FullCodeGenerator::EmitIsNonNegativeSmi(ZoneList<Expression*>* args) { |
1757 ASSERT(args->length() == 1); | 1738 ASSERT(args->length() == 1); |
1758 | 1739 |
1759 VisitForValue(args->at(0), kAccumulator); | 1740 VisitForValue(args->at(0), kAccumulator); |
1760 | 1741 |
1761 Label materialize_true, materialize_false; | 1742 Label materialize_true, materialize_false; |
1762 Label* if_true = NULL; | 1743 Label* if_true = NULL; |
1763 Label* if_false = NULL; | 1744 Label* if_false = NULL; |
1764 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1745 Label* fall_through = NULL; |
| 1746 PrepareTest(&materialize_true, &materialize_false, |
| 1747 &if_true, &if_false, &fall_through); |
1765 | 1748 |
1766 Condition positive_smi = __ CheckPositiveSmi(rax); | 1749 Condition positive_smi = __ CheckPositiveSmi(rax); |
1767 Split(positive_smi, if_true, if_false, NULL); | 1750 Split(positive_smi, if_true, if_false, fall_through); |
1768 | 1751 |
1769 Apply(context_, if_true, if_false); | 1752 Apply(context_, if_true, if_false); |
1770 } | 1753 } |
1771 | 1754 |
1772 | 1755 |
1773 void FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) { | 1756 void FullCodeGenerator::EmitIsObject(ZoneList<Expression*>* args) { |
1774 ASSERT(args->length() == 1); | 1757 ASSERT(args->length() == 1); |
1775 | 1758 |
1776 VisitForValue(args->at(0), kAccumulator); | 1759 VisitForValue(args->at(0), kAccumulator); |
1777 | 1760 |
1778 Label materialize_true, materialize_false; | 1761 Label materialize_true, materialize_false; |
1779 Label* if_true = NULL; | 1762 Label* if_true = NULL; |
1780 Label* if_false = NULL; | 1763 Label* if_false = NULL; |
1781 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1764 Label* fall_through = NULL; |
| 1765 PrepareTest(&materialize_true, &materialize_false, |
| 1766 &if_true, &if_false, &fall_through); |
1782 | 1767 |
1783 __ JumpIfSmi(rax, if_false); | 1768 __ JumpIfSmi(rax, if_false); |
1784 __ CompareRoot(rax, Heap::kNullValueRootIndex); | 1769 __ CompareRoot(rax, Heap::kNullValueRootIndex); |
1785 __ j(equal, if_true); | 1770 __ j(equal, if_true); |
1786 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); | 1771 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); |
1787 // Undetectable objects behave like undefined when tested with typeof. | 1772 // Undetectable objects behave like undefined when tested with typeof. |
1788 __ testb(FieldOperand(rbx, Map::kBitFieldOffset), | 1773 __ testb(FieldOperand(rbx, Map::kBitFieldOffset), |
1789 Immediate(1 << Map::kIsUndetectable)); | 1774 Immediate(1 << Map::kIsUndetectable)); |
1790 __ j(not_zero, if_false); | 1775 __ j(not_zero, if_false); |
1791 __ movzxbq(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); | 1776 __ movzxbq(rbx, FieldOperand(rbx, Map::kInstanceTypeOffset)); |
1792 __ cmpq(rbx, Immediate(FIRST_JS_OBJECT_TYPE)); | 1777 __ cmpq(rbx, Immediate(FIRST_JS_OBJECT_TYPE)); |
1793 __ j(below, if_false); | 1778 __ j(below, if_false); |
1794 __ cmpq(rbx, Immediate(LAST_JS_OBJECT_TYPE)); | 1779 __ cmpq(rbx, Immediate(LAST_JS_OBJECT_TYPE)); |
1795 Split(below_equal, if_true, if_false, NULL); | 1780 Split(below_equal, if_true, if_false, fall_through); |
1796 | 1781 |
1797 Apply(context_, if_true, if_false); | 1782 Apply(context_, if_true, if_false); |
1798 } | 1783 } |
1799 | 1784 |
1800 | 1785 |
1801 void FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) { | 1786 void FullCodeGenerator::EmitIsSpecObject(ZoneList<Expression*>* args) { |
1802 ASSERT(args->length() == 1); | 1787 ASSERT(args->length() == 1); |
1803 | 1788 |
1804 VisitForValue(args->at(0), kAccumulator); | 1789 VisitForValue(args->at(0), kAccumulator); |
1805 | 1790 |
1806 Label materialize_true, materialize_false; | 1791 Label materialize_true, materialize_false; |
1807 Label* if_true = NULL; | 1792 Label* if_true = NULL; |
1808 Label* if_false = NULL; | 1793 Label* if_false = NULL; |
1809 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1794 Label* fall_through = NULL; |
| 1795 PrepareTest(&materialize_true, &materialize_false, |
| 1796 &if_true, &if_false, &fall_through); |
1810 | 1797 |
1811 __ JumpIfSmi(rax, if_false); | 1798 __ JumpIfSmi(rax, if_false); |
1812 __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rbx); | 1799 __ CmpObjectType(rax, FIRST_JS_OBJECT_TYPE, rbx); |
1813 Split(above_equal, if_true, if_false, NULL); | 1800 Split(above_equal, if_true, if_false, fall_through); |
1814 | 1801 |
1815 Apply(context_, if_true, if_false); | 1802 Apply(context_, if_true, if_false); |
1816 } | 1803 } |
1817 | 1804 |
1818 | 1805 |
1819 void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) { | 1806 void FullCodeGenerator::EmitIsUndetectableObject(ZoneList<Expression*>* args) { |
1820 ASSERT(args->length() == 1); | 1807 ASSERT(args->length() == 1); |
1821 | 1808 |
1822 VisitForValue(args->at(0), kAccumulator); | 1809 VisitForValue(args->at(0), kAccumulator); |
1823 | 1810 |
1824 Label materialize_true, materialize_false; | 1811 Label materialize_true, materialize_false; |
1825 Label* if_true = NULL; | 1812 Label* if_true = NULL; |
1826 Label* if_false = NULL; | 1813 Label* if_false = NULL; |
1827 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1814 Label* fall_through = NULL; |
| 1815 PrepareTest(&materialize_true, &materialize_false, |
| 1816 &if_true, &if_false, &fall_through); |
1828 | 1817 |
1829 __ JumpIfSmi(rax, if_false); | 1818 __ JumpIfSmi(rax, if_false); |
1830 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); | 1819 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); |
1831 __ testb(FieldOperand(rbx, Map::kBitFieldOffset), | 1820 __ testb(FieldOperand(rbx, Map::kBitFieldOffset), |
1832 Immediate(1 << Map::kIsUndetectable)); | 1821 Immediate(1 << Map::kIsUndetectable)); |
1833 Split(not_zero, if_true, if_false, NULL); | 1822 Split(not_zero, if_true, if_false, fall_through); |
1834 | 1823 |
1835 Apply(context_, if_true, if_false); | 1824 Apply(context_, if_true, if_false); |
1836 } | 1825 } |
1837 | 1826 |
1838 | 1827 |
1839 void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( | 1828 void FullCodeGenerator::EmitIsStringWrapperSafeForDefaultValueOf( |
1840 ZoneList<Expression*>* args) { | 1829 ZoneList<Expression*>* args) { |
1841 ASSERT(args->length() == 1); | 1830 ASSERT(args->length() == 1); |
1842 | 1831 |
1843 VisitForValue(args->at(0), kAccumulator); | 1832 VisitForValue(args->at(0), kAccumulator); |
1844 | 1833 |
1845 Label materialize_true, materialize_false; | 1834 Label materialize_true, materialize_false; |
1846 Label* if_true = NULL; | 1835 Label* if_true = NULL; |
1847 Label* if_false = NULL; | 1836 Label* if_false = NULL; |
1848 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1837 Label* fall_through = NULL; |
| 1838 PrepareTest(&materialize_true, &materialize_false, |
| 1839 &if_true, &if_false, &fall_through); |
1849 | 1840 |
1850 // Just indicate false, as %_IsStringWrapperSafeForDefaultValueOf() is only | 1841 // Just indicate false, as %_IsStringWrapperSafeForDefaultValueOf() is only |
1851 // used in a few functions in runtime.js which should not normally be hit by | 1842 // used in a few functions in runtime.js which should not normally be hit by |
1852 // this compiler. | 1843 // this compiler. |
1853 __ jmp(if_false); | 1844 __ jmp(if_false); |
1854 Apply(context_, if_true, if_false); | 1845 Apply(context_, if_true, if_false); |
1855 } | 1846 } |
1856 | 1847 |
1857 | 1848 |
1858 void FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) { | 1849 void FullCodeGenerator::EmitIsFunction(ZoneList<Expression*>* args) { |
1859 ASSERT(args->length() == 1); | 1850 ASSERT(args->length() == 1); |
1860 | 1851 |
1861 VisitForValue(args->at(0), kAccumulator); | 1852 VisitForValue(args->at(0), kAccumulator); |
1862 | 1853 |
1863 Label materialize_true, materialize_false; | 1854 Label materialize_true, materialize_false; |
1864 Label* if_true = NULL; | 1855 Label* if_true = NULL; |
1865 Label* if_false = NULL; | 1856 Label* if_false = NULL; |
1866 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1857 Label* fall_through = NULL; |
| 1858 PrepareTest(&materialize_true, &materialize_false, |
| 1859 &if_true, &if_false, &fall_through); |
1867 | 1860 |
1868 __ JumpIfSmi(rax, if_false); | 1861 __ JumpIfSmi(rax, if_false); |
1869 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx); | 1862 __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx); |
1870 Split(equal, if_true, if_false, NULL); | 1863 Split(equal, if_true, if_false, fall_through); |
1871 | 1864 |
1872 Apply(context_, if_true, if_false); | 1865 Apply(context_, if_true, if_false); |
1873 } | 1866 } |
1874 | 1867 |
1875 | 1868 |
1876 void FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) { | 1869 void FullCodeGenerator::EmitIsArray(ZoneList<Expression*>* args) { |
1877 ASSERT(args->length() == 1); | 1870 ASSERT(args->length() == 1); |
1878 | 1871 |
1879 VisitForValue(args->at(0), kAccumulator); | 1872 VisitForValue(args->at(0), kAccumulator); |
1880 | 1873 |
1881 Label materialize_true, materialize_false; | 1874 Label materialize_true, materialize_false; |
1882 Label* if_true = NULL; | 1875 Label* if_true = NULL; |
1883 Label* if_false = NULL; | 1876 Label* if_false = NULL; |
1884 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1877 Label* fall_through = NULL; |
| 1878 PrepareTest(&materialize_true, &materialize_false, |
| 1879 &if_true, &if_false, &fall_through); |
1885 | 1880 |
1886 __ JumpIfSmi(rax, if_false); | 1881 __ JumpIfSmi(rax, if_false); |
1887 __ CmpObjectType(rax, JS_ARRAY_TYPE, rbx); | 1882 __ CmpObjectType(rax, JS_ARRAY_TYPE, rbx); |
1888 Split(equal, if_true, if_false, NULL); | 1883 Split(equal, if_true, if_false, fall_through); |
1889 | 1884 |
1890 Apply(context_, if_true, if_false); | 1885 Apply(context_, if_true, if_false); |
1891 } | 1886 } |
1892 | 1887 |
1893 | 1888 |
1894 void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) { | 1889 void FullCodeGenerator::EmitIsRegExp(ZoneList<Expression*>* args) { |
1895 ASSERT(args->length() == 1); | 1890 ASSERT(args->length() == 1); |
1896 | 1891 |
1897 VisitForValue(args->at(0), kAccumulator); | 1892 VisitForValue(args->at(0), kAccumulator); |
1898 | 1893 |
1899 Label materialize_true, materialize_false; | 1894 Label materialize_true, materialize_false; |
1900 Label* if_true = NULL; | 1895 Label* if_true = NULL; |
1901 Label* if_false = NULL; | 1896 Label* if_false = NULL; |
1902 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1897 Label* fall_through = NULL; |
| 1898 PrepareTest(&materialize_true, &materialize_false, |
| 1899 &if_true, &if_false, &fall_through); |
1903 | 1900 |
1904 __ JumpIfSmi(rax, if_false); | 1901 __ JumpIfSmi(rax, if_false); |
1905 __ CmpObjectType(rax, JS_REGEXP_TYPE, rbx); | 1902 __ CmpObjectType(rax, JS_REGEXP_TYPE, rbx); |
1906 Split(equal, if_true, if_false, NULL); | 1903 Split(equal, if_true, if_false, fall_through); |
1907 | 1904 |
1908 Apply(context_, if_true, if_false); | 1905 Apply(context_, if_true, if_false); |
1909 } | 1906 } |
1910 | 1907 |
1911 | 1908 |
1912 | 1909 |
1913 void FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) { | 1910 void FullCodeGenerator::EmitIsConstructCall(ZoneList<Expression*>* args) { |
1914 ASSERT(args->length() == 0); | 1911 ASSERT(args->length() == 0); |
1915 | 1912 |
1916 Label materialize_true, materialize_false; | 1913 Label materialize_true, materialize_false; |
1917 Label* if_true = NULL; | 1914 Label* if_true = NULL; |
1918 Label* if_false = NULL; | 1915 Label* if_false = NULL; |
1919 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1916 Label* fall_through = NULL; |
| 1917 PrepareTest(&materialize_true, &materialize_false, |
| 1918 &if_true, &if_false, &fall_through); |
1920 | 1919 |
1921 // Get the frame pointer for the calling frame. | 1920 // Get the frame pointer for the calling frame. |
1922 __ movq(rax, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); | 1921 __ movq(rax, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); |
1923 | 1922 |
1924 // Skip the arguments adaptor frame if it exists. | 1923 // Skip the arguments adaptor frame if it exists. |
1925 Label check_frame_marker; | 1924 Label check_frame_marker; |
1926 __ SmiCompare(Operand(rax, StandardFrameConstants::kContextOffset), | 1925 __ SmiCompare(Operand(rax, StandardFrameConstants::kContextOffset), |
1927 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); | 1926 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); |
1928 __ j(not_equal, &check_frame_marker); | 1927 __ j(not_equal, &check_frame_marker); |
1929 __ movq(rax, Operand(rax, StandardFrameConstants::kCallerFPOffset)); | 1928 __ movq(rax, Operand(rax, StandardFrameConstants::kCallerFPOffset)); |
1930 | 1929 |
1931 // Check the marker in the calling frame. | 1930 // Check the marker in the calling frame. |
1932 __ bind(&check_frame_marker); | 1931 __ bind(&check_frame_marker); |
1933 __ SmiCompare(Operand(rax, StandardFrameConstants::kMarkerOffset), | 1932 __ SmiCompare(Operand(rax, StandardFrameConstants::kMarkerOffset), |
1934 Smi::FromInt(StackFrame::CONSTRUCT)); | 1933 Smi::FromInt(StackFrame::CONSTRUCT)); |
1935 Split(equal, if_true, if_false, NULL); | 1934 Split(equal, if_true, if_false, fall_through); |
1936 | 1935 |
1937 Apply(context_, if_true, if_false); | 1936 Apply(context_, if_true, if_false); |
1938 } | 1937 } |
1939 | 1938 |
1940 | 1939 |
1941 void FullCodeGenerator::EmitObjectEquals(ZoneList<Expression*>* args) { | 1940 void FullCodeGenerator::EmitObjectEquals(ZoneList<Expression*>* args) { |
1942 ASSERT(args->length() == 2); | 1941 ASSERT(args->length() == 2); |
1943 | 1942 |
1944 // Load the two objects into registers and perform the comparison. | 1943 // Load the two objects into registers and perform the comparison. |
1945 VisitForValue(args->at(0), kStack); | 1944 VisitForValue(args->at(0), kStack); |
1946 VisitForValue(args->at(1), kAccumulator); | 1945 VisitForValue(args->at(1), kAccumulator); |
1947 | 1946 |
1948 Label materialize_true, materialize_false; | 1947 Label materialize_true, materialize_false; |
1949 Label* if_true = NULL; | 1948 Label* if_true = NULL; |
1950 Label* if_false = NULL; | 1949 Label* if_false = NULL; |
1951 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 1950 Label* fall_through = NULL; |
| 1951 PrepareTest(&materialize_true, &materialize_false, |
| 1952 &if_true, &if_false, &fall_through); |
1952 | 1953 |
1953 __ pop(rbx); | 1954 __ pop(rbx); |
1954 __ cmpq(rax, rbx); | 1955 __ cmpq(rax, rbx); |
1955 Split(equal, if_true, if_false, NULL); | 1956 Split(equal, if_true, if_false, fall_through); |
1956 | 1957 |
1957 Apply(context_, if_true, if_false); | 1958 Apply(context_, if_true, if_false); |
1958 } | 1959 } |
1959 | 1960 |
1960 | 1961 |
1961 void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) { | 1962 void FullCodeGenerator::EmitArguments(ZoneList<Expression*>* args) { |
1962 ASSERT(args->length() == 1); | 1963 ASSERT(args->length() == 1); |
1963 | 1964 |
1964 // ArgumentsAccessStub expects the key in edx and the formal | 1965 // ArgumentsAccessStub expects the key in edx and the formal |
1965 // parameter count in eax. | 1966 // parameter count in eax. |
(...skipping 639 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2605 break; | 2606 break; |
2606 } | 2607 } |
2607 break; | 2608 break; |
2608 } | 2609 } |
2609 | 2610 |
2610 case Token::NOT: { | 2611 case Token::NOT: { |
2611 Comment cmnt(masm_, "[ UnaryOperation (NOT)"); | 2612 Comment cmnt(masm_, "[ UnaryOperation (NOT)"); |
2612 Label materialize_true, materialize_false; | 2613 Label materialize_true, materialize_false; |
2613 Label* if_true = NULL; | 2614 Label* if_true = NULL; |
2614 Label* if_false = NULL; | 2615 Label* if_false = NULL; |
2615 | 2616 Label* fall_through = NULL; |
2616 // Notice that the labels are swapped. | 2617 // Notice that the labels are swapped. |
2617 PrepareTest(&materialize_true, &materialize_false, &if_false, &if_true); | 2618 PrepareTest(&materialize_true, &materialize_false, |
2618 | 2619 &if_false, &if_true, &fall_through); |
2619 VisitForControl(expr->expression(), if_true, if_false); | 2620 VisitForControl(expr->expression(), if_true, if_false, fall_through); |
2620 | |
2621 Apply(context_, if_false, if_true); // Labels swapped. | 2621 Apply(context_, if_false, if_true); // Labels swapped. |
2622 break; | 2622 break; |
2623 } | 2623 } |
2624 | 2624 |
2625 case Token::TYPEOF: { | 2625 case Token::TYPEOF: { |
2626 Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)"); | 2626 Comment cmnt(masm_, "[ UnaryOperation (TYPEOF)"); |
2627 VisitForTypeofValue(expr->expression(), kStack); | 2627 VisitForTypeofValue(expr->expression(), kStack); |
2628 __ CallRuntime(Runtime::kTypeof, 1); | 2628 __ CallRuntime(Runtime::kTypeof, 1); |
2629 Apply(context_, rax); | 2629 Apply(context_, rax); |
2630 break; | 2630 break; |
(...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2972 | 2972 |
2973 void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { | 2973 void FullCodeGenerator::VisitCompareOperation(CompareOperation* expr) { |
2974 Comment cmnt(masm_, "[ CompareOperation"); | 2974 Comment cmnt(masm_, "[ CompareOperation"); |
2975 SetSourcePosition(expr->position()); | 2975 SetSourcePosition(expr->position()); |
2976 | 2976 |
2977 // Always perform the comparison for its control flow. Pack the result | 2977 // Always perform the comparison for its control flow. Pack the result |
2978 // into the expression's context after the comparison is performed. | 2978 // into the expression's context after the comparison is performed. |
2979 Label materialize_true, materialize_false; | 2979 Label materialize_true, materialize_false; |
2980 Label* if_true = NULL; | 2980 Label* if_true = NULL; |
2981 Label* if_false = NULL; | 2981 Label* if_false = NULL; |
2982 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 2982 Label* fall_through = NULL; |
| 2983 PrepareTest(&materialize_true, &materialize_false, |
| 2984 &if_true, &if_false, &fall_through); |
2983 | 2985 |
2984 // First we try a fast inlined version of the compare when one of | 2986 // First we try a fast inlined version of the compare when one of |
2985 // the operands is a literal. | 2987 // the operands is a literal. |
2986 Token::Value op = expr->op(); | 2988 Token::Value op = expr->op(); |
2987 Expression* left = expr->left(); | 2989 Expression* left = expr->left(); |
2988 Expression* right = expr->right(); | 2990 Expression* right = expr->right(); |
2989 if (TryLiteralCompare(op, left, right, if_true, if_false, NULL)) { | 2991 if (TryLiteralCompare(op, left, right, if_true, if_false, fall_through)) { |
2990 Apply(context_, if_true, if_false); | 2992 Apply(context_, if_true, if_false); |
2991 return; | 2993 return; |
2992 } | 2994 } |
2993 | 2995 |
2994 VisitForValue(expr->left(), kStack); | 2996 VisitForValue(expr->left(), kStack); |
2995 switch (expr->op()) { | 2997 switch (expr->op()) { |
2996 case Token::IN: | 2998 case Token::IN: |
2997 VisitForValue(expr->right(), kStack); | 2999 VisitForValue(expr->right(), kStack); |
2998 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); | 3000 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION); |
2999 __ CompareRoot(rax, Heap::kTrueValueRootIndex); | 3001 __ CompareRoot(rax, Heap::kTrueValueRootIndex); |
3000 Split(equal, if_true, if_false, NULL); | 3002 Split(equal, if_true, if_false, fall_through); |
3001 break; | 3003 break; |
3002 | 3004 |
3003 case Token::INSTANCEOF: { | 3005 case Token::INSTANCEOF: { |
3004 VisitForValue(expr->right(), kStack); | 3006 VisitForValue(expr->right(), kStack); |
3005 InstanceofStub stub; | 3007 InstanceofStub stub; |
3006 __ CallStub(&stub); | 3008 __ CallStub(&stub); |
3007 __ testq(rax, rax); | 3009 __ testq(rax, rax); |
3008 // The stub returns 0 for true. | 3010 // The stub returns 0 for true. |
3009 Split(zero, if_true, if_false, NULL); | 3011 Split(zero, if_true, if_false, fall_through); |
3010 break; | 3012 break; |
3011 } | 3013 } |
3012 | 3014 |
3013 default: { | 3015 default: { |
3014 VisitForValue(expr->right(), kAccumulator); | 3016 VisitForValue(expr->right(), kAccumulator); |
3015 Condition cc = no_condition; | 3017 Condition cc = no_condition; |
3016 bool strict = false; | 3018 bool strict = false; |
3017 switch (expr->op()) { | 3019 switch (expr->op()) { |
3018 case Token::EQ_STRICT: | 3020 case Token::EQ_STRICT: |
3019 strict = true; | 3021 strict = true; |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3053 Label slow_case; | 3055 Label slow_case; |
3054 __ JumpIfNotBothSmi(rax, rdx, &slow_case); | 3056 __ JumpIfNotBothSmi(rax, rdx, &slow_case); |
3055 __ SmiCompare(rdx, rax); | 3057 __ SmiCompare(rdx, rax); |
3056 __ j(cc, if_true); | 3058 __ j(cc, if_true); |
3057 __ jmp(if_false); | 3059 __ jmp(if_false); |
3058 | 3060 |
3059 __ bind(&slow_case); | 3061 __ bind(&slow_case); |
3060 CompareStub stub(cc, strict); | 3062 CompareStub stub(cc, strict); |
3061 __ CallStub(&stub); | 3063 __ CallStub(&stub); |
3062 __ testq(rax, rax); | 3064 __ testq(rax, rax); |
3063 Split(cc, if_true, if_false, NULL); | 3065 Split(cc, if_true, if_false, fall_through); |
3064 } | 3066 } |
3065 } | 3067 } |
3066 | 3068 |
3067 // Convert the result of the comparison into one expected for this | 3069 // Convert the result of the comparison into one expected for this |
3068 // expression's context. | 3070 // expression's context. |
3069 Apply(context_, if_true, if_false); | 3071 Apply(context_, if_true, if_false); |
3070 } | 3072 } |
3071 | 3073 |
3072 | 3074 |
3073 void FullCodeGenerator::VisitCompareToNull(CompareToNull* expr) { | 3075 void FullCodeGenerator::VisitCompareToNull(CompareToNull* expr) { |
3074 Comment cmnt(masm_, "[ CompareToNull"); | 3076 Comment cmnt(masm_, "[ CompareToNull"); |
3075 Label materialize_true, materialize_false; | 3077 Label materialize_true, materialize_false; |
3076 Label* if_true = NULL; | 3078 Label* if_true = NULL; |
3077 Label* if_false = NULL; | 3079 Label* if_false = NULL; |
3078 PrepareTest(&materialize_true, &materialize_false, &if_true, &if_false); | 3080 Label* fall_through = NULL; |
| 3081 PrepareTest(&materialize_true, &materialize_false, |
| 3082 &if_true, &if_false, &fall_through); |
3079 | 3083 |
3080 VisitForValue(expr->expression(), kAccumulator); | 3084 VisitForValue(expr->expression(), kAccumulator); |
3081 __ CompareRoot(rax, Heap::kNullValueRootIndex); | 3085 __ CompareRoot(rax, Heap::kNullValueRootIndex); |
3082 if (expr->is_strict()) { | 3086 if (expr->is_strict()) { |
3083 Split(equal, if_true, if_false, NULL); | 3087 Split(equal, if_true, if_false, fall_through); |
3084 } else { | 3088 } else { |
3085 __ j(equal, if_true); | 3089 __ j(equal, if_true); |
3086 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); | 3090 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); |
3087 __ j(equal, if_true); | 3091 __ j(equal, if_true); |
3088 Condition is_smi = masm_->CheckSmi(rax); | 3092 Condition is_smi = masm_->CheckSmi(rax); |
3089 __ j(is_smi, if_false); | 3093 __ j(is_smi, if_false); |
3090 // It can be an undetectable object. | 3094 // It can be an undetectable object. |
3091 __ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset)); | 3095 __ movq(rdx, FieldOperand(rax, HeapObject::kMapOffset)); |
3092 __ testb(FieldOperand(rdx, Map::kBitFieldOffset), | 3096 __ testb(FieldOperand(rdx, Map::kBitFieldOffset), |
3093 Immediate(1 << Map::kIsUndetectable)); | 3097 Immediate(1 << Map::kIsUndetectable)); |
3094 Split(not_zero, if_true, if_false, NULL); | 3098 Split(not_zero, if_true, if_false, fall_through); |
3095 } | 3099 } |
3096 Apply(context_, if_true, if_false); | 3100 Apply(context_, if_true, if_false); |
3097 } | 3101 } |
3098 | 3102 |
3099 | 3103 |
3100 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { | 3104 void FullCodeGenerator::VisitThisFunction(ThisFunction* expr) { |
3101 __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); | 3105 __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); |
3102 Apply(context_, rax); | 3106 Apply(context_, rax); |
3103 } | 3107 } |
3104 | 3108 |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3153 __ ret(0); | 3157 __ ret(0); |
3154 } | 3158 } |
3155 | 3159 |
3156 | 3160 |
3157 #undef __ | 3161 #undef __ |
3158 | 3162 |
3159 | 3163 |
3160 } } // namespace v8::internal | 3164 } } // namespace v8::internal |
3161 | 3165 |
3162 #endif // V8_TARGET_ARCH_X64 | 3166 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |