| 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 |