Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 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, |
|
Kevin Millikin (Chromium)
2009/01/23 08:49:25
While you're changing this code, you could clean i
William Hesse
2012/05/07 09:35:10
Done.
| |
| 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() { |
|
Kevin Millikin (Chromium)
2009/01/23 08:49:25
I also don't care for these inline-looking Generat
William Hesse
2012/05/07 09:35:10
Done.
| |
| 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. |
|
Kevin Millikin (Chromium)
2009/01/23 08:49:25
Remove this comment.
William Hesse
2012/05/07 09:35:10
Done.
| |
| 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 // tos_reg is used to save the TOS value before reversing the operands |
| 945 // eax will contain the immediate value after undoing the optimistic sub. | 945 // eax will contain the immediate value after undoing the optimistic sub. |
| 946 DeferredInlinedSmiSubReversed(CodeGenerator* generator, Register tos_reg, | 946 DeferredInlinedSmiSubReversed(CodeGenerator* generator, |
| 947 Smi* value, | |
| 947 OverwriteMode overwrite_mode) : | 948 OverwriteMode overwrite_mode) : |
| 948 DeferredCode(generator), tos_reg_(tos_reg), | 949 DeferredCode(generator), value_(value), |
| 949 overwrite_mode_(overwrite_mode) { | 950 overwrite_mode_(overwrite_mode) { |
| 950 set_comment("[ DeferredInlinedSmiSubReversed"); | 951 set_comment("[ DeferredInlinedSmiSubReversed"); |
| 951 } | 952 } |
| 952 | 953 |
| 953 virtual void Generate() { | 954 virtual void Generate() { |
| 954 // The arguments are actually passed in eax and tos_reg. | 955 Result argument(generator()); |
| 955 enter()->Bind(); | 956 enter()->Bind(&argument); // argument contains lhs - rhs. lhs is value. |
|
Kevin Millikin (Chromium)
2009/01/23 08:49:25
Try to make comments look like English sentences.
| |
| 956 VirtualFrame::SpilledScope spilled_scope(generator()); | 957 argument.ToRegister(); |
| 958 generator()->frame()->Spill(argument.reg()); | |
|
Kevin Millikin (Chromium)
2009/01/23 08:49:25
I'm confused by this spill. Since argument is not
| |
| 957 // Undo the optimistic sub operation and call the shared stub. | 959 // Undo the optimistic sub operation and call the shared stub. |
| 958 __ add(eax, Operand(tos_reg_)); | 960 Result temp = generator()->allocator()->Allocate(); |
| 959 generator()->frame()->EmitPush(eax); | 961 ASSERT(temp.is_valid()); |
| 960 generator()->frame()->EmitPush(tos_reg_); | 962 __ mov(temp.reg(), Immediate(value_)); |
| 963 __ sub(temp.reg(), Operand(argument.reg())); // lhs - (lhs - rhs) gives us r hs. | |
|
Kevin Millikin (Chromium)
2009/01/23 08:49:25
Line seems too long. There should be two spaces b
| |
| 964 argument.Unuse(); | |
| 965 generator()->frame()->Push(value_); | |
| 966 generator()->frame()->Push(&temp); | |
| 961 GenericBinaryOpStub igostub(Token::SUB, overwrite_mode_, SMI_CODE_INLINED); | 967 GenericBinaryOpStub igostub(Token::SUB, overwrite_mode_, SMI_CODE_INLINED); |
| 962 generator()->frame()->CallStub(&igostub, 2); | 968 Result answer = generator()->frame()->CallStub(&igostub, 2); |
| 963 // The result is actually returned in eax. | 969 exit()->Jump(&answer); |
| 964 exit()->Jump(); | |
| 965 } | 970 } |
| 966 | 971 |
| 967 private: | 972 private: |
| 968 Register tos_reg_; | 973 Smi* value_; |
| 969 OverwriteMode overwrite_mode_; | 974 OverwriteMode overwrite_mode_; |
| 970 }; | 975 }; |
| 971 | 976 |
| 972 | 977 |
| 973 void CodeGenerator::SmiOperation(Token::Value op, | 978 void CodeGenerator::SmiOperation(Token::Value op, |
| 974 StaticType* type, | 979 StaticType* type, |
| 975 Handle<Object> value, | 980 Handle<Object> value, |
| 976 bool reversed, | 981 bool reversed, |
| 977 OverwriteMode overwrite_mode) { | 982 OverwriteMode overwrite_mode) { |
| 978 // NOTE: This is an attempt to inline (a bit) more of the code for | 983 // 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 | 984 // some possible smi operations (like + and -) when (at least) one |
| 980 // of the operands is a literal smi. With this optimization, the | 985 // of the operands is a literal smi. With this optimization, the |
| 981 // performance of the system is increased by ~15%, and the generated | 986 // performance of the system is increased by ~15%, and the generated |
| 982 // code size is increased by ~1% (measured on a combination of | 987 // code size is increased by ~1% (measured on a combination of |
| 983 // different benchmarks). | 988 // different benchmarks). |
| 984 | 989 |
| 985 // TODO(1217802): Optimize some special cases of operations | 990 // TODO(1217802): Optimize some special cases of operations |
| 986 // involving a smi literal (multiply by 2, shift by 0, etc.). | 991 // involving a smi literal (multiply by 2, shift by 0, etc.). |
| 987 VirtualFrame::SpilledScope spilled_scope(this); | |
| 988 | 992 |
| 989 // Get the literal value. | 993 // Get the literal value. |
| 990 int int_value = Smi::cast(*value)->value(); | 994 Smi* smi_value = Smi::cast(*value); |
| 995 int int_value = smi_value->value(); | |
| 991 ASSERT(is_intn(int_value, kMaxSmiInlinedBits)); | 996 ASSERT(is_intn(int_value, kMaxSmiInlinedBits)); |
| 992 | 997 |
| 993 switch (op) { | 998 switch (op) { |
| 994 case Token::ADD: { | 999 case Token::ADD: { |
| 995 DeferredCode* deferred = NULL; | 1000 DeferredCode* deferred = NULL; |
| 996 if (!reversed) { | 1001 if (!reversed) { |
|
Kevin Millikin (Chromium)
2009/01/23 08:49:25
Since this is a two-armed if anyway, it might read
William Hesse
2012/05/07 09:35:10
Done.
| |
| 997 deferred = new DeferredInlinedSmiAdd(this, int_value, overwrite_mode); | 1002 deferred = new DeferredInlinedSmiAdd(this, smi_value, overwrite_mode); |
| 998 } else { | 1003 } else { |
| 999 deferred = new DeferredInlinedSmiAddReversed(this, int_value, | 1004 deferred = new DeferredInlinedSmiAddReversed(this, smi_value, |
| 1000 overwrite_mode); | 1005 overwrite_mode); |
| 1001 } | 1006 } |
| 1002 Result operand = frame_->Pop(); | 1007 Result operand = frame_->Pop(); |
| 1003 operand.ToRegister(); | 1008 operand.ToRegister(); |
| 1004 frame_->Spill(operand.reg()); | 1009 frame_->Spill(operand.reg()); |
| 1005 __ add(Operand(operand.reg()), Immediate(value)); | 1010 __ add(Operand(operand.reg()), Immediate(value)); |
| 1006 deferred->enter()->Branch(overflow, &operand, not_taken); | 1011 deferred->enter()->Branch(overflow, &operand, not_taken); |
| 1007 __ test(Operand(operand.reg()), Immediate(kSmiTagMask)); | 1012 __ test(Operand(operand.reg()), Immediate(kSmiTagMask)); |
| 1008 deferred->enter()->Branch(not_zero, &operand, not_taken); | 1013 deferred->enter()->Branch(not_zero, &operand, not_taken); |
| 1009 deferred->exit()->Bind(&operand); | 1014 deferred->exit()->Bind(&operand); |
| 1010 frame_->Push(&operand); | 1015 frame_->Push(&operand); |
| 1011 break; | 1016 break; |
| 1012 } | 1017 } |
| 1013 | 1018 |
| 1014 case Token::SUB: { | 1019 case Token::SUB: { |
| 1015 DeferredCode* deferred = NULL; | 1020 DeferredCode* deferred = NULL; |
| 1016 frame_->EmitPop(eax); | 1021 Result operand = frame_->Pop(); |
| 1022 Result answer(this); // Only allocated a new register if reversed. | |
|
Kevin Millikin (Chromium)
2009/01/23 08:49:25
allocated ==> allocate
William Hesse
2012/05/07 09:35:10
Done.
| |
| 1023 operand.ToRegister(); | |
| 1024 frame_->Spill(operand.reg()); | |
|
Kevin Millikin (Chromium)
2009/01/23 08:49:25
It looks like operand is only clobbered in the not
William Hesse
2012/05/07 09:35:10
Done.
| |
| 1017 if (!reversed) { | 1025 if (!reversed) { |
| 1018 deferred = new DeferredInlinedSmiSub(this, int_value, overwrite_mode); | 1026 deferred = new DeferredInlinedSmiSub(this, |
| 1019 __ sub(Operand(eax), Immediate(value)); | 1027 smi_value, |
| 1028 overwrite_mode); | |
| 1029 __ sub(Operand(operand.reg()), Immediate(value)); | |
| 1030 answer = operand; | |
| 1020 } else { | 1031 } else { |
| 1021 deferred = new DeferredInlinedSmiSubReversed(this, edx, overwrite_mode); | 1032 answer = allocator()->Allocate(); |
| 1022 __ mov(edx, Operand(eax)); | 1033 ASSERT(answer.is_valid()); |
| 1023 __ mov(eax, Immediate(value)); | 1034 deferred = new DeferredInlinedSmiSubReversed(this, |
| 1024 __ sub(eax, Operand(edx)); | 1035 smi_value, |
| 1036 overwrite_mode); | |
| 1037 __ mov(answer.reg(), Immediate(value)); | |
| 1038 __ sub(answer.reg(), Operand(operand.reg())); | |
| 1025 } | 1039 } |
| 1026 deferred->enter()->Branch(overflow, not_taken); | 1040 operand.Unuse(); |
| 1027 __ test(eax, Immediate(kSmiTagMask)); | 1041 deferred->enter()->Branch(overflow, &answer, not_taken); |
|
Kevin Millikin (Chromium)
2009/01/23 08:49:25
Maybe it makes this code uglier, but can't we pass
William Hesse
2012/05/07 09:35:10
Done.
| |
| 1028 deferred->enter()->Branch(not_zero, not_taken); | 1042 __ test(answer.reg(), Immediate(kSmiTagMask)); |
| 1029 deferred->exit()->Bind(); | 1043 deferred->enter()->Branch(not_zero, &answer, not_taken); |
| 1030 frame_->EmitPush(eax); | 1044 deferred->exit()->Bind(&answer); |
| 1045 frame_->Push(&answer); | |
| 1031 break; | 1046 break; |
| 1032 } | 1047 } |
| 1033 | 1048 |
| 1034 case Token::SAR: { | 1049 case Token::SAR: { |
| 1035 if (reversed) { | 1050 if (reversed) { |
| 1036 frame_->EmitPop(eax); | 1051 Result top = frame_->Pop(); |
| 1037 frame_->EmitPush(Immediate(value)); | 1052 frame_->Push(value); |
| 1038 frame_->EmitPush(eax); | 1053 frame_->Push(&top); |
| 1039 GenericBinaryOperation(op, type, overwrite_mode); | 1054 GenericBinaryOperation(op, type, overwrite_mode); |
| 1040 } else { | 1055 } else { |
| 1056 VirtualFrame::SpilledScope spilled_scope(this); | |
| 1041 int shift_value = int_value & 0x1f; // only least significant 5 bits | 1057 int shift_value = int_value & 0x1f; // only least significant 5 bits |
| 1042 DeferredCode* deferred = | 1058 DeferredCode* deferred = |
| 1043 new DeferredInlinedSmiOperation(this, Token::SAR, shift_value, | 1059 new DeferredInlinedSmiOperation(this, Token::SAR, shift_value, |
| 1044 overwrite_mode); | 1060 overwrite_mode); |
| 1045 frame_->EmitPop(eax); | 1061 frame_->EmitPop(eax); |
| 1046 __ test(eax, Immediate(kSmiTagMask)); | 1062 __ test(eax, Immediate(kSmiTagMask)); |
| 1047 deferred->enter()->Branch(not_zero, not_taken); | 1063 deferred->enter()->Branch(not_zero, not_taken); |
| 1048 __ sar(eax, shift_value); | 1064 __ sar(eax, shift_value); |
| 1049 __ and_(eax, ~kSmiTagMask); | 1065 __ and_(eax, ~kSmiTagMask); |
| 1050 deferred->exit()->Bind(); | 1066 deferred->exit()->Bind(); |
| 1051 frame_->EmitPush(eax); | 1067 frame_->EmitPush(eax); |
| 1052 } | 1068 } |
| 1053 break; | 1069 break; |
| 1054 } | 1070 } |
| 1055 | 1071 |
| 1056 case Token::SHR: { | 1072 case Token::SHR: { |
| 1057 if (reversed) { | 1073 if (reversed) { |
| 1058 frame_->EmitPop(eax); | 1074 Result top = frame_->Pop(); |
| 1059 frame_->EmitPush(Immediate(value)); | 1075 frame_->Push(value); |
| 1060 frame_->EmitPush(eax); | 1076 frame_->Push(&top); |
| 1061 GenericBinaryOperation(op, type, overwrite_mode); | 1077 GenericBinaryOperation(op, type, overwrite_mode); |
| 1062 } else { | 1078 } else { |
| 1079 VirtualFrame::SpilledScope spilled_scope(this); | |
| 1063 int shift_value = int_value & 0x1f; // only least significant 5 bits | 1080 int shift_value = int_value & 0x1f; // only least significant 5 bits |
| 1064 DeferredCode* deferred = | 1081 DeferredCode* deferred = |
| 1065 new DeferredInlinedSmiOperation(this, Token::SHR, shift_value, | 1082 new DeferredInlinedSmiOperation(this, Token::SHR, shift_value, |
| 1066 overwrite_mode); | 1083 overwrite_mode); |
| 1067 frame_->EmitPop(eax); | 1084 frame_->EmitPop(eax); |
| 1068 __ test(eax, Immediate(kSmiTagMask)); | 1085 __ test(eax, Immediate(kSmiTagMask)); |
| 1069 __ mov(ebx, Operand(eax)); | 1086 __ mov(ebx, Operand(eax)); |
| 1070 deferred->enter()->Branch(not_zero, not_taken); | 1087 deferred->enter()->Branch(not_zero, not_taken); |
| 1071 __ sar(ebx, kSmiTagSize); | 1088 __ sar(ebx, kSmiTagSize); |
| 1072 __ shr(ebx, shift_value); | 1089 __ shr(ebx, shift_value); |
| 1073 __ test(ebx, Immediate(0xc0000000)); | 1090 __ test(ebx, Immediate(0xc0000000)); |
| 1074 deferred->enter()->Branch(not_zero, not_taken); | 1091 deferred->enter()->Branch(not_zero, not_taken); |
| 1075 // tag result and store it in TOS (eax) | 1092 // tag result and store it in TOS (eax) |
| 1076 ASSERT(kSmiTagSize == times_2); // adjust code if not the case | 1093 ASSERT(kSmiTagSize == times_2); // adjust code if not the case |
| 1077 __ lea(eax, Operand(ebx, ebx, times_1, kSmiTag)); | 1094 __ lea(eax, Operand(ebx, ebx, times_1, kSmiTag)); |
| 1078 deferred->exit()->Bind(); | 1095 deferred->exit()->Bind(); |
| 1079 frame_->EmitPush(eax); | 1096 frame_->EmitPush(eax); |
| 1080 } | 1097 } |
| 1081 break; | 1098 break; |
| 1082 } | 1099 } |
| 1083 | 1100 |
| 1084 case Token::SHL: { | 1101 case Token::SHL: { |
| 1102 VirtualFrame::SpilledScope spilled_scope(this); | |
| 1085 if (reversed) { | 1103 if (reversed) { |
| 1086 frame_->EmitPop(eax); | 1104 frame_->EmitPop(eax); |
| 1087 frame_->EmitPush(Immediate(value)); | 1105 frame_->EmitPush(Immediate(value)); |
| 1088 frame_->EmitPush(eax); | 1106 frame_->EmitPush(eax); |
| 1089 GenericBinaryOperation(op, type, overwrite_mode); | 1107 GenericBinaryOperation(op, type, overwrite_mode); |
| 1090 } else { | 1108 } else { |
| 1091 int shift_value = int_value & 0x1f; // only least significant 5 bits | 1109 int shift_value = int_value & 0x1f; // only least significant 5 bits |
| 1092 DeferredCode* deferred = | 1110 DeferredCode* deferred = |
| 1093 new DeferredInlinedSmiOperation(this, Token::SHL, shift_value, | 1111 new DeferredInlinedSmiOperation(this, Token::SHL, shift_value, |
| 1094 overwrite_mode); | 1112 overwrite_mode); |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 1106 __ lea(eax, Operand(ebx, ebx, times_1, kSmiTag)); | 1124 __ lea(eax, Operand(ebx, ebx, times_1, kSmiTag)); |
| 1107 deferred->exit()->Bind(); | 1125 deferred->exit()->Bind(); |
| 1108 frame_->EmitPush(eax); | 1126 frame_->EmitPush(eax); |
| 1109 } | 1127 } |
| 1110 break; | 1128 break; |
| 1111 } | 1129 } |
| 1112 | 1130 |
| 1113 case Token::BIT_OR: | 1131 case Token::BIT_OR: |
| 1114 case Token::BIT_XOR: | 1132 case Token::BIT_XOR: |
| 1115 case Token::BIT_AND: { | 1133 case Token::BIT_AND: { |
| 1134 VirtualFrame::SpilledScope spilled_scope(this); | |
| 1116 DeferredCode* deferred = NULL; | 1135 DeferredCode* deferred = NULL; |
| 1117 if (!reversed) { | 1136 if (!reversed) { |
| 1118 deferred = new DeferredInlinedSmiOperation(this, op, int_value, | 1137 deferred = new DeferredInlinedSmiOperation(this, op, int_value, |
| 1119 overwrite_mode); | 1138 overwrite_mode); |
| 1120 } else { | 1139 } else { |
| 1121 deferred = new DeferredInlinedSmiOperationReversed(this, op, int_value, | 1140 deferred = new DeferredInlinedSmiOperationReversed(this, op, int_value, |
| 1122 overwrite_mode); | 1141 overwrite_mode); |
| 1123 } | 1142 } |
| 1124 frame_->EmitPop(eax); | 1143 frame_->EmitPop(eax); |
| 1125 __ test(eax, Immediate(kSmiTagMask)); | 1144 __ test(eax, Immediate(kSmiTagMask)); |
| 1126 deferred->enter()->Branch(not_zero, not_taken); | 1145 deferred->enter()->Branch(not_zero, not_taken); |
| 1127 if (op == Token::BIT_AND) { | 1146 if (op == Token::BIT_AND) { |
| 1128 __ and_(Operand(eax), Immediate(value)); | 1147 __ and_(Operand(eax), Immediate(value)); |
| 1129 } else if (op == Token::BIT_XOR) { | 1148 } else if (op == Token::BIT_XOR) { |
| 1130 __ xor_(Operand(eax), Immediate(value)); | 1149 __ xor_(Operand(eax), Immediate(value)); |
| 1131 } else { | 1150 } else { |
| 1132 ASSERT(op == Token::BIT_OR); | 1151 ASSERT(op == Token::BIT_OR); |
| 1133 __ or_(Operand(eax), Immediate(value)); | 1152 __ or_(Operand(eax), Immediate(value)); |
| 1134 } | 1153 } |
| 1135 deferred->exit()->Bind(); | 1154 deferred->exit()->Bind(); |
| 1136 frame_->EmitPush(eax); | 1155 frame_->EmitPush(eax); |
| 1137 break; | 1156 break; |
| 1138 } | 1157 } |
| 1139 | 1158 |
| 1140 default: { | 1159 default: { |
| 1141 if (!reversed) { | 1160 if (!reversed) { |
|
Kevin Millikin (Chromium)
2009/01/23 08:49:25
Reverse the arms of the if?
William Hesse
2012/05/07 09:35:10
Done.
| |
| 1142 frame_->EmitPush(Immediate(value)); | 1161 frame_->Push(value); |
| 1143 } else { | 1162 } else { |
| 1144 frame_->EmitPop(eax); | 1163 Result top = frame_->Pop(); |
| 1145 frame_->EmitPush(Immediate(value)); | 1164 frame_->Push(value); |
| 1146 frame_->EmitPush(eax); | 1165 frame_->Push(&top); |
| 1147 } | 1166 } |
| 1148 GenericBinaryOperation(op, type, overwrite_mode); | 1167 GenericBinaryOperation(op, type, overwrite_mode); |
| 1149 break; | 1168 break; |
| 1150 } | 1169 } |
| 1151 } | 1170 } |
| 1152 } | 1171 } |
| 1153 | 1172 |
| 1154 | 1173 |
| 1155 class CompareStub: public CodeStub { | 1174 class CompareStub: public CodeStub { |
| 1156 public: | 1175 public: |
| (...skipping 4952 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6109 | 6128 |
| 6110 // Slow-case: Go through the JavaScript implementation. | 6129 // Slow-case: Go through the JavaScript implementation. |
| 6111 __ bind(&slow); | 6130 __ bind(&slow); |
| 6112 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); | 6131 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); |
| 6113 } | 6132 } |
| 6114 | 6133 |
| 6115 | 6134 |
| 6116 #undef __ | 6135 #undef __ |
| 6117 | 6136 |
| 6118 } } // namespace v8::internal | 6137 } } // namespace v8::internal |
| OLD | NEW |