| 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 695 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |