Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(451)

Side by Side Diff: src/codegen-ia32.cc

Issue 18742: Experimental: cleanup of the code generator source file. Some simple... (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/toiger/
Patch Set: Created 11 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698