| 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 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 182 } | 182 } |
| 183 | 183 |
| 184 if (scope_->num_heap_slots() > 0) { | 184 if (scope_->num_heap_slots() > 0) { |
| 185 Comment cmnt(masm_, "[ allocate local context"); | 185 Comment cmnt(masm_, "[ allocate local context"); |
| 186 // Allocate local context. | 186 // Allocate local context. |
| 187 // Get outer context and create a new context based on it. | 187 // Get outer context and create a new context based on it. |
| 188 frame_->PushFunction(); | 188 frame_->PushFunction(); |
| 189 Result context = frame_->CallRuntime(Runtime::kNewContext, 1); | 189 Result context = frame_->CallRuntime(Runtime::kNewContext, 1); |
| 190 | 190 |
| 191 if (kDebug) { | 191 if (kDebug) { |
| 192 frame_->SpillAll(); // Needed for breakpoint below. | |
| 193 JumpTarget verified_true(this); | 192 JumpTarget verified_true(this); |
| 194 // Verify eax and esi are the same in debug mode | 193 // Verify eax and esi are the same in debug mode |
| 195 __ cmp(context.reg(), Operand(esi)); | 194 __ cmp(context.reg(), Operand(esi)); |
| 196 context.Unuse(); | 195 context.Unuse(); |
| 197 verified_true.Branch(equal); | 196 verified_true.Branch(equal); |
| 197 frame_->SpillAll(); |
| 198 __ int3(); | 198 __ int3(); |
| 199 verified_true.Bind(); | 199 verified_true.Bind(); |
| 200 } | 200 } |
| 201 // Update context local. | 201 // Update context local. |
| 202 frame_->SaveContextRegister(); | 202 frame_->SaveContextRegister(); |
| 203 } | 203 } |
| 204 | 204 |
| 205 // TODO(1241774): Improve this code: | 205 // TODO(1241774): Improve this code: |
| 206 // 1) only needed if we have a context | 206 // 1) only needed if we have a context |
| 207 // 2) no need to recompute context ptr every single time | 207 // 2) no need to recompute context ptr every single time |
| (...skipping 640 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 848 | 848 |
| 849 private: | 849 private: |
| 850 Token::Value op_; | 850 Token::Value op_; |
| 851 int value_; | 851 int value_; |
| 852 OverwriteMode overwrite_mode_; | 852 OverwriteMode overwrite_mode_; |
| 853 }; | 853 }; |
| 854 | 854 |
| 855 | 855 |
| 856 class DeferredInlinedSmiAdd: public DeferredCode { | 856 class DeferredInlinedSmiAdd: public DeferredCode { |
| 857 public: | 857 public: |
| 858 DeferredInlinedSmiAdd(CodeGenerator* generator, int value, | 858 DeferredInlinedSmiAdd(CodeGenerator* generator, Smi* value, |
| 859 OverwriteMode overwrite_mode) : | 859 OverwriteMode overwrite_mode) : |
| 860 DeferredCode(generator), value_(value), overwrite_mode_(overwrite_mode) { | 860 DeferredCode(generator), value_(value), overwrite_mode_(overwrite_mode) { |
| 861 set_comment("[ DeferredInlinedSmiAdd"); | 861 set_comment("[ DeferredInlinedSmiAdd"); |
| 862 } | 862 } |
| 863 | 863 |
| 864 virtual void Generate() { | 864 virtual void Generate() { |
| 865 Result arg(generator()); | 865 Result arg(generator()); |
| 866 enter()->Bind(&arg); | 866 enter()->Bind(&arg); |
| 867 arg.ToRegister(); | 867 arg.ToRegister(); |
| 868 generator()->frame()->Spill(arg.reg()); | 868 generator()->frame()->Spill(arg.reg()); |
| 869 // Undo the optimistic add operation and call the shared stub. | 869 // Undo the optimistic add operation and call the shared stub. |
| 870 __ sub(Operand(arg.reg()), Immediate(Smi::FromInt(value_))); | 870 __ sub(Operand(arg.reg()), Immediate(value_)); |
| 871 generator()->frame()->Push(&arg); | 871 generator()->frame()->Push(&arg); |
| 872 generator()->frame()->Push(Smi::FromInt(value_)); | 872 generator()->frame()->Push(value_); |
| 873 GenericBinaryOpStub igostub(Token::ADD, overwrite_mode_, SMI_CODE_INLINED); | 873 GenericBinaryOpStub igostub(Token::ADD, overwrite_mode_, SMI_CODE_INLINED); |
| 874 Result result = generator()->frame()->CallStub(&igostub, 2); | 874 Result result = generator()->frame()->CallStub(&igostub, 2); |
| 875 exit()->Jump(&result); | 875 exit()->Jump(&result); |
| 876 } | 876 } |
| 877 | 877 |
| 878 private: | 878 private: |
| 879 int value_; | 879 Smi* value_; |
| 880 OverwriteMode overwrite_mode_; | 880 OverwriteMode overwrite_mode_; |
| 881 }; | 881 }; |
| 882 | 882 |
| 883 | 883 |
| 884 class DeferredInlinedSmiAddReversed: public DeferredCode { | 884 class DeferredInlinedSmiAddReversed: public DeferredCode { |
| 885 public: | 885 public: |
| 886 DeferredInlinedSmiAddReversed(CodeGenerator* generator, int value, | 886 DeferredInlinedSmiAddReversed(CodeGenerator* generator, Smi* value, |
| 887 OverwriteMode overwrite_mode) : | 887 OverwriteMode overwrite_mode) : |
| 888 DeferredCode(generator), value_(value), overwrite_mode_(overwrite_mode) { | 888 DeferredCode(generator), value_(value), overwrite_mode_(overwrite_mode) { |
| 889 set_comment("[ DeferredInlinedSmiAddReversed"); | 889 set_comment("[ DeferredInlinedSmiAddReversed"); |
| 890 } | 890 } |
| 891 | 891 |
| 892 virtual void Generate() { | 892 virtual void Generate() { |
| 893 Result arg(generator()); | 893 Result arg(generator()); |
| 894 enter()->Bind(&arg); | 894 enter()->Bind(&arg); |
| 895 arg.ToRegister(); | 895 arg.ToRegister(); |
| 896 generator()->frame()->Spill(arg.reg()); // Should not be needed. | 896 generator()->frame()->Spill(arg.reg()); |
| 897 // Undo the optimistic add operation and call the shared stub. | 897 // Undo the optimistic add operation and call the shared stub. |
| 898 Immediate immediate(Smi::FromInt(value_)); | 898 __ sub(Operand(arg.reg()), Immediate(value_)); |
| 899 __ sub(Operand(arg.reg()), immediate); | 899 generator()->frame()->Push(value_); |
| 900 generator()->frame()->Push(Smi::FromInt(value_)); | |
| 901 generator()->frame()->Push(&arg); | 900 generator()->frame()->Push(&arg); |
| 902 GenericBinaryOpStub igostub(Token::ADD, overwrite_mode_, SMI_CODE_INLINED); | 901 GenericBinaryOpStub igostub(Token::ADD, overwrite_mode_, SMI_CODE_INLINED); |
| 903 arg = generator()->frame()->CallStub(&igostub, 2); | 902 arg = generator()->frame()->CallStub(&igostub, 2); |
| 904 exit()->Jump(&arg); | 903 exit()->Jump(&arg); |
| 905 } | 904 } |
| 906 | 905 |
| 907 private: | 906 private: |
| 908 int value_; | 907 Smi* value_; |
| 909 OverwriteMode overwrite_mode_; | 908 OverwriteMode overwrite_mode_; |
| 910 }; | 909 }; |
| 911 | 910 |
| 912 | 911 |
| 913 class DeferredInlinedSmiSub: public DeferredCode { | 912 class DeferredInlinedSmiSub: public DeferredCode { |
| 914 public: | 913 public: |
| 915 DeferredInlinedSmiSub(CodeGenerator* generator, int value, | 914 DeferredInlinedSmiSub(CodeGenerator* generator, |
| 915 Smi* value, |
| 916 OverwriteMode overwrite_mode) : | 916 OverwriteMode overwrite_mode) : |
| 917 DeferredCode(generator), value_(value), overwrite_mode_(overwrite_mode) { | 917 DeferredCode(generator), value_(value), overwrite_mode_(overwrite_mode) { |
| 918 set_comment("[ DeferredInlinedSmiSub"); | 918 set_comment("[ DeferredInlinedSmiSub"); |
| 919 } | 919 } |
| 920 | 920 |
| 921 virtual void Generate() { | 921 virtual void Generate() { |
| 922 // The argument is actually passed in eax. | 922 Result argument(generator()); |
| 923 enter()->Bind(); | 923 enter()->Bind(&argument); |
| 924 VirtualFrame::SpilledScope spilled_scope(generator()); | 924 argument.ToRegister(); |
| 925 generator()->frame()->Spill(argument.reg()); |
| 925 // Undo the optimistic sub operation and call the shared stub. | 926 // Undo the optimistic sub operation and call the shared stub. |
| 926 Immediate immediate(Smi::FromInt(value_)); | 927 __ add(Operand(argument.reg()), Immediate(value_)); |
| 927 __ add(Operand(eax), immediate); | 928 generator()->frame()->Push(&argument); |
| 928 generator()->frame()->EmitPush(eax); | 929 generator()->frame()->Push(value_); |
| 929 generator()->frame()->EmitPush(immediate); | |
| 930 GenericBinaryOpStub igostub(Token::SUB, overwrite_mode_, SMI_CODE_INLINED); | 930 GenericBinaryOpStub igostub(Token::SUB, overwrite_mode_, SMI_CODE_INLINED); |
| 931 generator()->frame()->CallStub(&igostub, 2); | 931 Result answer = generator()->frame()->CallStub(&igostub, 2); |
| 932 // The result is actually returned in eax. | 932 // The result is actually returned in eax. |
| 933 exit()->Jump(); | 933 exit()->Jump(&answer); |
| 934 } | 934 } |
| 935 | 935 |
| 936 private: | 936 private: |
| 937 int value_; | 937 Smi* value_; |
| 938 OverwriteMode overwrite_mode_; | 938 OverwriteMode overwrite_mode_; |
| 939 }; | 939 }; |
| 940 | 940 |
| 941 | 941 |
| 942 class DeferredInlinedSmiSubReversed: public DeferredCode { | 942 class DeferredInlinedSmiSubReversed: public DeferredCode { |
| 943 public: | 943 public: |
| 944 // tos_reg is used to save the TOS value before reversing the operands | 944 DeferredInlinedSmiSubReversed(CodeGenerator* generator, |
| 945 // eax will contain the immediate value after undoing the optimistic sub. | 945 Smi* value, |
| 946 DeferredInlinedSmiSubReversed(CodeGenerator* generator, Register tos_reg, | |
| 947 OverwriteMode overwrite_mode) : | 946 OverwriteMode overwrite_mode) : |
| 948 DeferredCode(generator), tos_reg_(tos_reg), | 947 DeferredCode(generator), value_(value), |
| 949 overwrite_mode_(overwrite_mode) { | 948 overwrite_mode_(overwrite_mode) { |
| 950 set_comment("[ DeferredInlinedSmiSubReversed"); | 949 set_comment("[ DeferredInlinedSmiSubReversed"); |
| 951 } | 950 } |
| 952 | 951 |
| 953 virtual void Generate() { | 952 virtual void Generate() { |
| 954 // The arguments are actually passed in eax and tos_reg. | 953 Result rhs(generator()); |
| 955 enter()->Bind(); | 954 enter()->Bind(&rhs); |
| 956 VirtualFrame::SpilledScope spilled_scope(generator()); | 955 generator()->frame()->Push(value_); |
| 957 // Undo the optimistic sub operation and call the shared stub. | 956 generator()->frame()->Push(&rhs); |
| 958 __ add(eax, Operand(tos_reg_)); | |
| 959 generator()->frame()->EmitPush(eax); | |
| 960 generator()->frame()->EmitPush(tos_reg_); | |
| 961 GenericBinaryOpStub igostub(Token::SUB, overwrite_mode_, SMI_CODE_INLINED); | 957 GenericBinaryOpStub igostub(Token::SUB, overwrite_mode_, SMI_CODE_INLINED); |
| 962 generator()->frame()->CallStub(&igostub, 2); | 958 Result answer = generator()->frame()->CallStub(&igostub, 2); |
| 963 // The result is actually returned in eax. | 959 exit()->Jump(&answer); |
| 964 exit()->Jump(); | |
| 965 } | 960 } |
| 966 | 961 |
| 967 private: | 962 private: |
| 968 Register tos_reg_; | 963 Smi* value_; |
| 969 OverwriteMode overwrite_mode_; | 964 OverwriteMode overwrite_mode_; |
| 970 }; | 965 }; |
| 971 | 966 |
| 972 | 967 |
| 973 void CodeGenerator::SmiOperation(Token::Value op, | 968 void CodeGenerator::SmiOperation(Token::Value op, |
| 974 StaticType* type, | 969 StaticType* type, |
| 975 Handle<Object> value, | 970 Handle<Object> value, |
| 976 bool reversed, | 971 bool reversed, |
| 977 OverwriteMode overwrite_mode) { | 972 OverwriteMode overwrite_mode) { |
| 978 // NOTE: This is an attempt to inline (a bit) more of the code for | 973 // NOTE: This is an attempt to inline (a bit) more of the code for |
| 979 // some possible smi operations (like + and -) when (at least) one | 974 // some possible smi operations (like + and -) when (at least) one |
| 980 // of the operands is a literal smi. With this optimization, the | 975 // of the operands is a literal smi. With this optimization, the |
| 981 // performance of the system is increased by ~15%, and the generated | 976 // performance of the system is increased by ~15%, and the generated |
| 982 // code size is increased by ~1% (measured on a combination of | 977 // code size is increased by ~1% (measured on a combination of |
| 983 // different benchmarks). | 978 // different benchmarks). |
| 984 | 979 |
| 985 // TODO(1217802): Optimize some special cases of operations | 980 // TODO(1217802): Optimize some special cases of operations |
| 986 // involving a smi literal (multiply by 2, shift by 0, etc.). | 981 // involving a smi literal (multiply by 2, shift by 0, etc.). |
| 987 VirtualFrame::SpilledScope spilled_scope(this); | |
| 988 | 982 |
| 989 // Get the literal value. | 983 // Get the literal value. |
| 990 int int_value = Smi::cast(*value)->value(); | 984 Smi* smi_value = Smi::cast(*value); |
| 985 int int_value = smi_value->value(); |
| 991 ASSERT(is_intn(int_value, kMaxSmiInlinedBits)); | 986 ASSERT(is_intn(int_value, kMaxSmiInlinedBits)); |
| 992 | 987 |
| 993 switch (op) { | 988 switch (op) { |
| 994 case Token::ADD: { | 989 case Token::ADD: { |
| 995 DeferredCode* deferred = NULL; | 990 DeferredCode* deferred = NULL; |
| 996 if (!reversed) { | 991 if (!reversed) { |
| 997 deferred = new DeferredInlinedSmiAdd(this, int_value, overwrite_mode); | 992 deferred = new DeferredInlinedSmiAdd(this, smi_value, overwrite_mode); |
| 998 } else { | 993 } else { |
| 999 deferred = new DeferredInlinedSmiAddReversed(this, int_value, | 994 deferred = new DeferredInlinedSmiAddReversed(this, smi_value, |
| 1000 overwrite_mode); | 995 overwrite_mode); |
| 1001 } | 996 } |
| 1002 Result operand = frame_->Pop(); | 997 Result operand = frame_->Pop(); |
| 1003 operand.ToRegister(); | 998 operand.ToRegister(); |
| 1004 frame_->Spill(operand.reg()); | 999 frame_->Spill(operand.reg()); |
| 1005 __ add(Operand(operand.reg()), Immediate(value)); | 1000 __ add(Operand(operand.reg()), Immediate(value)); |
| 1006 deferred->enter()->Branch(overflow, &operand, not_taken); | 1001 deferred->enter()->Branch(overflow, &operand, not_taken); |
| 1007 __ test(Operand(operand.reg()), Immediate(kSmiTagMask)); | 1002 __ test(Operand(operand.reg()), Immediate(kSmiTagMask)); |
| 1008 deferred->enter()->Branch(not_zero, &operand, not_taken); | 1003 deferred->enter()->Branch(not_zero, &operand, not_taken); |
| 1009 deferred->exit()->Bind(&operand); | 1004 deferred->exit()->Bind(&operand); |
| 1010 frame_->Push(&operand); | 1005 frame_->Push(&operand); |
| 1011 break; | 1006 break; |
| 1012 } | 1007 } |
| 1013 | 1008 |
| 1014 case Token::SUB: { | 1009 case Token::SUB: { |
| 1015 DeferredCode* deferred = NULL; | 1010 DeferredCode* deferred = NULL; |
| 1016 frame_->EmitPop(eax); | 1011 Result operand = frame_->Pop(); |
| 1012 Result answer(this); // Only allocated a new register if reversed. |
| 1017 if (!reversed) { | 1013 if (!reversed) { |
| 1018 deferred = new DeferredInlinedSmiSub(this, int_value, overwrite_mode); | 1014 operand.ToRegister(); |
| 1019 __ sub(Operand(eax), Immediate(value)); | 1015 frame_->Spill(operand.reg()); |
| 1016 deferred = new DeferredInlinedSmiSub(this, |
| 1017 smi_value, |
| 1018 overwrite_mode); |
| 1019 __ sub(Operand(operand.reg()), Immediate(value)); |
| 1020 answer = operand; |
| 1020 } else { | 1021 } else { |
| 1021 deferred = new DeferredInlinedSmiSubReversed(this, edx, overwrite_mode); | 1022 answer = allocator()->Allocate(); |
| 1022 __ mov(edx, Operand(eax)); | 1023 ASSERT(answer.is_valid()); |
| 1023 __ mov(eax, Immediate(value)); | 1024 deferred = new DeferredInlinedSmiSubReversed(this, |
| 1024 __ sub(eax, Operand(edx)); | 1025 smi_value, |
| 1026 overwrite_mode); |
| 1027 __ mov(answer.reg(), Immediate(value)); |
| 1028 if (operand.is_register()) { |
| 1029 __ sub(answer.reg(), Operand(operand.reg())); |
| 1030 } else { |
| 1031 ASSERT(operand.is_constant()); |
| 1032 __ sub(Operand(answer.reg()), Immediate(operand.handle())); |
| 1033 } |
| 1025 } | 1034 } |
| 1026 deferred->enter()->Branch(overflow, not_taken); | 1035 deferred->enter()->Branch(overflow, &operand, not_taken); |
| 1027 __ test(eax, Immediate(kSmiTagMask)); | 1036 __ test(answer.reg(), Immediate(kSmiTagMask)); |
| 1028 deferred->enter()->Branch(not_zero, not_taken); | 1037 deferred->enter()->Branch(not_zero, &operand, not_taken); |
| 1029 deferred->exit()->Bind(); | 1038 operand.Unuse(); |
| 1030 frame_->EmitPush(eax); | 1039 deferred->exit()->Bind(&answer); |
| 1040 frame_->Push(&answer); |
| 1031 break; | 1041 break; |
| 1032 } | 1042 } |
| 1033 | 1043 |
| 1034 case Token::SAR: { | 1044 case Token::SAR: { |
| 1035 if (reversed) { | 1045 if (reversed) { |
| 1036 frame_->EmitPop(eax); | 1046 Result top = frame_->Pop(); |
| 1037 frame_->EmitPush(Immediate(value)); | 1047 frame_->Push(value); |
| 1038 frame_->EmitPush(eax); | 1048 frame_->Push(&top); |
| 1039 GenericBinaryOperation(op, type, overwrite_mode); | 1049 GenericBinaryOperation(op, type, overwrite_mode); |
| 1040 } else { | 1050 } else { |
| 1051 VirtualFrame::SpilledScope spilled_scope(this); |
| 1041 int shift_value = int_value & 0x1f; // only least significant 5 bits | 1052 int shift_value = int_value & 0x1f; // only least significant 5 bits |
| 1042 DeferredCode* deferred = | 1053 DeferredCode* deferred = |
| 1043 new DeferredInlinedSmiOperation(this, Token::SAR, shift_value, | 1054 new DeferredInlinedSmiOperation(this, Token::SAR, shift_value, |
| 1044 overwrite_mode); | 1055 overwrite_mode); |
| 1045 frame_->EmitPop(eax); | 1056 frame_->EmitPop(eax); |
| 1046 __ test(eax, Immediate(kSmiTagMask)); | 1057 __ test(eax, Immediate(kSmiTagMask)); |
| 1047 deferred->enter()->Branch(not_zero, not_taken); | 1058 deferred->enter()->Branch(not_zero, not_taken); |
| 1048 __ sar(eax, shift_value); | 1059 __ sar(eax, shift_value); |
| 1049 __ and_(eax, ~kSmiTagMask); | 1060 __ and_(eax, ~kSmiTagMask); |
| 1050 deferred->exit()->Bind(); | 1061 deferred->exit()->Bind(); |
| 1051 frame_->EmitPush(eax); | 1062 frame_->EmitPush(eax); |
| 1052 } | 1063 } |
| 1053 break; | 1064 break; |
| 1054 } | 1065 } |
| 1055 | 1066 |
| 1056 case Token::SHR: { | 1067 case Token::SHR: { |
| 1057 if (reversed) { | 1068 if (reversed) { |
| 1058 frame_->EmitPop(eax); | 1069 Result top = frame_->Pop(); |
| 1059 frame_->EmitPush(Immediate(value)); | 1070 frame_->Push(value); |
| 1060 frame_->EmitPush(eax); | 1071 frame_->Push(&top); |
| 1061 GenericBinaryOperation(op, type, overwrite_mode); | 1072 GenericBinaryOperation(op, type, overwrite_mode); |
| 1062 } else { | 1073 } else { |
| 1074 VirtualFrame::SpilledScope spilled_scope(this); |
| 1063 int shift_value = int_value & 0x1f; // only least significant 5 bits | 1075 int shift_value = int_value & 0x1f; // only least significant 5 bits |
| 1064 DeferredCode* deferred = | 1076 DeferredCode* deferred = |
| 1065 new DeferredInlinedSmiOperation(this, Token::SHR, shift_value, | 1077 new DeferredInlinedSmiOperation(this, Token::SHR, shift_value, |
| 1066 overwrite_mode); | 1078 overwrite_mode); |
| 1067 frame_->EmitPop(eax); | 1079 frame_->EmitPop(eax); |
| 1068 __ test(eax, Immediate(kSmiTagMask)); | 1080 __ test(eax, Immediate(kSmiTagMask)); |
| 1069 __ mov(ebx, Operand(eax)); | 1081 __ mov(ebx, Operand(eax)); |
| 1070 deferred->enter()->Branch(not_zero, not_taken); | 1082 deferred->enter()->Branch(not_zero, not_taken); |
| 1071 __ sar(ebx, kSmiTagSize); | 1083 __ sar(ebx, kSmiTagSize); |
| 1072 __ shr(ebx, shift_value); | 1084 __ shr(ebx, shift_value); |
| 1073 __ test(ebx, Immediate(0xc0000000)); | 1085 __ test(ebx, Immediate(0xc0000000)); |
| 1074 deferred->enter()->Branch(not_zero, not_taken); | 1086 deferred->enter()->Branch(not_zero, not_taken); |
| 1075 // tag result and store it in TOS (eax) | 1087 // tag result and store it in TOS (eax) |
| 1076 ASSERT(kSmiTagSize == times_2); // adjust code if not the case | 1088 ASSERT(kSmiTagSize == times_2); // adjust code if not the case |
| 1077 __ lea(eax, Operand(ebx, ebx, times_1, kSmiTag)); | 1089 __ lea(eax, Operand(ebx, ebx, times_1, kSmiTag)); |
| 1078 deferred->exit()->Bind(); | 1090 deferred->exit()->Bind(); |
| 1079 frame_->EmitPush(eax); | 1091 frame_->EmitPush(eax); |
| 1080 } | 1092 } |
| 1081 break; | 1093 break; |
| 1082 } | 1094 } |
| 1083 | 1095 |
| 1084 case Token::SHL: { | 1096 case Token::SHL: { |
| 1097 VirtualFrame::SpilledScope spilled_scope(this); |
| 1085 if (reversed) { | 1098 if (reversed) { |
| 1086 frame_->EmitPop(eax); | 1099 frame_->EmitPop(eax); |
| 1087 frame_->EmitPush(Immediate(value)); | 1100 frame_->EmitPush(Immediate(value)); |
| 1088 frame_->EmitPush(eax); | 1101 frame_->EmitPush(eax); |
| 1089 GenericBinaryOperation(op, type, overwrite_mode); | 1102 GenericBinaryOperation(op, type, overwrite_mode); |
| 1090 } else { | 1103 } else { |
| 1091 int shift_value = int_value & 0x1f; // only least significant 5 bits | 1104 int shift_value = int_value & 0x1f; // only least significant 5 bits |
| 1092 DeferredCode* deferred = | 1105 DeferredCode* deferred = |
| 1093 new DeferredInlinedSmiOperation(this, Token::SHL, shift_value, | 1106 new DeferredInlinedSmiOperation(this, Token::SHL, shift_value, |
| 1094 overwrite_mode); | 1107 overwrite_mode); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1106 __ lea(eax, Operand(ebx, ebx, times_1, kSmiTag)); | 1119 __ lea(eax, Operand(ebx, ebx, times_1, kSmiTag)); |
| 1107 deferred->exit()->Bind(); | 1120 deferred->exit()->Bind(); |
| 1108 frame_->EmitPush(eax); | 1121 frame_->EmitPush(eax); |
| 1109 } | 1122 } |
| 1110 break; | 1123 break; |
| 1111 } | 1124 } |
| 1112 | 1125 |
| 1113 case Token::BIT_OR: | 1126 case Token::BIT_OR: |
| 1114 case Token::BIT_XOR: | 1127 case Token::BIT_XOR: |
| 1115 case Token::BIT_AND: { | 1128 case Token::BIT_AND: { |
| 1129 VirtualFrame::SpilledScope spilled_scope(this); |
| 1116 DeferredCode* deferred = NULL; | 1130 DeferredCode* deferred = NULL; |
| 1117 if (!reversed) { | 1131 if (!reversed) { |
| 1118 deferred = new DeferredInlinedSmiOperation(this, op, int_value, | 1132 deferred = new DeferredInlinedSmiOperation(this, op, int_value, |
| 1119 overwrite_mode); | 1133 overwrite_mode); |
| 1120 } else { | 1134 } else { |
| 1121 deferred = new DeferredInlinedSmiOperationReversed(this, op, int_value, | 1135 deferred = new DeferredInlinedSmiOperationReversed(this, op, int_value, |
| 1122 overwrite_mode); | 1136 overwrite_mode); |
| 1123 } | 1137 } |
| 1124 frame_->EmitPop(eax); | 1138 frame_->EmitPop(eax); |
| 1125 __ test(eax, Immediate(kSmiTagMask)); | 1139 __ test(eax, Immediate(kSmiTagMask)); |
| 1126 deferred->enter()->Branch(not_zero, not_taken); | 1140 deferred->enter()->Branch(not_zero, not_taken); |
| 1127 if (op == Token::BIT_AND) { | 1141 if (op == Token::BIT_AND) { |
| 1128 __ and_(Operand(eax), Immediate(value)); | 1142 __ and_(Operand(eax), Immediate(value)); |
| 1129 } else if (op == Token::BIT_XOR) { | 1143 } else if (op == Token::BIT_XOR) { |
| 1130 __ xor_(Operand(eax), Immediate(value)); | 1144 __ xor_(Operand(eax), Immediate(value)); |
| 1131 } else { | 1145 } else { |
| 1132 ASSERT(op == Token::BIT_OR); | 1146 ASSERT(op == Token::BIT_OR); |
| 1133 __ or_(Operand(eax), Immediate(value)); | 1147 __ or_(Operand(eax), Immediate(value)); |
| 1134 } | 1148 } |
| 1135 deferred->exit()->Bind(); | 1149 deferred->exit()->Bind(); |
| 1136 frame_->EmitPush(eax); | 1150 frame_->EmitPush(eax); |
| 1137 break; | 1151 break; |
| 1138 } | 1152 } |
| 1139 | 1153 |
| 1140 default: { | 1154 default: { |
| 1141 if (!reversed) { | 1155 if (!reversed) { |
| 1142 frame_->EmitPush(Immediate(value)); | 1156 frame_->Push(value); |
| 1143 } else { | 1157 } else { |
| 1144 frame_->EmitPop(eax); | 1158 Result top = frame_->Pop(); |
| 1145 frame_->EmitPush(Immediate(value)); | 1159 frame_->Push(value); |
| 1146 frame_->EmitPush(eax); | 1160 frame_->Push(&top); |
| 1147 } | 1161 } |
| 1148 GenericBinaryOperation(op, type, overwrite_mode); | 1162 GenericBinaryOperation(op, type, overwrite_mode); |
| 1149 break; | 1163 break; |
| 1150 } | 1164 } |
| 1151 } | 1165 } |
| 1152 } | 1166 } |
| 1153 | 1167 |
| 1154 | 1168 |
| 1155 class CompareStub: public CodeStub { | 1169 class CompareStub: public CodeStub { |
| 1156 public: | 1170 public: |
| (...skipping 4969 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6126 | 6140 |
| 6127 // Slow-case: Go through the JavaScript implementation. | 6141 // Slow-case: Go through the JavaScript implementation. |
| 6128 __ bind(&slow); | 6142 __ bind(&slow); |
| 6129 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); | 6143 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); |
| 6130 } | 6144 } |
| 6131 | 6145 |
| 6132 | 6146 |
| 6133 #undef __ | 6147 #undef __ |
| 6134 | 6148 |
| 6135 } } // namespace v8::internal | 6149 } } // namespace v8::internal |
| OLD | NEW |