Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 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 700 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 711 } | 711 } |
| 712 } | 712 } |
| 713 | 713 |
| 714 | 714 |
| 715 class DeferredInlineBinaryOperation: public DeferredCode { | 715 class DeferredInlineBinaryOperation: public DeferredCode { |
| 716 public: | 716 public: |
| 717 DeferredInlineBinaryOperation(CodeGenerator* generator, | 717 DeferredInlineBinaryOperation(CodeGenerator* generator, |
| 718 Token::Value op, | 718 Token::Value op, |
| 719 OverwriteMode mode, | 719 OverwriteMode mode, |
| 720 GenericBinaryFlags flags) | 720 GenericBinaryFlags flags) |
| 721 : DeferredCode(generator), | 721 : DeferredCode(generator), stub_(op, mode, flags), op_(op) { |
| 722 stub_(op, mode, flags), | 722 set_comment("[ DeferredInlineBinaryOperation"); |
| 723 op_(op) { | |
| 724 } | 723 } |
| 725 | 724 |
| 726 // The binary operation's arguments are on top of the code generator's frame. | |
| 727 Result GenerateInlineCode(); | 725 Result GenerateInlineCode(); |
| 728 | 726 |
| 729 virtual void Generate() { | 727 virtual void Generate(); |
| 730 Result left(generator()); | |
| 731 Result right(generator()); | |
| 732 enter()->Bind(&left, &right); | |
| 733 generator()->frame()->Push(&left); | |
| 734 generator()->frame()->Push(&right); | |
| 735 Result answer = generator()->frame()->CallStub(&stub_, 2); | |
| 736 exit()->Jump(&answer); | |
| 737 } | |
| 738 | 728 |
| 739 private: | 729 private: |
| 740 GenericBinaryOpStub stub_; | 730 GenericBinaryOpStub stub_; |
| 741 Token::Value op_; | 731 Token::Value op_; |
| 742 }; | 732 }; |
| 743 | 733 |
| 744 | 734 |
| 735 void DeferredInlineBinaryOperation::Generate() { | |
| 736 Result left(generator()); | |
| 737 Result right(generator()); | |
| 738 enter()->Bind(&left, &right); | |
| 739 generator()->frame()->Push(&left); | |
| 740 generator()->frame()->Push(&right); | |
| 741 Result answer = generator()->frame()->CallStub(&stub_, 2); | |
| 742 exit()->Jump(&answer); | |
| 743 } | |
| 744 | |
| 745 | |
| 745 void CodeGenerator::GenericBinaryOperation(Token::Value op, | 746 void CodeGenerator::GenericBinaryOperation(Token::Value op, |
| 746 StaticType* type, | 747 StaticType* type, |
| 747 OverwriteMode overwrite_mode) { | 748 OverwriteMode overwrite_mode) { |
| 748 Comment cmnt(masm_, "[ BinaryOperation"); | 749 Comment cmnt(masm_, "[ BinaryOperation"); |
| 749 Comment cmnt_token(masm_, Token::String(op)); | 750 Comment cmnt_token(masm_, Token::String(op)); |
| 750 | 751 |
| 751 if (op == Token::COMMA) { | 752 if (op == Token::COMMA) { |
| 752 // Simply discard left value. | 753 // Simply discard left value. |
| 753 frame_->Nip(1); | 754 frame_->Nip(1); |
| 754 return; | 755 return; |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 793 GenericBinaryOpStub stub(op, overwrite_mode, flags); | 794 GenericBinaryOpStub stub(op, overwrite_mode, flags); |
| 794 Result answer = frame_->CallStub(&stub, 2); | 795 Result answer = frame_->CallStub(&stub, 2); |
| 795 frame_->Push(&answer); | 796 frame_->Push(&answer); |
| 796 } | 797 } |
| 797 } | 798 } |
| 798 | 799 |
| 799 | 800 |
| 800 class DeferredInlinedSmiOperation: public DeferredCode { | 801 class DeferredInlinedSmiOperation: public DeferredCode { |
| 801 public: | 802 public: |
| 802 DeferredInlinedSmiOperation(CodeGenerator* generator, | 803 DeferredInlinedSmiOperation(CodeGenerator* generator, |
| 803 Token::Value op, int value, | 804 Token::Value op, |
| 804 OverwriteMode overwrite_mode) : | 805 int value, |
| 805 DeferredCode(generator), op_(op), value_(value), | 806 OverwriteMode overwrite_mode) |
| 806 overwrite_mode_(overwrite_mode) { | 807 : DeferredCode(generator), |
| 808 op_(op), | |
| 809 value_(value), | |
| 810 overwrite_mode_(overwrite_mode) { | |
| 807 set_comment("[ DeferredInlinedSmiOperation"); | 811 set_comment("[ DeferredInlinedSmiOperation"); |
| 808 } | 812 } |
| 809 virtual void Generate() { | 813 |
| 810 // The argument is actually passed in eax. | 814 virtual void Generate(); |
| 811 enter()->Bind(); | |
| 812 VirtualFrame::SpilledScope spilled_scope(generator()); | |
| 813 generator()->frame()->EmitPush(eax); | |
| 814 generator()->frame()->EmitPush(Immediate(Smi::FromInt(value_))); | |
| 815 GenericBinaryOpStub igostub(op_, overwrite_mode_, SMI_CODE_INLINED); | |
| 816 generator()->frame()->CallStub(&igostub, 2); | |
| 817 // The result is actually returned in eax. | |
| 818 exit()->Jump(); | |
| 819 } | |
| 820 | 815 |
| 821 private: | 816 private: |
| 822 Token::Value op_; | 817 Token::Value op_; |
| 823 int value_; | 818 int value_; |
| 824 OverwriteMode overwrite_mode_; | 819 OverwriteMode overwrite_mode_; |
| 825 }; | 820 }; |
| 826 | 821 |
| 827 | 822 |
| 823 void DeferredInlinedSmiOperation::Generate() { | |
| 824 // The argument is passed in eax. | |
| 825 enter()->Bind(); | |
| 826 VirtualFrame::SpilledScope spilled_scope(generator()); | |
| 827 generator()->frame()->EmitPush(eax); | |
| 828 generator()->frame()->EmitPush(Immediate(Smi::FromInt(value_))); | |
| 829 GenericBinaryOpStub igostub(op_, overwrite_mode_, SMI_CODE_INLINED); | |
| 830 generator()->frame()->CallStub(&igostub, 2); | |
| 831 // The result is returned in eax. | |
| 832 exit()->Jump(); | |
| 833 } | |
| 834 | |
| 835 | |
| 828 class DeferredInlinedSmiOperationReversed: public DeferredCode { | 836 class DeferredInlinedSmiOperationReversed: public DeferredCode { |
| 829 public: | 837 public: |
| 830 DeferredInlinedSmiOperationReversed(CodeGenerator* generator, | 838 DeferredInlinedSmiOperationReversed(CodeGenerator* generator, |
| 831 Token::Value op, int value, | 839 Token::Value op, |
| 832 OverwriteMode overwrite_mode) : | 840 int value, |
| 833 DeferredCode(generator), op_(op), value_(value), | 841 OverwriteMode overwrite_mode) |
| 834 overwrite_mode_(overwrite_mode) { | 842 : DeferredCode(generator), |
| 843 op_(op), | |
| 844 value_(value), | |
| 845 overwrite_mode_(overwrite_mode) { | |
| 835 set_comment("[ DeferredInlinedSmiOperationReversed"); | 846 set_comment("[ DeferredInlinedSmiOperationReversed"); |
| 836 } | 847 } |
| 837 virtual void Generate() { | 848 |
| 838 // The argument is actually passed in eax. | 849 virtual void Generate(); |
| 839 enter()->Bind(); | |
| 840 VirtualFrame::SpilledScope spilled_scope(generator()); | |
| 841 generator()->frame()->EmitPush(Immediate(Smi::FromInt(value_))); | |
| 842 generator()->frame()->EmitPush(eax); | |
| 843 GenericBinaryOpStub igostub(op_, overwrite_mode_, SMI_CODE_INLINED); | |
| 844 generator()->frame()->CallStub(&igostub, 2); | |
| 845 // The result is actually returned in eax. | |
| 846 exit()->Jump(); | |
|
William Hesse
2009/01/26 10:07:50
The other change list returns a result through Jum
Kevin Millikin (Chromium)
2009/01/26 10:36:00
This is spilled code jumping into spilled code, so
| |
| 847 } | |
| 848 | 850 |
| 849 private: | 851 private: |
| 850 Token::Value op_; | 852 Token::Value op_; |
| 851 int value_; | 853 int value_; |
| 852 OverwriteMode overwrite_mode_; | 854 OverwriteMode overwrite_mode_; |
| 853 }; | 855 }; |
| 854 | 856 |
| 855 | 857 |
| 858 void DeferredInlinedSmiOperationReversed::Generate() { | |
| 859 // The argument is passed in eax. | |
| 860 enter()->Bind(); | |
| 861 VirtualFrame::SpilledScope spilled_scope(generator()); | |
| 862 generator()->frame()->EmitPush(Immediate(Smi::FromInt(value_))); | |
| 863 generator()->frame()->EmitPush(eax); | |
| 864 GenericBinaryOpStub igostub(op_, overwrite_mode_, SMI_CODE_INLINED); | |
| 865 generator()->frame()->CallStub(&igostub, 2); | |
| 866 // The result is returned in eax. | |
| 867 exit()->Jump(); | |
| 868 } | |
| 869 | |
| 870 | |
| 856 class DeferredInlinedSmiAdd: public DeferredCode { | 871 class DeferredInlinedSmiAdd: public DeferredCode { |
| 857 public: | 872 public: |
| 858 DeferredInlinedSmiAdd(CodeGenerator* generator, Smi* value, | 873 DeferredInlinedSmiAdd(CodeGenerator* generator, |
| 859 OverwriteMode overwrite_mode) : | 874 Smi* value, |
| 860 DeferredCode(generator), value_(value), overwrite_mode_(overwrite_mode) { | 875 OverwriteMode overwrite_mode) |
| 876 : DeferredCode(generator), | |
| 877 value_(value), | |
| 878 overwrite_mode_(overwrite_mode) { | |
| 861 set_comment("[ DeferredInlinedSmiAdd"); | 879 set_comment("[ DeferredInlinedSmiAdd"); |
| 862 } | 880 } |
| 863 | 881 |
| 864 virtual void Generate() { | 882 virtual void Generate(); |
| 865 Result arg(generator()); | |
| 866 enter()->Bind(&arg); | |
| 867 arg.ToRegister(); | |
| 868 generator()->frame()->Spill(arg.reg()); | |
| 869 // Undo the optimistic add operation and call the shared stub. | |
| 870 __ sub(Operand(arg.reg()), Immediate(value_)); | |
| 871 generator()->frame()->Push(&arg); | |
| 872 generator()->frame()->Push(value_); | |
| 873 GenericBinaryOpStub igostub(Token::ADD, overwrite_mode_, SMI_CODE_INLINED); | |
| 874 Result result = generator()->frame()->CallStub(&igostub, 2); | |
| 875 exit()->Jump(&result); | |
| 876 } | |
| 877 | 883 |
| 878 private: | 884 private: |
| 879 Smi* value_; | 885 Smi* value_; |
| 880 OverwriteMode overwrite_mode_; | 886 OverwriteMode overwrite_mode_; |
| 881 }; | 887 }; |
| 882 | 888 |
| 883 | 889 |
| 890 void DeferredInlinedSmiAdd::Generate() { | |
| 891 // Undo the optimistic add operation and call the shared stub. | |
| 892 Result left(generator()); // Initially left + value_. | |
| 893 enter()->Bind(&left); | |
| 894 left.ToRegister(); | |
| 895 generator()->frame()->Spill(left.reg()); | |
| 896 __ sub(Operand(left.reg()), Immediate(value_)); | |
| 897 generator()->frame()->Push(&left); | |
| 898 generator()->frame()->Push(value_); | |
| 899 GenericBinaryOpStub igostub(Token::ADD, overwrite_mode_, SMI_CODE_INLINED); | |
| 900 Result answer = generator()->frame()->CallStub(&igostub, 2); | |
| 901 exit()->Jump(&answer); | |
| 902 } | |
| 903 | |
| 904 | |
| 884 class DeferredInlinedSmiAddReversed: public DeferredCode { | 905 class DeferredInlinedSmiAddReversed: public DeferredCode { |
| 885 public: | 906 public: |
| 886 DeferredInlinedSmiAddReversed(CodeGenerator* generator, Smi* value, | 907 DeferredInlinedSmiAddReversed(CodeGenerator* generator, |
| 887 OverwriteMode overwrite_mode) : | 908 Smi* value, |
| 888 DeferredCode(generator), value_(value), overwrite_mode_(overwrite_mode) { | 909 OverwriteMode overwrite_mode) |
| 910 : DeferredCode(generator), | |
| 911 value_(value), | |
| 912 overwrite_mode_(overwrite_mode) { | |
| 889 set_comment("[ DeferredInlinedSmiAddReversed"); | 913 set_comment("[ DeferredInlinedSmiAddReversed"); |
| 890 } | 914 } |
| 891 | 915 |
| 892 virtual void Generate() { | 916 virtual void Generate(); |
| 893 Result arg(generator()); | |
| 894 enter()->Bind(&arg); | |
| 895 arg.ToRegister(); | |
| 896 generator()->frame()->Spill(arg.reg()); | |
| 897 // Undo the optimistic add operation and call the shared stub. | |
| 898 __ sub(Operand(arg.reg()), Immediate(value_)); | |
| 899 generator()->frame()->Push(value_); | |
| 900 generator()->frame()->Push(&arg); | |
| 901 GenericBinaryOpStub igostub(Token::ADD, overwrite_mode_, SMI_CODE_INLINED); | |
| 902 arg = generator()->frame()->CallStub(&igostub, 2); | |
| 903 exit()->Jump(&arg); | |
| 904 } | |
| 905 | 917 |
| 906 private: | 918 private: |
| 907 Smi* value_; | 919 Smi* value_; |
| 908 OverwriteMode overwrite_mode_; | 920 OverwriteMode overwrite_mode_; |
| 909 }; | 921 }; |
| 910 | 922 |
| 911 | 923 |
| 924 void DeferredInlinedSmiAddReversed::Generate() { | |
| 925 // Undo the optimistic add operation and call the shared stub. | |
| 926 Result right(generator()); // Initially value_ + right. | |
| 927 enter()->Bind(&right); | |
| 928 right.ToRegister(); | |
| 929 generator()->frame()->Spill(right.reg()); | |
| 930 __ sub(Operand(right.reg()), Immediate(value_)); | |
| 931 generator()->frame()->Push(value_); | |
| 932 generator()->frame()->Push(&right); | |
| 933 GenericBinaryOpStub igostub(Token::ADD, overwrite_mode_, SMI_CODE_INLINED); | |
| 934 Result answer = generator()->frame()->CallStub(&igostub, 2); | |
| 935 exit()->Jump(&answer); | |
| 936 } | |
| 937 | |
| 938 | |
| 912 class DeferredInlinedSmiSub: public DeferredCode { | 939 class DeferredInlinedSmiSub: public DeferredCode { |
| 913 public: | 940 public: |
| 914 DeferredInlinedSmiSub(CodeGenerator* generator, | 941 DeferredInlinedSmiSub(CodeGenerator* generator, |
| 915 Smi* value, | 942 Smi* value, |
| 916 OverwriteMode overwrite_mode) : | 943 OverwriteMode overwrite_mode) |
| 917 DeferredCode(generator), value_(value), overwrite_mode_(overwrite_mode) { | 944 : DeferredCode(generator), |
| 945 value_(value), | |
| 946 overwrite_mode_(overwrite_mode) { | |
| 918 set_comment("[ DeferredInlinedSmiSub"); | 947 set_comment("[ DeferredInlinedSmiSub"); |
| 919 } | 948 } |
| 920 | 949 |
| 921 virtual void Generate() { | 950 virtual void Generate(); |
| 922 Result argument(generator()); | |
| 923 enter()->Bind(&argument); | |
| 924 argument.ToRegister(); | |
| 925 generator()->frame()->Spill(argument.reg()); | |
| 926 // Undo the optimistic sub operation and call the shared stub. | |
| 927 __ add(Operand(argument.reg()), Immediate(value_)); | |
| 928 generator()->frame()->Push(&argument); | |
| 929 generator()->frame()->Push(value_); | |
| 930 GenericBinaryOpStub igostub(Token::SUB, overwrite_mode_, SMI_CODE_INLINED); | |
| 931 Result answer = generator()->frame()->CallStub(&igostub, 2); | |
| 932 // The result is actually returned in eax. | |
| 933 exit()->Jump(&answer); | |
| 934 } | |
| 935 | 951 |
| 936 private: | 952 private: |
| 937 Smi* value_; | 953 Smi* value_; |
| 938 OverwriteMode overwrite_mode_; | 954 OverwriteMode overwrite_mode_; |
| 939 }; | 955 }; |
| 940 | 956 |
| 941 | 957 |
| 958 void DeferredInlinedSmiSub::Generate() { | |
| 959 // Undo the optimistic sub operation and call the shared stub. | |
| 960 Result left(generator()); // Initially left - value_. | |
| 961 enter()->Bind(&left); | |
| 962 left.ToRegister(); | |
| 963 generator()->frame()->Spill(left.reg()); | |
| 964 __ add(Operand(left.reg()), Immediate(value_)); | |
| 965 generator()->frame()->Push(&left); | |
| 966 generator()->frame()->Push(value_); | |
| 967 GenericBinaryOpStub igostub(Token::SUB, overwrite_mode_, SMI_CODE_INLINED); | |
| 968 Result answer = generator()->frame()->CallStub(&igostub, 2); | |
| 969 exit()->Jump(&answer); | |
| 970 } | |
| 971 | |
| 972 | |
| 942 class DeferredInlinedSmiSubReversed: public DeferredCode { | 973 class DeferredInlinedSmiSubReversed: public DeferredCode { |
| 943 public: | 974 public: |
| 944 DeferredInlinedSmiSubReversed(CodeGenerator* generator, | 975 DeferredInlinedSmiSubReversed(CodeGenerator* generator, |
| 945 Smi* value, | 976 Smi* value, |
| 946 OverwriteMode overwrite_mode) : | 977 OverwriteMode overwrite_mode) |
| 947 DeferredCode(generator), value_(value), | 978 : DeferredCode(generator), |
| 948 overwrite_mode_(overwrite_mode) { | 979 value_(value), |
| 980 overwrite_mode_(overwrite_mode) { | |
| 949 set_comment("[ DeferredInlinedSmiSubReversed"); | 981 set_comment("[ DeferredInlinedSmiSubReversed"); |
| 950 } | 982 } |
| 951 | 983 |
| 952 virtual void Generate() { | 984 virtual void Generate(); |
| 953 Result rhs(generator()); | |
| 954 enter()->Bind(&rhs); | |
| 955 generator()->frame()->Push(value_); | |
| 956 generator()->frame()->Push(&rhs); | |
| 957 GenericBinaryOpStub igostub(Token::SUB, overwrite_mode_, SMI_CODE_INLINED); | |
| 958 Result answer = generator()->frame()->CallStub(&igostub, 2); | |
| 959 exit()->Jump(&answer); | |
| 960 } | |
| 961 | 985 |
| 962 private: | 986 private: |
| 963 Smi* value_; | 987 Smi* value_; |
| 964 OverwriteMode overwrite_mode_; | 988 OverwriteMode overwrite_mode_; |
| 965 }; | 989 }; |
| 966 | 990 |
| 967 | 991 |
| 992 void DeferredInlinedSmiSubReversed::Generate() { | |
| 993 // Call the shared stub. | |
| 994 Result right(generator()); | |
| 995 enter()->Bind(&right); | |
| 996 generator()->frame()->Push(value_); | |
| 997 generator()->frame()->Push(&right); | |
| 998 GenericBinaryOpStub igostub(Token::SUB, overwrite_mode_, SMI_CODE_INLINED); | |
| 999 Result answer = generator()->frame()->CallStub(&igostub, 2); | |
| 1000 exit()->Jump(&answer); | |
| 1001 } | |
| 1002 | |
| 1003 | |
| 968 void CodeGenerator::SmiOperation(Token::Value op, | 1004 void CodeGenerator::SmiOperation(Token::Value op, |
| 969 StaticType* type, | 1005 StaticType* type, |
| 970 Handle<Object> value, | 1006 Handle<Object> value, |
| 971 bool reversed, | 1007 bool reversed, |
| 972 OverwriteMode overwrite_mode) { | 1008 OverwriteMode overwrite_mode) { |
| 973 // NOTE: This is an attempt to inline (a bit) more of the code for | 1009 // NOTE: This is an attempt to inline (a bit) more of the code for |
| 974 // some possible smi operations (like + and -) when (at least) one | 1010 // some possible smi operations (like + and -) when (at least) one |
| 975 // of the operands is a literal smi. With this optimization, the | 1011 // of the operands is a literal smi. With this optimization, the |
| 976 // performance of the system is increased by ~15%, and the generated | 1012 // performance of the system is increased by ~15%, and the generated |
| 977 // code size is increased by ~1% (measured on a combination of | 1013 // code size is increased by ~1% (measured on a combination of |
| (...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1336 Result answer = frame_->CallStub(&call_function, arg_count + 1); | 1372 Result answer = frame_->CallStub(&call_function, arg_count + 1); |
| 1337 // Restore context and replace function on the stack with the | 1373 // Restore context and replace function on the stack with the |
| 1338 // result of the stub invocation. | 1374 // result of the stub invocation. |
| 1339 frame_->RestoreContextRegister(); | 1375 frame_->RestoreContextRegister(); |
| 1340 frame_->SetElementAt(0, &answer); | 1376 frame_->SetElementAt(0, &answer); |
| 1341 } | 1377 } |
| 1342 | 1378 |
| 1343 | 1379 |
| 1344 class DeferredStackCheck: public DeferredCode { | 1380 class DeferredStackCheck: public DeferredCode { |
| 1345 public: | 1381 public: |
| 1346 DeferredStackCheck(CodeGenerator* generator) | 1382 explicit DeferredStackCheck(CodeGenerator* generator) |
| 1347 : DeferredCode(generator) { | 1383 : DeferredCode(generator) { |
| 1348 set_comment("[ DeferredStackCheck"); | 1384 set_comment("[ DeferredStackCheck"); |
| 1349 } | 1385 } |
| 1350 | 1386 |
| 1351 virtual void Generate(); | 1387 virtual void Generate(); |
| 1352 }; | 1388 }; |
| 1353 | 1389 |
| 1354 | 1390 |
| 1355 void DeferredStackCheck::Generate() { | 1391 void DeferredStackCheck::Generate() { |
| 1356 enter()->Bind(); | 1392 enter()->Bind(); |
| (...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1596 CodeForStatement(node); | 1632 CodeForStatement(node); |
| 1597 Load(node->expression()); | 1633 Load(node->expression()); |
| 1598 | 1634 |
| 1599 // Pop the result from the frame and prepare the frame for | 1635 // Pop the result from the frame and prepare the frame for |
| 1600 // returning thus making it easier to merge. | 1636 // returning thus making it easier to merge. |
| 1601 Result result = frame_->Pop(); | 1637 Result result = frame_->Pop(); |
| 1602 frame_->PrepareForReturn(); | 1638 frame_->PrepareForReturn(); |
| 1603 | 1639 |
| 1604 // Move the result into register eax where it belongs. | 1640 // Move the result into register eax where it belongs. |
| 1605 result.ToRegister(eax); | 1641 result.ToRegister(eax); |
| 1606 // TODO(): Instead of explictly calling Unuse on the result, it | 1642 // TODO(203): Instead of explictly calling Unuse on the result, it |
| 1607 // might be better to pass the result to Jump and Bind below. | 1643 // might be better to pass the result to Jump and Bind below. |
| 1608 result.Unuse(); | 1644 result.Unuse(); |
| 1609 | 1645 |
| 1610 // If the function return label is already bound, we reuse the | 1646 // If the function return label is already bound, we reuse the |
| 1611 // code by jumping to the return site. | 1647 // code by jumping to the return site. |
| 1612 if (function_return_.is_bound()) { | 1648 if (function_return_.is_bound()) { |
| 1613 function_return_.Jump(); | 1649 function_return_.Jump(); |
| 1614 } else { | 1650 } else { |
| 1615 function_return_.Bind(); | 1651 function_return_.Bind(); |
| 1616 GenerateReturnSequence(); | 1652 GenerateReturnSequence(); |
| (...skipping 1102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2719 // The other slot types (LOOKUP and GLOBAL) cannot reach here. | 2755 // The other slot types (LOOKUP and GLOBAL) cannot reach here. |
| 2720 ASSERT(slot->type() == Slot::CONTEXT); | 2756 ASSERT(slot->type() == Slot::CONTEXT); |
| 2721 frame_->Dup(); | 2757 frame_->Dup(); |
| 2722 Result value = frame_->Pop(); | 2758 Result value = frame_->Pop(); |
| 2723 value.ToRegister(); | 2759 value.ToRegister(); |
| 2724 Result start = allocator_->Allocate(); | 2760 Result start = allocator_->Allocate(); |
| 2725 ASSERT(start.is_valid()); | 2761 ASSERT(start.is_valid()); |
| 2726 __ mov(SlotOperand(slot, start.reg()), value.reg()); | 2762 __ mov(SlotOperand(slot, start.reg()), value.reg()); |
| 2727 // RecordWrite may destroy the value registers. | 2763 // RecordWrite may destroy the value registers. |
| 2728 // | 2764 // |
| 2729 // TODO(): Avoid actually spilling when the value is not needed | 2765 // TODO(204): Avoid actually spilling when the value is not |
| 2730 // (probably the common case). | 2766 // needed (probably the common case). |
| 2731 frame_->Spill(value.reg()); | 2767 frame_->Spill(value.reg()); |
| 2732 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; | 2768 int offset = FixedArray::kHeaderSize + slot->index() * kPointerSize; |
| 2733 Result temp = allocator_->Allocate(); | 2769 Result temp = allocator_->Allocate(); |
| 2734 ASSERT(temp.is_valid()); | 2770 ASSERT(temp.is_valid()); |
| 2735 __ RecordWrite(start.reg(), offset, value.reg(), temp.reg()); | 2771 __ RecordWrite(start.reg(), offset, value.reg(), temp.reg()); |
| 2736 // The results start, value, and temp are unused by going out of | 2772 // The results start, value, and temp are unused by going out of |
| 2737 // scope. | 2773 // scope. |
| 2738 } | 2774 } |
| 2739 | 2775 |
| 2740 // If we definitely did not jump over the assignment, we do not need | 2776 // If we definitely did not jump over the assignment, we do not need |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2791 } | 2827 } |
| 2792 } | 2828 } |
| 2793 | 2829 |
| 2794 | 2830 |
| 2795 class DeferredRegExpLiteral: public DeferredCode { | 2831 class DeferredRegExpLiteral: public DeferredCode { |
| 2796 public: | 2832 public: |
| 2797 DeferredRegExpLiteral(CodeGenerator* generator, RegExpLiteral* node) | 2833 DeferredRegExpLiteral(CodeGenerator* generator, RegExpLiteral* node) |
| 2798 : DeferredCode(generator), node_(node) { | 2834 : DeferredCode(generator), node_(node) { |
| 2799 set_comment("[ DeferredRegExpLiteral"); | 2835 set_comment("[ DeferredRegExpLiteral"); |
| 2800 } | 2836 } |
| 2837 | |
| 2801 virtual void Generate(); | 2838 virtual void Generate(); |
| 2839 | |
| 2802 private: | 2840 private: |
| 2803 RegExpLiteral* node_; | 2841 RegExpLiteral* node_; |
| 2804 }; | 2842 }; |
| 2805 | 2843 |
| 2806 | 2844 |
| 2807 void DeferredRegExpLiteral::Generate() { | 2845 void DeferredRegExpLiteral::Generate() { |
| 2808 // The argument is actually passed in ecx. | 2846 // The argument is actually passed in ecx. |
| 2809 enter()->Bind(); | 2847 enter()->Bind(); |
| 2810 VirtualFrame::SpilledScope spilled_scope(generator()); | 2848 VirtualFrame::SpilledScope spilled_scope(generator()); |
| 2811 // If the entry is undefined we call the runtime system to compute the | 2849 // If the entry is undefined we call the runtime system to compute the |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2860 // by calling Runtime_CreateObjectLiteral. | 2898 // by calling Runtime_CreateObjectLiteral. |
| 2861 // Each created boilerplate is stored in the JSFunction and they are | 2899 // Each created boilerplate is stored in the JSFunction and they are |
| 2862 // therefore context dependent. | 2900 // therefore context dependent. |
| 2863 class DeferredObjectLiteral: public DeferredCode { | 2901 class DeferredObjectLiteral: public DeferredCode { |
| 2864 public: | 2902 public: |
| 2865 DeferredObjectLiteral(CodeGenerator* generator, | 2903 DeferredObjectLiteral(CodeGenerator* generator, |
| 2866 ObjectLiteral* node) | 2904 ObjectLiteral* node) |
| 2867 : DeferredCode(generator), node_(node) { | 2905 : DeferredCode(generator), node_(node) { |
| 2868 set_comment("[ DeferredObjectLiteral"); | 2906 set_comment("[ DeferredObjectLiteral"); |
| 2869 } | 2907 } |
| 2908 | |
| 2870 virtual void Generate(); | 2909 virtual void Generate(); |
| 2910 | |
| 2871 private: | 2911 private: |
| 2872 ObjectLiteral* node_; | 2912 ObjectLiteral* node_; |
| 2873 }; | 2913 }; |
| 2874 | 2914 |
| 2875 | 2915 |
| 2876 void DeferredObjectLiteral::Generate() { | 2916 void DeferredObjectLiteral::Generate() { |
| 2877 // The argument is actually passed in ecx. | 2917 // The argument is actually passed in ecx. |
| 2878 enter()->Bind(); | 2918 enter()->Bind(); |
| 2879 VirtualFrame::SpilledScope spilled_scope(generator()); | 2919 VirtualFrame::SpilledScope spilled_scope(generator()); |
| 2880 // If the entry is undefined we call the runtime system to compute | 2920 // If the entry is undefined we call the runtime system to compute |
| (...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3261 Load(node->expression()); | 3301 Load(node->expression()); |
| 3262 LoadGlobal(); | 3302 LoadGlobal(); |
| 3263 | 3303 |
| 3264 // Push the arguments ("left-to-right") on the stack. | 3304 // Push the arguments ("left-to-right") on the stack. |
| 3265 ZoneList<Expression*>* args = node->arguments(); | 3305 ZoneList<Expression*>* args = node->arguments(); |
| 3266 int arg_count = args->length(); | 3306 int arg_count = args->length(); |
| 3267 for (int i = 0; i < arg_count; i++) { | 3307 for (int i = 0; i < arg_count; i++) { |
| 3268 Load(args->at(i)); | 3308 Load(args->at(i)); |
| 3269 } | 3309 } |
| 3270 | 3310 |
| 3271 // TODO(): Get rid of this spilling. It is only necessary because we | 3311 // TODO(205): Get rid of this spilling. It is only necessary because |
| 3272 // load the function from the non-virtual stack. | 3312 // we load the function from the non-virtual stack. |
| 3273 frame_->SpillAll(); | 3313 frame_->SpillAll(); |
| 3274 | 3314 |
| 3275 // Constructors are called with the number of arguments in register | 3315 // Constructors are called with the number of arguments in register |
| 3276 // eax for now. Another option would be to have separate construct | 3316 // eax for now. Another option would be to have separate construct |
| 3277 // call trampolines per different arguments counts encountered. | 3317 // call trampolines per different arguments counts encountered. |
| 3278 __ Set(eax, Immediate(arg_count)); | 3318 __ Set(eax, Immediate(arg_count)); |
| 3279 | 3319 |
| 3280 // Load the function into temporary function slot as per calling | 3320 // Load the function into temporary function slot as per calling |
| 3281 // convention. | 3321 // convention. |
| 3282 __ mov(edi, frame_->ElementAt(arg_count + 1)); | 3322 __ mov(edi, frame_->ElementAt(arg_count + 1)); |
| (...skipping 1076 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4359 #endif | 4399 #endif |
| 4360 | 4400 |
| 4361 | 4401 |
| 4362 class DeferredReferenceGetKeyedValue: public DeferredCode { | 4402 class DeferredReferenceGetKeyedValue: public DeferredCode { |
| 4363 public: | 4403 public: |
| 4364 DeferredReferenceGetKeyedValue(CodeGenerator* generator, bool is_global) | 4404 DeferredReferenceGetKeyedValue(CodeGenerator* generator, bool is_global) |
| 4365 : DeferredCode(generator), is_global_(is_global) { | 4405 : DeferredCode(generator), is_global_(is_global) { |
| 4366 set_comment("[ DeferredReferenceGetKeyedValue"); | 4406 set_comment("[ DeferredReferenceGetKeyedValue"); |
| 4367 } | 4407 } |
| 4368 | 4408 |
| 4369 virtual void Generate() { | 4409 virtual void Generate(); |
| 4370 CodeGenerator* cgen = generator(); | |
| 4371 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | |
| 4372 Result receiver(cgen); | |
| 4373 Result key(cgen); | |
| 4374 enter()->Bind(&receiver, &key); | |
| 4375 VirtualFrame* frame = generator()->frame(); | |
| 4376 frame->Push(&receiver); // First IC argument. | |
| 4377 frame->Push(&key); // Second IC argument. | |
| 4378 | |
| 4379 // Calculate the delta from the IC call instruction to the map | |
| 4380 // check cmp instruction in the inlined version. This delta is | |
| 4381 // stored in a test(eax, delta) instruction after the call so that | |
| 4382 // we can find it in the IC initialization code and patch the cmp | |
| 4383 // instruction. This means that we cannot allow test instructions | |
| 4384 // after calls to KeyedLoadIC stubs in other places. | |
| 4385 // | |
| 4386 // The virtual frame should be spilled fully before the call so | |
| 4387 // that the call itself does not generate extra code to spill | |
| 4388 // values. | |
| 4389 frame->SpillAll(); | |
| 4390 int delta_to_patch_site = __ SizeOfCodeGeneratedSince(patch_site()); | |
| 4391 Result value(cgen); | |
| 4392 if (is_global_) { | |
| 4393 value = frame->CallCodeObject(ic, RelocInfo::CODE_TARGET_CONTEXT, 0); | |
| 4394 } else { | |
| 4395 value = frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0); | |
| 4396 } | |
| 4397 // The result needs to be specifically the eax register because | |
| 4398 // the offset to the patch site will be expected in a test eax | |
| 4399 // instruction. | |
| 4400 ASSERT(value.is_register() && value.reg().is(eax)); | |
| 4401 __ test(value.reg(), Immediate(-delta_to_patch_site)); | |
| 4402 __ IncrementCounter(&Counters::keyed_load_inline_miss, 1); | |
| 4403 exit()->Jump(&value); | |
| 4404 } | |
| 4405 | 4410 |
| 4406 Label* patch_site() { return &patch_site_; } | 4411 Label* patch_site() { return &patch_site_; } |
| 4407 | 4412 |
| 4408 private: | 4413 private: |
| 4409 Label patch_site_; | 4414 Label patch_site_; |
| 4410 bool is_global_; | 4415 bool is_global_; |
| 4411 }; | 4416 }; |
| 4412 | 4417 |
| 4413 | 4418 |
| 4419 void DeferredReferenceGetKeyedValue::Generate() { | |
| 4420 CodeGenerator* cgen = generator(); | |
| 4421 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | |
| 4422 Result receiver(cgen); | |
| 4423 Result key(cgen); | |
| 4424 enter()->Bind(&receiver, &key); | |
| 4425 cgen->frame()->Push(&receiver); // First IC argument. | |
| 4426 cgen->frame()->Push(&key); // Second IC argument. | |
| 4427 | |
| 4428 // Calculate the delta from the IC call instruction to the map check | |
| 4429 // cmp instruction in the inlined version. This delta is stored in | |
| 4430 // a test(eax, delta) instruction after the call so that we can find | |
| 4431 // it in the IC initialization code and patch the cmp instruction. | |
| 4432 // This means that we cannot allow test instructions after calls to | |
| 4433 // KeyedLoadIC stubs in other places. | |
| 4434 // | |
| 4435 // The virtual frame should be spilled fully before the call so that | |
| 4436 // the call itself does not generate extra code to spill values, | |
| 4437 // which would invalidate the delta calculation. | |
| 4438 cgen->frame()->SpillAll(); | |
| 4439 int delta_to_patch_site = __ SizeOfCodeGeneratedSince(patch_site()); | |
| 4440 Result value(cgen); | |
| 4441 if (is_global_) { | |
| 4442 value = cgen->frame()->CallCodeObject(ic, | |
| 4443 RelocInfo::CODE_TARGET_CONTEXT, | |
| 4444 0); | |
| 4445 } else { | |
| 4446 value = cgen->frame()->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0); | |
| 4447 } | |
| 4448 // The result needs to be specifically the eax register because the | |
| 4449 // offset to the patch site will be expected in a test eax | |
| 4450 // instruction. | |
| 4451 ASSERT(value.is_register() && value.reg().is(eax)); | |
| 4452 __ test(value.reg(), Immediate(-delta_to_patch_site)); | |
| 4453 __ IncrementCounter(&Counters::keyed_load_inline_miss, 1); | |
| 4454 exit()->Jump(&value); | |
| 4455 } | |
| 4456 | |
| 4457 | |
| 4414 #undef __ | 4458 #undef __ |
| 4415 #define __ masm-> | 4459 #define __ masm-> |
| 4416 | 4460 |
| 4417 Handle<String> Reference::GetName() { | 4461 Handle<String> Reference::GetName() { |
| 4418 ASSERT(type_ == NAMED); | 4462 ASSERT(type_ == NAMED); |
| 4419 Property* property = expression_->AsProperty(); | 4463 Property* property = expression_->AsProperty(); |
| 4420 if (property == NULL) { | 4464 if (property == NULL) { |
| 4421 // Global variable reference treated as a named property reference. | 4465 // Global variable reference treated as a named property reference. |
| 4422 VariableProxy* proxy = expression_->AsVariableProxy(); | 4466 VariableProxy* proxy = expression_->AsVariableProxy(); |
| 4423 ASSERT(proxy->AsVariable() != NULL); | 4467 ASSERT(proxy->AsVariable() != NULL); |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4525 ASSERT(index.is_valid()); | 4569 ASSERT(index.is_valid()); |
| 4526 __ mov(index.reg(), key.reg()); | 4570 __ mov(index.reg(), key.reg()); |
| 4527 __ sar(index.reg(), kSmiTagSize); | 4571 __ sar(index.reg(), kSmiTagSize); |
| 4528 __ cmp(index.reg(), | 4572 __ cmp(index.reg(), |
| 4529 FieldOperand(elements.reg(), Array::kLengthOffset)); | 4573 FieldOperand(elements.reg(), Array::kLengthOffset)); |
| 4530 deferred->enter()->Branch(above_equal, &receiver, &key, not_taken); | 4574 deferred->enter()->Branch(above_equal, &receiver, &key, not_taken); |
| 4531 | 4575 |
| 4532 // Load and check that the result is not the hole. We could | 4576 // Load and check that the result is not the hole. We could |
| 4533 // reuse the index or elements register for the value. | 4577 // reuse the index or elements register for the value. |
| 4534 // | 4578 // |
| 4535 // TODO(): Consider whether it makes sense to try some | 4579 // TODO(206): Consider whether it makes sense to try some |
| 4536 // heuristic about which register to reuse. For example, if | 4580 // heuristic about which register to reuse. For example, if |
| 4537 // one is eax, the we can reuse that one because the value | 4581 // one is eax, the we can reuse that one because the value |
| 4538 // coming from the deferred code will be in eax. | 4582 // coming from the deferred code will be in eax. |
| 4539 Result value = index; | 4583 Result value = index; |
| 4540 __ mov(value.reg(), Operand(elements.reg(), | 4584 __ mov(value.reg(), Operand(elements.reg(), |
| 4541 index.reg(), | 4585 index.reg(), |
| 4542 times_4, | 4586 times_4, |
| 4543 Array::kHeaderSize - kHeapObjectTag)); | 4587 Array::kHeaderSize - kHeapObjectTag)); |
| 4544 elements.Unuse(); | 4588 elements.Unuse(); |
| 4545 index.Unuse(); | 4589 index.Unuse(); |
| (...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4934 ASSERT(kSmiTag == 0); | 4978 ASSERT(kSmiTag == 0); |
| 4935 __ shl(left.reg(), kSmiTagSize); | 4979 __ shl(left.reg(), kSmiTagSize); |
| 4936 __ shl(right.reg(), kSmiTagSize); | 4980 __ shl(right.reg(), kSmiTagSize); |
| 4937 enter()->Jump(&left, &right); | 4981 enter()->Jump(&left, &right); |
| 4938 result_ok.Bind(&left, &right); | 4982 result_ok.Bind(&left, &right); |
| 4939 break; | 4983 break; |
| 4940 } | 4984 } |
| 4941 case Token::SHL: { | 4985 case Token::SHL: { |
| 4942 __ shl(left.reg()); | 4986 __ shl(left.reg()); |
| 4943 // Check that the *signed* result fits in a smi. | 4987 // Check that the *signed* result fits in a smi. |
| 4944 // TODO(): Can reduce registers from 4 to 3 by preallocating ecx. | 4988 // |
| 4989 // TODO(207): Can reduce registers from 4 to 3 by | |
| 4990 // preallocating ecx. | |
| 4945 JumpTarget result_ok(generator()); | 4991 JumpTarget result_ok(generator()); |
| 4946 Result smi_test_reg = generator()->allocator()->Allocate(); | 4992 Result smi_test_reg = generator()->allocator()->Allocate(); |
| 4947 ASSERT(smi_test_reg.is_valid()); | 4993 ASSERT(smi_test_reg.is_valid()); |
| 4948 __ lea(smi_test_reg.reg(), Operand(left.reg(), 0x40000000)); | 4994 __ lea(smi_test_reg.reg(), Operand(left.reg(), 0x40000000)); |
| 4949 __ test(smi_test_reg.reg(), Immediate(0x80000000)); | 4995 __ test(smi_test_reg.reg(), Immediate(0x80000000)); |
| 4950 smi_test_reg.Unuse(); | 4996 smi_test_reg.Unuse(); |
| 4951 result_ok.Branch(zero, &left, &right, taken); | 4997 result_ok.Branch(zero, &left, &right, taken); |
| 4952 __ shr(left.reg()); | 4998 __ shr(left.reg()); |
| 4953 ASSERT(kSmiTag == 0); | 4999 ASSERT(kSmiTag == 0); |
| 4954 __ shl(left.reg(), kSmiTagSize); | 5000 __ shl(left.reg(), kSmiTagSize); |
| (...skipping 1185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6140 | 6186 |
| 6141 // Slow-case: Go through the JavaScript implementation. | 6187 // Slow-case: Go through the JavaScript implementation. |
| 6142 __ bind(&slow); | 6188 __ bind(&slow); |
| 6143 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); | 6189 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); |
| 6144 } | 6190 } |
| 6145 | 6191 |
| 6146 | 6192 |
| 6147 #undef __ | 6193 #undef __ |
| 6148 | 6194 |
| 6149 } } // namespace v8::internal | 6195 } } // namespace v8::internal |
| OLD | NEW |