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

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

Issue 15079: Experimental: this is a substantial change to allow the virtual frame... (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/toiger/
Patch Set: '' Created 12 years 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
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 695 matching lines...) Expand 10 before | Expand all | Expand 10 after
706 OverwriteMode mode, 706 OverwriteMode mode,
707 GenericBinaryFlags flags) 707 GenericBinaryFlags flags)
708 : DeferredCode(generator), 708 : DeferredCode(generator),
709 stub_(op, mode, flags), 709 stub_(op, mode, flags),
710 op_(op) { 710 op_(op) {
711 } 711 }
712 712
713 void GenerateInlineCode(); 713 void GenerateInlineCode();
714 714
715 virtual void Generate() { 715 virtual void Generate() {
716 __ push(ebx); 716 // The arguments are is actually passed in ebx and the top of the stack.
717 __ CallStub(&stub_); 717 enter()->Bind();
718 VirtualFrame::SpilledScope spilled_scope(generator());
719 generator()->frame()->EmitPush(ebx);
720 generator()->frame()->CallStub(&stub_, 2);
718 // We must preserve the eax value here, because it will be written 721 // We must preserve the eax value here, because it will be written
719 // to the top-of-stack element when getting back to the fast case 722 // to the top-of-stack element when getting back to the fast case
720 // code. See comment in GenericBinaryOperation where 723 // code. See comment in GenericBinaryOperation where
721 // deferred->exit() is bound. 724 // deferred->exit() is bound.
722 __ push(eax); 725 generator()->frame()->EmitPush(eax);
726 // The result is actually returned on the top of the stack.
727 exit()->Jump();
723 } 728 }
724 729
725 private: 730 private:
726 GenericBinaryOpStub stub_; 731 GenericBinaryOpStub stub_;
727 Token::Value op_; 732 Token::Value op_;
728 }; 733 };
729 734
730 735
731 void CodeGenerator::GenericBinaryOperation(Token::Value op, 736 void CodeGenerator::GenericBinaryOperation(Token::Value op,
732 StaticType* type, 737 StaticType* type,
(...skipping 29 matching lines...) Expand all
762 // By default only inline the Smi check code for likely smis if this 767 // By default only inline the Smi check code for likely smis if this
763 // operation is part of a loop. 768 // operation is part of a loop.
764 flags = ((loop_nesting() > 0) && type->IsLikelySmi()) 769 flags = ((loop_nesting() > 0) && type->IsLikelySmi())
765 ? SMI_CODE_INLINED 770 ? SMI_CODE_INLINED
766 : SMI_CODE_IN_STUB; 771 : SMI_CODE_IN_STUB;
767 break; 772 break;
768 } 773 }
769 774
770 if (flags == SMI_CODE_INLINED) { 775 if (flags == SMI_CODE_INLINED) {
771 // Create a new deferred code for the slow-case part. 776 // Create a new deferred code for the slow-case part.
777 //
778 // TODO(): When this code is updated to use the virtual frame, it
779 // has to properly flow to the inline code from this deferred code
780 // stub.
772 DeferredInlineBinaryOperation* deferred = 781 DeferredInlineBinaryOperation* deferred =
773 new DeferredInlineBinaryOperation(this, op, overwrite_mode, flags); 782 new DeferredInlineBinaryOperation(this, op, overwrite_mode, flags);
774 // Fetch the operands from the stack. 783 // Fetch the operands from the stack.
775 frame_->EmitPop(ebx); // get y 784 frame_->EmitPop(ebx); // get y
776 __ mov(eax, frame_->Top()); // get x 785 __ mov(eax, frame_->Top()); // get x
777 // Generate the inline part of the code. 786 // Generate the inline part of the code.
778 deferred->GenerateInlineCode(); 787 deferred->GenerateInlineCode();
779 // Put result back on the stack. It seems somewhat weird to let 788 // Put result back on the stack. It seems somewhat weird to let
780 // the deferred code jump back before the assignment to the frame 789 // the deferred code jump back before the assignment to the frame
781 // top, but this is just to let the peephole optimizer get rid of 790 // top, but this is just to let the peephole optimizer get rid of
(...skipping 12 matching lines...) Expand all
794 class DeferredInlinedSmiOperation: public DeferredCode { 803 class DeferredInlinedSmiOperation: public DeferredCode {
795 public: 804 public:
796 DeferredInlinedSmiOperation(CodeGenerator* generator, 805 DeferredInlinedSmiOperation(CodeGenerator* generator,
797 Token::Value op, int value, 806 Token::Value op, int value,
798 OverwriteMode overwrite_mode) : 807 OverwriteMode overwrite_mode) :
799 DeferredCode(generator), op_(op), value_(value), 808 DeferredCode(generator), op_(op), value_(value),
800 overwrite_mode_(overwrite_mode) { 809 overwrite_mode_(overwrite_mode) {
801 set_comment("[ DeferredInlinedSmiOperation"); 810 set_comment("[ DeferredInlinedSmiOperation");
802 } 811 }
803 virtual void Generate() { 812 virtual void Generate() {
804 __ push(eax); 813 // The argument is actually passed in eax.
805 __ push(Immediate(Smi::FromInt(value_))); 814 enter()->Bind();
815 VirtualFrame::SpilledScope spilled_scope(generator());
816 generator()->frame()->EmitPush(eax);
817 generator()->frame()->EmitPush(Immediate(Smi::FromInt(value_)));
806 GenericBinaryOpStub igostub(op_, overwrite_mode_, SMI_CODE_INLINED); 818 GenericBinaryOpStub igostub(op_, overwrite_mode_, SMI_CODE_INLINED);
807 __ CallStub(&igostub); 819 generator()->frame()->CallStub(&igostub, 2);
820 // The result is actually returned in eax.
821 exit()->Jump();
808 } 822 }
809 823
810 private: 824 private:
811 Token::Value op_; 825 Token::Value op_;
812 int value_; 826 int value_;
813 OverwriteMode overwrite_mode_; 827 OverwriteMode overwrite_mode_;
814 }; 828 };
815 829
816 830
817 class DeferredInlinedSmiOperationReversed: public DeferredCode { 831 class DeferredInlinedSmiOperationReversed: public DeferredCode {
818 public: 832 public:
819 DeferredInlinedSmiOperationReversed(CodeGenerator* generator, 833 DeferredInlinedSmiOperationReversed(CodeGenerator* generator,
820 Token::Value op, int value, 834 Token::Value op, int value,
821 OverwriteMode overwrite_mode) : 835 OverwriteMode overwrite_mode) :
822 DeferredCode(generator), op_(op), value_(value), 836 DeferredCode(generator), op_(op), value_(value),
823 overwrite_mode_(overwrite_mode) { 837 overwrite_mode_(overwrite_mode) {
824 set_comment("[ DeferredInlinedSmiOperationReversed"); 838 set_comment("[ DeferredInlinedSmiOperationReversed");
825 } 839 }
826 virtual void Generate() { 840 virtual void Generate() {
827 __ push(Immediate(Smi::FromInt(value_))); 841 // The argument is actually passed in eax.
828 __ push(eax); 842 enter()->Bind();
843 VirtualFrame::SpilledScope spilled_scope(generator());
844 generator()->frame()->EmitPush(Immediate(Smi::FromInt(value_)));
845 generator()->frame()->EmitPush(eax);
829 GenericBinaryOpStub igostub(op_, overwrite_mode_, SMI_CODE_INLINED); 846 GenericBinaryOpStub igostub(op_, overwrite_mode_, SMI_CODE_INLINED);
830 __ CallStub(&igostub); 847 generator()->frame()->CallStub(&igostub, 2);
848 // The result is actually returned in eax.
849 exit()->Jump();
831 } 850 }
832 851
833 private: 852 private:
834 Token::Value op_; 853 Token::Value op_;
835 int value_; 854 int value_;
836 OverwriteMode overwrite_mode_; 855 OverwriteMode overwrite_mode_;
837 }; 856 };
838 857
839 858
840 class DeferredInlinedSmiAdd: public DeferredCode { 859 class DeferredInlinedSmiAdd: public DeferredCode {
841 public: 860 public:
842 DeferredInlinedSmiAdd(CodeGenerator* generator, int value, 861 DeferredInlinedSmiAdd(CodeGenerator* generator, int value,
843 OverwriteMode overwrite_mode) : 862 OverwriteMode overwrite_mode) :
844 DeferredCode(generator), value_(value), overwrite_mode_(overwrite_mode) { 863 DeferredCode(generator), value_(value), overwrite_mode_(overwrite_mode) {
845 set_comment("[ DeferredInlinedSmiAdd"); 864 set_comment("[ DeferredInlinedSmiAdd");
846 } 865 }
847 866
848 virtual void Generate() { 867 virtual void Generate() {
868 // The argument is actually passed in eax.
869 enter()->Bind();
870 VirtualFrame::SpilledScope spilled_scope(generator());
849 // Undo the optimistic add operation and call the shared stub. 871 // Undo the optimistic add operation and call the shared stub.
850 Immediate immediate(Smi::FromInt(value_)); 872 Immediate immediate(Smi::FromInt(value_));
851 __ sub(Operand(eax), immediate); 873 __ sub(Operand(eax), immediate);
852 __ push(eax); 874 generator()->frame()->EmitPush(eax);
853 __ push(immediate); 875 generator()->frame()->EmitPush(immediate);
854 GenericBinaryOpStub igostub(Token::ADD, overwrite_mode_, SMI_CODE_INLINED); 876 GenericBinaryOpStub igostub(Token::ADD, overwrite_mode_, SMI_CODE_INLINED);
855 __ CallStub(&igostub); 877 generator()->frame()->CallStub(&igostub, 2);
878 // The result is actually returned in eax.
879 exit()->Jump();
856 } 880 }
857 881
858 private: 882 private:
859 int value_; 883 int value_;
860 OverwriteMode overwrite_mode_; 884 OverwriteMode overwrite_mode_;
861 }; 885 };
862 886
863 887
864 class DeferredInlinedSmiAddReversed: public DeferredCode { 888 class DeferredInlinedSmiAddReversed: public DeferredCode {
865 public: 889 public:
866 DeferredInlinedSmiAddReversed(CodeGenerator* generator, int value, 890 DeferredInlinedSmiAddReversed(CodeGenerator* generator, int value,
867 OverwriteMode overwrite_mode) : 891 OverwriteMode overwrite_mode) :
868 DeferredCode(generator), value_(value), overwrite_mode_(overwrite_mode) { 892 DeferredCode(generator), value_(value), overwrite_mode_(overwrite_mode) {
869 set_comment("[ DeferredInlinedSmiAddReversed"); 893 set_comment("[ DeferredInlinedSmiAddReversed");
870 } 894 }
871 895
872 virtual void Generate() { 896 virtual void Generate() {
897 // The argument is actually passed in eax.
898 enter()->Bind();
899 VirtualFrame::SpilledScope spilled_scope(generator());
873 // Undo the optimistic add operation and call the shared stub. 900 // Undo the optimistic add operation and call the shared stub.
874 Immediate immediate(Smi::FromInt(value_)); 901 Immediate immediate(Smi::FromInt(value_));
875 __ sub(Operand(eax), immediate); 902 __ sub(Operand(eax), immediate);
876 __ push(immediate); 903 generator()->frame()->EmitPush(immediate);
877 __ push(eax); 904 generator()->frame()->EmitPush(eax);
878 GenericBinaryOpStub igostub(Token::ADD, overwrite_mode_, SMI_CODE_INLINED); 905 GenericBinaryOpStub igostub(Token::ADD, overwrite_mode_, SMI_CODE_INLINED);
879 __ CallStub(&igostub); 906 generator()->frame()->CallStub(&igostub, 2);
907 // The result is actually returned in eax.
908 exit()->Jump();
880 } 909 }
881 910
882 private: 911 private:
883 int value_; 912 int value_;
884 OverwriteMode overwrite_mode_; 913 OverwriteMode overwrite_mode_;
885 }; 914 };
886 915
887 916
888 class DeferredInlinedSmiSub: public DeferredCode { 917 class DeferredInlinedSmiSub: public DeferredCode {
889 public: 918 public:
890 DeferredInlinedSmiSub(CodeGenerator* generator, int value, 919 DeferredInlinedSmiSub(CodeGenerator* generator, int value,
891 OverwriteMode overwrite_mode) : 920 OverwriteMode overwrite_mode) :
892 DeferredCode(generator), value_(value), overwrite_mode_(overwrite_mode) { 921 DeferredCode(generator), value_(value), overwrite_mode_(overwrite_mode) {
893 set_comment("[ DeferredInlinedSmiSub"); 922 set_comment("[ DeferredInlinedSmiSub");
894 } 923 }
895 924
896 virtual void Generate() { 925 virtual void Generate() {
926 // The argument is actually passed in eax.
927 enter()->Bind();
928 VirtualFrame::SpilledScope spilled_scope(generator());
897 // Undo the optimistic sub operation and call the shared stub. 929 // Undo the optimistic sub operation and call the shared stub.
898 Immediate immediate(Smi::FromInt(value_)); 930 Immediate immediate(Smi::FromInt(value_));
899 __ add(Operand(eax), immediate); 931 __ add(Operand(eax), immediate);
900 __ push(eax); 932 generator()->frame()->EmitPush(eax);
901 __ push(immediate); 933 generator()->frame()->EmitPush(immediate);
902 GenericBinaryOpStub igostub(Token::SUB, overwrite_mode_, SMI_CODE_INLINED); 934 GenericBinaryOpStub igostub(Token::SUB, overwrite_mode_, SMI_CODE_INLINED);
903 __ CallStub(&igostub); 935 generator()->frame()->CallStub(&igostub, 2);
936 // The result is actually returned in eax.
937 exit()->Jump();
904 } 938 }
905 939
906 private: 940 private:
907 int value_; 941 int value_;
908 OverwriteMode overwrite_mode_; 942 OverwriteMode overwrite_mode_;
909 }; 943 };
910 944
911 945
912 class DeferredInlinedSmiSubReversed: public DeferredCode { 946 class DeferredInlinedSmiSubReversed: public DeferredCode {
913 public: 947 public:
914 // tos_reg is used to save the TOS value before reversing the operands 948 // tos_reg is used to save the TOS value before reversing the operands
915 // eax will contain the immediate value after undoing the optimistic sub. 949 // eax will contain the immediate value after undoing the optimistic sub.
916 DeferredInlinedSmiSubReversed(CodeGenerator* generator, Register tos_reg, 950 DeferredInlinedSmiSubReversed(CodeGenerator* generator, Register tos_reg,
917 OverwriteMode overwrite_mode) : 951 OverwriteMode overwrite_mode) :
918 DeferredCode(generator), tos_reg_(tos_reg), 952 DeferredCode(generator), tos_reg_(tos_reg),
919 overwrite_mode_(overwrite_mode) { 953 overwrite_mode_(overwrite_mode) {
920 set_comment("[ DeferredInlinedSmiSubReversed"); 954 set_comment("[ DeferredInlinedSmiSubReversed");
921 } 955 }
922 956
923 virtual void Generate() { 957 virtual void Generate() {
958 // The arguments are actually passed in eax and tos_reg.
959 enter()->Bind();
960 VirtualFrame::SpilledScope spilled_scope(generator());
924 // Undo the optimistic sub operation and call the shared stub. 961 // Undo the optimistic sub operation and call the shared stub.
925 __ add(eax, Operand(tos_reg_)); 962 __ add(eax, Operand(tos_reg_));
926 __ push(eax); 963 generator()->frame()->EmitPush(eax);
927 __ push(tos_reg_); 964 generator()->frame()->EmitPush(tos_reg_);
928 GenericBinaryOpStub igostub(Token::SUB, overwrite_mode_, SMI_CODE_INLINED); 965 GenericBinaryOpStub igostub(Token::SUB, overwrite_mode_, SMI_CODE_INLINED);
929 __ CallStub(&igostub); 966 generator()->frame()->CallStub(&igostub, 2);
967 // The result is actually returned in eax.
968 exit()->Jump();
930 } 969 }
931 970
932 private: 971 private:
933 Register tos_reg_; 972 Register tos_reg_;
934 OverwriteMode overwrite_mode_; 973 OverwriteMode overwrite_mode_;
935 }; 974 };
936 975
937 976
938 void CodeGenerator::SmiOperation(Token::Value op, 977 void CodeGenerator::SmiOperation(Token::Value op,
939 StaticType* type, 978 StaticType* type,
(...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after
1178 // Test smi equality by pointer comparison. 1217 // Test smi equality by pointer comparison.
1179 is_smi.Bind(); 1218 is_smi.Bind();
1180 __ cmp(edx, Operand(eax)); 1219 __ cmp(edx, Operand(eax));
1181 // Fall through to |done|. 1220 // Fall through to |done|.
1182 1221
1183 done.Bind(); 1222 done.Bind();
1184 cc_reg_ = cc; 1223 cc_reg_ = cc;
1185 } 1224 }
1186 1225
1187 1226
1188 class SmiComparisonDeferred: public DeferredCode { 1227 class DeferredSmiComparison: public DeferredCode {
1189 public: 1228 public:
1190 SmiComparisonDeferred(CodeGenerator* generator, 1229 DeferredSmiComparison(CodeGenerator* generator,
1191 Condition cc, 1230 Condition cc,
1192 bool strict, 1231 bool strict,
1193 Register left_side, 1232 int int_value) :
1194 int right_side) :
1195 DeferredCode(generator), 1233 DeferredCode(generator),
1196 cc_(cc), 1234 cc_(cc),
1197 strict_(strict), 1235 strict_(strict),
1198 left_side_(left_side), 1236 int_value_(int_value) {
1199 right_side_(right_side) {
1200 set_comment("[ ComparisonDeferred"); 1237 set_comment("[ ComparisonDeferred");
1201 } 1238 }
1202 virtual void Generate(); 1239 virtual void Generate();
1203 1240
1204 private: 1241 private:
1205 Condition cc_; 1242 Condition cc_;
1206 bool strict_; 1243 bool strict_;
1207 Register left_side_; 1244 int int_value_;
1208 int right_side_;
1209 }; 1245 };
1210 1246
1211 1247
1212 void SmiComparisonDeferred::Generate() { 1248 void DeferredSmiComparison::Generate() {
1249 CodeGenerator* cgen = generator();
1213 CompareStub stub(cc_, strict_); 1250 CompareStub stub(cc_, strict_);
1251 Result argument(cgen);
1252 enter()->Bind(&argument);
1253
1214 // Setup parameters and call stub. 1254 // Setup parameters and call stub.
1215 if (!left_side_.is(edx)) { 1255 argument.ToRegister(edx);
1216 __ mov(edx, Operand(left_side_)); 1256 Result value = cgen->allocator()->Allocate(eax);
1217 } 1257 ASSERT(value.is_valid());
1218 __ Set(eax, Immediate(Smi::FromInt(right_side_))); 1258 __ Set(value.reg(), Immediate(Smi::FromInt(int_value_)));
1219 __ CallStub(&stub); 1259 Result result = cgen->frame()->CallStub(&stub, &argument, &value, 0);
1220 __ cmp(eax, 0); 1260 ASSERT(result.is_register());
1221 // "result" is returned in the flags. 1261 __ cmp(result.reg(), 0);
1262 result.Unuse();
1263 // The actual result is returned in the flags.
1264 exit()->Jump();
1222 } 1265 }
1223 1266
1224 1267
1225 void CodeGenerator::SmiComparison(Condition cc, 1268 void CodeGenerator::SmiComparison(Condition cc,
1226 Handle<Object> value, 1269 Handle<Object> value,
1227 bool strict) { 1270 bool strict) {
1228 // Strict only makes sense for equality comparisons. 1271 // Strict only makes sense for equality comparisons.
1229 ASSERT(!strict || cc == equal); 1272 ASSERT(!strict || cc == equal);
1230 1273
1231 int int_value = Smi::cast(*value)->value(); 1274 int int_value = Smi::cast(*value)->value();
1232 ASSERT(is_intn(int_value, kMaxSmiInlinedBits)); 1275 ASSERT(is_intn(int_value, kMaxSmiInlinedBits));
1233 1276
1277 DeferredSmiComparison* deferred =
1278 new DeferredSmiComparison(this, cc, strict, int_value);
1279
1234 Result comparee = frame_->Pop(); 1280 Result comparee = frame_->Pop();
1235 comparee.ToRegister(); 1281 comparee.ToRegister();
1236 Register reg = comparee.reg(); 1282 __ test(comparee.reg(), Immediate(kSmiTagMask));
1237 __ test(reg, Immediate(kSmiTagMask)); 1283 deferred->enter()->Branch(not_zero, &comparee, not_taken);
1238 SmiComparisonDeferred* deferred =
1239 new SmiComparisonDeferred(this, cc, strict, reg, int_value);
1240 deferred->enter()->Branch(not_zero, not_taken);
1241 // Test smi equality and comparison by signed int comparison. 1284 // Test smi equality and comparison by signed int comparison.
1242 __ cmp(Operand(reg), Immediate(value)); 1285 __ cmp(Operand(comparee.reg()), Immediate(value));
1243 comparee.Unuse(); 1286 comparee.Unuse();
1244 deferred->exit()->Bind(); 1287 deferred->exit()->Bind();
1245 cc_reg_ = cc; 1288 cc_reg_ = cc;
1246 } 1289 }
1247 1290
1248 1291
1249 class CallFunctionStub: public CodeStub { 1292 class CallFunctionStub: public CodeStub {
1250 public: 1293 public:
1251 explicit CallFunctionStub(int argc) : argc_(argc) { } 1294 explicit CallFunctionStub(int argc) : argc_(argc) { }
1252 1295
(...skipping 1418 matching lines...) Expand 10 before | Expand all | Expand 10 after
2671 int bits = reinterpret_cast<int>(*node->handle()); 2714 int bits = reinterpret_cast<int>(*node->handle());
2672 __ mov(temp.reg(), bits & 0x0000FFFF); 2715 __ mov(temp.reg(), bits & 0x0000FFFF);
2673 __ xor_(temp.reg(), bits & 0xFFFF0000); 2716 __ xor_(temp.reg(), bits & 0xFFFF0000);
2674 frame_->Push(&temp); 2717 frame_->Push(&temp);
2675 } else { 2718 } else {
2676 frame_->Push(node->handle()); 2719 frame_->Push(node->handle());
2677 } 2720 }
2678 } 2721 }
2679 2722
2680 2723
2681 class RegExpDeferred: public DeferredCode { 2724 class DeferredRegExpLiteral: public DeferredCode {
2682 public: 2725 public:
2683 RegExpDeferred(CodeGenerator* generator, RegExpLiteral* node) 2726 DeferredRegExpLiteral(CodeGenerator* generator, RegExpLiteral* node)
2684 : DeferredCode(generator), node_(node) { 2727 : DeferredCode(generator), node_(node) {
2685 set_comment("[ RegExpDeferred"); 2728 set_comment("[ RegExpDeferred");
2686 } 2729 }
2687 virtual void Generate(); 2730 virtual void Generate();
2688 private: 2731 private:
2689 RegExpLiteral* node_; 2732 RegExpLiteral* node_;
2690 }; 2733 };
2691 2734
2692 2735
2693 void RegExpDeferred::Generate() { 2736 void DeferredRegExpLiteral::Generate() {
2737 // The argument is actually passed in ecx.
2738 enter()->Bind();
2739 VirtualFrame::SpilledScope spilled_scope(generator());
2694 // If the entry is undefined we call the runtime system to compute the 2740 // If the entry is undefined we call the runtime system to compute the
2695 // literal. 2741 // literal.
2696 2742
2697 // Literal array (0). 2743 // Literal array (0).
2698 __ push(ecx); 2744 generator()->frame()->EmitPush(ecx);
2699 // Literal index (1). 2745 // Literal index (1).
2700 __ push(Immediate(Smi::FromInt(node_->literal_index()))); 2746 generator()->frame()->EmitPush(
2747 Immediate(Smi::FromInt(node_->literal_index())));
2701 // RegExp pattern (2). 2748 // RegExp pattern (2).
2702 __ push(Immediate(node_->pattern())); 2749 generator()->frame()->EmitPush(Immediate(node_->pattern()));
2703 // RegExp flags (3). 2750 // RegExp flags (3).
2704 __ push(Immediate(node_->flags())); 2751 generator()->frame()->EmitPush(Immediate(node_->flags()));
2705 __ CallRuntime(Runtime::kMaterializeRegExpLiteral, 4); 2752 generator()->frame()->CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
2706 __ mov(ebx, Operand(eax)); // "caller" expects result in ebx 2753 __ mov(ebx, Operand(eax)); // "caller" expects result in ebx
2754 // The result is actually returned in ebx.
2755 exit()->Jump();
2707 } 2756 }
2708 2757
2709 2758
2710 void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) { 2759 void CodeGenerator::VisitRegExpLiteral(RegExpLiteral* node) {
2711 VirtualFrame::SpilledScope spilled_scope(this); 2760 VirtualFrame::SpilledScope spilled_scope(this);
2712 Comment cmnt(masm_, "[ RegExp Literal"); 2761 Comment cmnt(masm_, "[ RegExp Literal");
2713 RegExpDeferred* deferred = new RegExpDeferred(this, node); 2762 DeferredRegExpLiteral* deferred = new DeferredRegExpLiteral(this, node);
2714 2763
2715 // Retrieve the literal array and check the allocated entry. 2764 // Retrieve the literal array and check the allocated entry.
2716 2765
2717 // Load the function of this activation. 2766 // Load the function of this activation.
2718 __ mov(ecx, frame_->Function()); 2767 __ mov(ecx, frame_->Function());
2719 2768
2720 // Load the literals array of the function. 2769 // Load the literals array of the function.
2721 __ mov(ecx, FieldOperand(ecx, JSFunction::kLiteralsOffset)); 2770 __ mov(ecx, FieldOperand(ecx, JSFunction::kLiteralsOffset));
2722 2771
2723 // Load the literal at the ast saved index. 2772 // Load the literal at the ast saved index.
2724 int literal_offset = 2773 int literal_offset =
2725 FixedArray::kHeaderSize + node->literal_index() * kPointerSize; 2774 FixedArray::kHeaderSize + node->literal_index() * kPointerSize;
2726 __ mov(ebx, FieldOperand(ecx, literal_offset)); 2775 __ mov(ebx, FieldOperand(ecx, literal_offset));
2727 2776
2728 // Check whether we need to materialize the RegExp object. 2777 // Check whether we need to materialize the RegExp object.
2729 // If so, jump to the deferred code. 2778 // If so, jump to the deferred code.
2730 __ cmp(ebx, Factory::undefined_value()); 2779 __ cmp(ebx, Factory::undefined_value());
2731 deferred->enter()->Branch(equal, not_taken); 2780 deferred->enter()->Branch(equal, not_taken);
2732 deferred->exit()->Bind(); 2781 deferred->exit()->Bind();
2733 2782
2734 // Push the literal. 2783 // Push the literal.
2735 frame_->EmitPush(ebx); 2784 frame_->EmitPush(ebx);
2736 } 2785 }
2737 2786
2738 2787
2739 // This deferred code stub will be used for creating the boilerplate 2788 // This deferred code stub will be used for creating the boilerplate
2740 // by calling Runtime_CreateObjectLiteral. 2789 // by calling Runtime_CreateObjectLiteral.
2741 // Each created boilerplate is stored in the JSFunction and they are 2790 // Each created boilerplate is stored in the JSFunction and they are
2742 // therefore context dependent. 2791 // therefore context dependent.
2743 class ObjectLiteralDeferred: public DeferredCode { 2792 class DeferredObjectLiteral: public DeferredCode {
2744 public: 2793 public:
2745 ObjectLiteralDeferred(CodeGenerator* generator, 2794 DeferredObjectLiteral(CodeGenerator* generator,
2746 ObjectLiteral* node) 2795 ObjectLiteral* node)
2747 : DeferredCode(generator), node_(node) { 2796 : DeferredCode(generator), node_(node) {
2748 set_comment("[ ObjectLiteralDeferred"); 2797 set_comment("[ ObjectLiteralDeferred");
2749 } 2798 }
2750 virtual void Generate(); 2799 virtual void Generate();
2751 private: 2800 private:
2752 ObjectLiteral* node_; 2801 ObjectLiteral* node_;
2753 }; 2802 };
2754 2803
2755 2804
2756 void ObjectLiteralDeferred::Generate() { 2805 void DeferredObjectLiteral::Generate() {
2806 // The argument is actually passed in ecx.
2807 enter()->Bind();
2808 VirtualFrame::SpilledScope spilled_scope(generator());
2757 // If the entry is undefined we call the runtime system to compute 2809 // If the entry is undefined we call the runtime system to compute
2758 // the literal. 2810 // the literal.
2759 2811
2760 // Literal array (0). 2812 // Literal array (0).
2761 __ push(ecx); 2813 generator()->frame()->EmitPush(ecx);
2762 // Literal index (1). 2814 // Literal index (1).
2763 __ push(Immediate(Smi::FromInt(node_->literal_index()))); 2815 generator()->frame()->EmitPush(
2816 Immediate(Smi::FromInt(node_->literal_index())));
2764 // Constant properties (2). 2817 // Constant properties (2).
2765 __ push(Immediate(node_->constant_properties())); 2818 generator()->frame()->EmitPush(Immediate(node_->constant_properties()));
2766 __ CallRuntime(Runtime::kCreateObjectLiteralBoilerplate, 3); 2819 generator()->frame()->CallRuntime(Runtime::kCreateObjectLiteralBoilerplate,
2820 3);
2767 __ mov(ebx, Operand(eax)); 2821 __ mov(ebx, Operand(eax));
2822 // The result is actually returned in ebx.
2823 exit()->Jump();
2768 } 2824 }
2769 2825
2770 2826
2771 void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) { 2827 void CodeGenerator::VisitObjectLiteral(ObjectLiteral* node) {
2772 VirtualFrame::SpilledScope spilled_scope(this); 2828 VirtualFrame::SpilledScope spilled_scope(this);
2773 Comment cmnt(masm_, "[ ObjectLiteral"); 2829 Comment cmnt(masm_, "[ ObjectLiteral");
2774 ObjectLiteralDeferred* deferred = new ObjectLiteralDeferred(this, node); 2830 DeferredObjectLiteral* deferred = new DeferredObjectLiteral(this, node);
2775 2831
2776 // Retrieve the literal array and check the allocated entry. 2832 // Retrieve the literal array and check the allocated entry.
2777 2833
2778 // Load the function of this activation. 2834 // Load the function of this activation.
2779 __ mov(ecx, frame_->Function()); 2835 __ mov(ecx, frame_->Function());
2780 2836
2781 // Load the literals array of the function. 2837 // Load the literals array of the function.
2782 __ mov(ecx, FieldOperand(ecx, JSFunction::kLiteralsOffset)); 2838 __ mov(ecx, FieldOperand(ecx, JSFunction::kLiteralsOffset));
2783 2839
2784 // Load the literal at the ast saved index. 2840 // Load the literal at the ast saved index.
(...skipping 833 matching lines...) Expand 10 before | Expand all | Expand 10 after
3618 break; 3674 break;
3619 } 3675 }
3620 3676
3621 default: 3677 default:
3622 UNREACHABLE(); 3678 UNREACHABLE();
3623 } 3679 }
3624 } 3680 }
3625 } 3681 }
3626 3682
3627 3683
3628 class CountOperationDeferred: public DeferredCode { 3684 class DeferredCountOperation: public DeferredCode {
3629 public: 3685 public:
3630 CountOperationDeferred(CodeGenerator* generator, 3686 DeferredCountOperation(CodeGenerator* generator,
3631 bool is_postfix, 3687 bool is_postfix,
3632 bool is_increment, 3688 bool is_increment,
3633 int result_offset) 3689 int result_offset)
3634 : DeferredCode(generator), 3690 : DeferredCode(generator),
3635 is_postfix_(is_postfix), 3691 is_postfix_(is_postfix),
3636 is_increment_(is_increment), 3692 is_increment_(is_increment),
3637 result_offset_(result_offset) { 3693 result_offset_(result_offset) {
3638 set_comment("[ CountOperationDeferred"); 3694 set_comment("[ CountOperationDeferred");
3639 } 3695 }
3640 3696
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
3693 PrintF("CounterOpStub (result_offset %d), (is_postfix %s)," 3749 PrintF("CounterOpStub (result_offset %d), (is_postfix %s),"
3694 " (is_increment %s)\n", 3750 " (is_increment %s)\n",
3695 result_offset_, 3751 result_offset_,
3696 is_postfix_ ? "true" : "false", 3752 is_postfix_ ? "true" : "false",
3697 is_increment_ ? "true" : "false"); 3753 is_increment_ ? "true" : "false");
3698 } 3754 }
3699 #endif 3755 #endif
3700 }; 3756 };
3701 3757
3702 3758
3703 void CountOperationDeferred::Generate() { 3759 void DeferredCountOperation::Generate() {
3760 // The argument is actually passed in eax.
3761 enter()->Bind();
3762 VirtualFrame::SpilledScope spilled_scope(generator());
3704 if (is_postfix_) { 3763 if (is_postfix_) {
3705 RevertToNumberStub to_number_stub(is_increment_); 3764 RevertToNumberStub to_number_stub(is_increment_);
3706 __ CallStub(&to_number_stub); 3765 generator()->frame()->CallStub(&to_number_stub, 0);
3707 } 3766 }
3708 CounterOpStub stub(result_offset_, is_postfix_, is_increment_); 3767 CounterOpStub stub(result_offset_, is_postfix_, is_increment_);
3709 __ CallStub(&stub); 3768 generator()->frame()->CallStub(&stub, 0);
3769 // The result is actually returned in eax.
3770 exit()->Jump();
3710 } 3771 }
3711 3772
3712 3773
3713 void CodeGenerator::VisitCountOperation(CountOperation* node) { 3774 void CodeGenerator::VisitCountOperation(CountOperation* node) {
3714 VirtualFrame::SpilledScope spilled_scope(this); 3775 VirtualFrame::SpilledScope spilled_scope(this);
3715 Comment cmnt(masm_, "[ CountOperation"); 3776 Comment cmnt(masm_, "[ CountOperation");
3716 3777
3717 bool is_postfix = node->is_postfix(); 3778 bool is_postfix = node->is_postfix();
3718 bool is_increment = node->op() == Token::INC; 3779 bool is_increment = node->op() == Token::INC;
3719 3780
3720 Variable* var = node->expression()->AsVariableProxy()->AsVariable(); 3781 Variable* var = node->expression()->AsVariableProxy()->AsVariable();
3721 bool is_const = (var != NULL && var->mode() == Variable::CONST); 3782 bool is_const = (var != NULL && var->mode() == Variable::CONST);
3722 3783
3723 // Postfix: Make room for the result. 3784 // Postfix: Make room for the result.
3724 if (is_postfix) { 3785 if (is_postfix) {
3725 frame_->EmitPush(Immediate(0)); 3786 frame_->EmitPush(Immediate(0));
3726 } 3787 }
3727 3788
3728 { Reference target(this, node->expression()); 3789 { Reference target(this, node->expression());
3729 if (target.is_illegal()) { 3790 if (target.is_illegal()) {
3730 // Spoof the virtual frame to have the expected height (one higher 3791 // Spoof the virtual frame to have the expected height (one higher
3731 // than on entry). 3792 // than on entry).
3732 if (!is_postfix) { 3793 if (!is_postfix) {
3733 frame_->EmitPush(Immediate(Smi::FromInt(0))); 3794 frame_->EmitPush(Immediate(Smi::FromInt(0)));
3734 } 3795 }
3735 return; 3796 return;
3736 } 3797 }
3737 target.GetValueAndSpill(NOT_INSIDE_TYPEOF); 3798 target.GetValueAndSpill(NOT_INSIDE_TYPEOF);
3738 3799
3739 CountOperationDeferred* deferred = 3800 DeferredCountOperation* deferred =
3740 new CountOperationDeferred(this, is_postfix, is_increment, 3801 new DeferredCountOperation(this, is_postfix, is_increment,
3741 target.size() * kPointerSize); 3802 target.size() * kPointerSize);
3742 3803
3743 frame_->EmitPop(eax); // Load TOS into eax for calculations below 3804 frame_->EmitPop(eax); // Load TOS into eax for calculations below
3744 3805
3745 // Postfix: Store the old value as the result. 3806 // Postfix: Store the old value as the result.
3746 if (is_postfix) { 3807 if (is_postfix) {
3747 __ mov(frame_->ElementAt(target.size()), eax); 3808 __ mov(frame_->ElementAt(target.size()), eax);
3748 } 3809 }
3749 3810
3750 // Perform optimistic increment/decrement. 3811 // Perform optimistic increment/decrement.
(...skipping 386 matching lines...) Expand 10 before | Expand all | Expand 10 after
4137 LoadAndSpill(right); 4198 LoadAndSpill(right);
4138 Comparison(cc, strict); 4199 Comparison(cc, strict);
4139 } 4200 }
4140 4201
4141 4202
4142 bool CodeGenerator::IsActualFunctionReturn(JumpTarget* target) { 4203 bool CodeGenerator::IsActualFunctionReturn(JumpTarget* target) {
4143 return (target == &function_return_ && !function_return_is_shadowed_); 4204 return (target == &function_return_ && !function_return_is_shadowed_);
4144 } 4205 }
4145 4206
4146 4207
4208 #ifdef DEBUG
4209 bool CodeGenerator::HasValidEntryRegisters() {
4210 return (allocator()->count(eax) - frame()->register_count(eax) == 0)
4211 && (allocator()->count(ebx) - frame()->register_count(ebx) == 0)
4212 && (allocator()->count(ecx) - frame()->register_count(ecx) == 0)
4213 && (allocator()->count(edx) - frame()->register_count(edx) == 0)
4214 && (allocator()->count(edi) - frame()->register_count(edi) == 0);
4215 }
4216 #endif
4217
4218
4147 #undef __ 4219 #undef __
4148 #define __ masm-> 4220 #define __ masm->
4149 4221
4150 Handle<String> Reference::GetName() { 4222 Handle<String> Reference::GetName() {
4151 ASSERT(type_ == NAMED); 4223 ASSERT(type_ == NAMED);
4152 Property* property = expression_->AsProperty(); 4224 Property* property = expression_->AsProperty();
4153 if (property == NULL) { 4225 if (property == NULL) {
4154 // Global variable reference treated as a named property reference. 4226 // Global variable reference treated as a named property reference.
4155 VariableProxy* proxy = expression_->AsVariableProxy(); 4227 VariableProxy* proxy = expression_->AsVariableProxy();
4156 ASSERT(proxy->AsVariable() != NULL); 4228 ASSERT(proxy->AsVariable() != NULL);
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
4201 } 4273 }
4202 frame->EmitPush(eax); // IC call leaves result in eax, push it out 4274 frame->EmitPush(eax); // IC call leaves result in eax, push it out
4203 break; 4275 break;
4204 } 4276 }
4205 4277
4206 case KEYED: { 4278 case KEYED: {
4207 // TODO(1241834): Make sure that this it is safe to ignore the 4279 // TODO(1241834): Make sure that this it is safe to ignore the
4208 // distinction between expressions in a typeof and not in a typeof. 4280 // distinction between expressions in a typeof and not in a typeof.
4209 VirtualFrame::SpilledScope spilled_scope(cgen_); 4281 VirtualFrame::SpilledScope spilled_scope(cgen_);
4210 Comment cmnt(masm, "[ Load from keyed Property"); 4282 Comment cmnt(masm, "[ Load from keyed Property");
4211 Property* property = expression_->AsProperty();
4212 ASSERT(property != NULL);
4213 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 4283 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
4214 4284
4215 Variable* var = expression_->AsVariableProxy()->AsVariable(); 4285 Variable* var = expression_->AsVariableProxy()->AsVariable();
4216 if (var != NULL) { 4286 if (var != NULL) {
4217 ASSERT(var->is_global()); 4287 ASSERT(var->is_global());
4218 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET_CONTEXT, 0); 4288 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET_CONTEXT, 0);
4219 } else { 4289 } else {
4220 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0); 4290 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
4221 } 4291 }
4222 frame->EmitPush(eax); // IC call leaves result in eax, push it out 4292 frame->EmitPush(eax); // IC call leaves result in eax, push it out
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
4254 // Setup the name register. 4324 // Setup the name register.
4255 __ mov(ecx, name); 4325 __ mov(ecx, name);
4256 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0); 4326 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
4257 frame->EmitPush(eax); // IC call leaves result in eax, push it out 4327 frame->EmitPush(eax); // IC call leaves result in eax, push it out
4258 break; 4328 break;
4259 } 4329 }
4260 4330
4261 case KEYED: { 4331 case KEYED: {
4262 VirtualFrame::SpilledScope spilled_scope(cgen_); 4332 VirtualFrame::SpilledScope spilled_scope(cgen_);
4263 Comment cmnt(masm, "[ Store to keyed Property"); 4333 Comment cmnt(masm, "[ Store to keyed Property");
4264 Property* property = expression_->AsProperty();
4265 ASSERT(property != NULL);
4266 // Call IC code. 4334 // Call IC code.
4267 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize)); 4335 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Initialize));
4268 // TODO(1222589): Make the IC grab the values from the stack. 4336 // TODO(1222589): Make the IC grab the values from the stack.
4269 frame->EmitPop(eax); 4337 frame->EmitPop(eax);
4270 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0); 4338 frame->CallCodeObject(ic, RelocInfo::CODE_TARGET, 0);
4271 frame->EmitPush(eax); // IC call leaves result in eax, push it out 4339 frame->EmitPush(eax); // IC call leaves result in eax, push it out
4272 break; 4340 break;
4273 } 4341 }
4274 4342
4275 default: 4343 default:
(...skipping 1376 matching lines...) Expand 10 before | Expand all | Expand 10 after
5652 5720
5653 // Slow-case: Go through the JavaScript implementation. 5721 // Slow-case: Go through the JavaScript implementation.
5654 __ bind(&slow); 5722 __ bind(&slow);
5655 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); 5723 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION);
5656 } 5724 }
5657 5725
5658 5726
5659 #undef __ 5727 #undef __
5660 5728
5661 } } // namespace v8::internal 5729 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/codegen-ia32.h ('k') | src/jump-target.h » ('j') | src/register-allocator-ia32.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698