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