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