OLD | NEW |
---|---|
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 6876 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6887 DeferredCode* deferred = NULL; | 6887 DeferredCode* deferred = NULL; |
6888 if (reversed) { | 6888 if (reversed) { |
6889 deferred = new DeferredInlineSmiAddReversed(operand->reg(), | 6889 deferred = new DeferredInlineSmiAddReversed(operand->reg(), |
6890 smi_value, | 6890 smi_value, |
6891 overwrite_mode); | 6891 overwrite_mode); |
6892 } else { | 6892 } else { |
6893 deferred = new DeferredInlineSmiAdd(operand->reg(), | 6893 deferred = new DeferredInlineSmiAdd(operand->reg(), |
6894 smi_value, | 6894 smi_value, |
6895 overwrite_mode); | 6895 overwrite_mode); |
6896 } | 6896 } |
6897 __ JumpIfNotSmi(operand->reg(), deferred->entry_label()); | 6897 JumpIfNotSmiUsingTypeInfo(operand->reg(), operand->type_info(), |
6898 deferred); | |
6898 __ SmiAddConstant(operand->reg(), | 6899 __ SmiAddConstant(operand->reg(), |
6899 operand->reg(), | 6900 operand->reg(), |
6900 smi_value, | 6901 smi_value, |
6901 deferred->entry_label()); | 6902 deferred->entry_label()); |
6902 deferred->BindExit(); | 6903 deferred->BindExit(); |
6903 answer = *operand; | 6904 answer = *operand; |
6904 break; | 6905 break; |
6905 } | 6906 } |
6906 | 6907 |
6907 case Token::SUB: { | 6908 case Token::SUB: { |
6908 if (reversed) { | 6909 if (reversed) { |
6909 Result constant_operand(value); | 6910 Result constant_operand(value); |
6910 answer = LikelySmiBinaryOperation(expr, &constant_operand, operand, | 6911 answer = LikelySmiBinaryOperation(expr, &constant_operand, operand, |
6911 overwrite_mode); | 6912 overwrite_mode); |
6912 } else { | 6913 } else { |
6913 operand->ToRegister(); | 6914 operand->ToRegister(); |
6914 frame_->Spill(operand->reg()); | 6915 frame_->Spill(operand->reg()); |
6915 DeferredCode* deferred = new DeferredInlineSmiSub(operand->reg(), | 6916 DeferredCode* deferred = new DeferredInlineSmiSub(operand->reg(), |
6916 smi_value, | 6917 smi_value, |
6917 overwrite_mode); | 6918 overwrite_mode); |
6918 __ JumpIfNotSmi(operand->reg(), deferred->entry_label()); | 6919 JumpIfNotSmiUsingTypeInfo(operand->reg(), operand->type_info(), |
6920 deferred); | |
6919 // A smi currently fits in a 32-bit Immediate. | 6921 // A smi currently fits in a 32-bit Immediate. |
6920 __ SmiSubConstant(operand->reg(), | 6922 __ SmiSubConstant(operand->reg(), |
6921 operand->reg(), | 6923 operand->reg(), |
6922 smi_value, | 6924 smi_value, |
6923 deferred->entry_label()); | 6925 deferred->entry_label()); |
6924 deferred->BindExit(); | 6926 deferred->BindExit(); |
6925 answer = *operand; | 6927 answer = *operand; |
6926 } | 6928 } |
6927 break; | 6929 break; |
6928 } | 6930 } |
6929 | 6931 |
6930 case Token::SAR: | 6932 case Token::SAR: |
6931 if (reversed) { | 6933 if (reversed) { |
6932 Result constant_operand(value); | 6934 Result constant_operand(value); |
6933 answer = LikelySmiBinaryOperation(expr, &constant_operand, operand, | 6935 answer = LikelySmiBinaryOperation(expr, &constant_operand, operand, |
6934 overwrite_mode); | 6936 overwrite_mode); |
6935 } else { | 6937 } else { |
6936 // Only the least significant 5 bits of the shift value are used. | 6938 // Only the least significant 5 bits of the shift value are used. |
6937 // In the slow case, this masking is done inside the runtime call. | 6939 // In the slow case, this masking is done inside the runtime call. |
6938 int shift_value = int_value & 0x1f; | 6940 int shift_value = int_value & 0x1f; |
6939 operand->ToRegister(); | 6941 operand->ToRegister(); |
6940 frame_->Spill(operand->reg()); | 6942 frame_->Spill(operand->reg()); |
6941 DeferredInlineSmiOperation* deferred = | 6943 DeferredInlineSmiOperation* deferred = |
6942 new DeferredInlineSmiOperation(op, | 6944 new DeferredInlineSmiOperation(op, |
6943 operand->reg(), | 6945 operand->reg(), |
6944 operand->reg(), | 6946 operand->reg(), |
6945 smi_value, | 6947 smi_value, |
6946 overwrite_mode); | 6948 overwrite_mode); |
6947 __ JumpIfNotSmi(operand->reg(), deferred->entry_label()); | 6949 JumpIfNotSmiUsingTypeInfo(operand->reg(), operand->type_info(), |
6950 deferred); | |
6948 __ SmiShiftArithmeticRightConstant(operand->reg(), | 6951 __ SmiShiftArithmeticRightConstant(operand->reg(), |
6949 operand->reg(), | 6952 operand->reg(), |
6950 shift_value); | 6953 shift_value); |
6951 deferred->BindExit(); | 6954 deferred->BindExit(); |
6952 answer = *operand; | 6955 answer = *operand; |
6953 } | 6956 } |
6954 break; | 6957 break; |
6955 | 6958 |
6956 case Token::SHR: | 6959 case Token::SHR: |
6957 if (reversed) { | 6960 if (reversed) { |
6958 Result constant_operand(value); | 6961 Result constant_operand(value); |
6959 answer = LikelySmiBinaryOperation(expr, &constant_operand, operand, | 6962 answer = LikelySmiBinaryOperation(expr, &constant_operand, operand, |
6960 overwrite_mode); | 6963 overwrite_mode); |
6961 } else { | 6964 } else { |
6962 // Only the least significant 5 bits of the shift value are used. | 6965 // Only the least significant 5 bits of the shift value are used. |
6963 // In the slow case, this masking is done inside the runtime call. | 6966 // In the slow case, this masking is done inside the runtime call. |
6964 int shift_value = int_value & 0x1f; | 6967 int shift_value = int_value & 0x1f; |
6965 operand->ToRegister(); | 6968 operand->ToRegister(); |
6966 answer = allocator()->Allocate(); | 6969 answer = allocator()->Allocate(); |
6967 ASSERT(answer.is_valid()); | 6970 ASSERT(answer.is_valid()); |
6968 DeferredInlineSmiOperation* deferred = | 6971 DeferredInlineSmiOperation* deferred = |
6969 new DeferredInlineSmiOperation(op, | 6972 new DeferredInlineSmiOperation(op, |
6970 answer.reg(), | 6973 answer.reg(), |
6971 operand->reg(), | 6974 operand->reg(), |
6972 smi_value, | 6975 smi_value, |
6973 overwrite_mode); | 6976 overwrite_mode); |
6974 __ JumpIfNotSmi(operand->reg(), deferred->entry_label()); | 6977 JumpIfNotSmiUsingTypeInfo(operand->reg(), operand->type_info(), |
6978 deferred); | |
6975 __ SmiShiftLogicalRightConstant(answer.reg(), | 6979 __ SmiShiftLogicalRightConstant(answer.reg(), |
6976 operand->reg(), | 6980 operand->reg(), |
6977 shift_value, | 6981 shift_value, |
6978 deferred->entry_label()); | 6982 deferred->entry_label()); |
6979 deferred->BindExit(); | 6983 deferred->BindExit(); |
6980 operand->Unuse(); | 6984 operand->Unuse(); |
6981 } | 6985 } |
6982 break; | 6986 break; |
6983 | 6987 |
6984 case Token::SHL: | 6988 case Token::SHL: |
(...skipping 11 matching lines...) Expand all Loading... | |
6996 answer = allocator()->Allocate(); | 7000 answer = allocator()->Allocate(); |
6997 // rcx_reg goes out of scope. | 7001 // rcx_reg goes out of scope. |
6998 } | 7002 } |
6999 | 7003 |
7000 DeferredInlineSmiOperationReversed* deferred = | 7004 DeferredInlineSmiOperationReversed* deferred = |
7001 new DeferredInlineSmiOperationReversed(op, | 7005 new DeferredInlineSmiOperationReversed(op, |
7002 answer.reg(), | 7006 answer.reg(), |
7003 smi_value, | 7007 smi_value, |
7004 operand->reg(), | 7008 operand->reg(), |
7005 overwrite_mode); | 7009 overwrite_mode); |
7006 if (!operand->type_info().IsSmi()) { | 7010 JumpIfNotSmiUsingTypeInfo(operand->reg(), operand->type_info(), |
7007 Condition is_smi = masm_->CheckSmi(operand->reg()); | 7011 deferred); |
7008 deferred->Branch(NegateCondition(is_smi)); | |
7009 } else if (FLAG_debug_code) { | |
7010 __ AbortIfNotSmi(operand->reg()); | |
7011 } | |
7012 | 7012 |
7013 __ Move(answer.reg(), smi_value); | 7013 __ Move(answer.reg(), smi_value); |
7014 __ SmiShiftLeft(answer.reg(), answer.reg(), operand->reg()); | 7014 __ SmiShiftLeft(answer.reg(), answer.reg(), operand->reg()); |
7015 operand->Unuse(); | 7015 operand->Unuse(); |
7016 | 7016 |
7017 deferred->BindExit(); | 7017 deferred->BindExit(); |
7018 } else { | 7018 } else { |
7019 // Only the least significant 5 bits of the shift value are used. | 7019 // Only the least significant 5 bits of the shift value are used. |
7020 // In the slow case, this masking is done inside the runtime call. | 7020 // In the slow case, this masking is done inside the runtime call. |
7021 int shift_value = int_value & 0x1f; | 7021 int shift_value = int_value & 0x1f; |
7022 operand->ToRegister(); | 7022 operand->ToRegister(); |
7023 if (shift_value == 0) { | 7023 if (shift_value == 0) { |
7024 // Spill operand so it can be overwritten in the slow case. | 7024 // Spill operand so it can be overwritten in the slow case. |
7025 frame_->Spill(operand->reg()); | 7025 frame_->Spill(operand->reg()); |
7026 DeferredInlineSmiOperation* deferred = | 7026 DeferredInlineSmiOperation* deferred = |
7027 new DeferredInlineSmiOperation(op, | 7027 new DeferredInlineSmiOperation(op, |
7028 operand->reg(), | 7028 operand->reg(), |
7029 operand->reg(), | 7029 operand->reg(), |
7030 smi_value, | 7030 smi_value, |
7031 overwrite_mode); | 7031 overwrite_mode); |
7032 __ JumpIfNotSmi(operand->reg(), deferred->entry_label()); | 7032 JumpIfNotSmiUsingTypeInfo(operand->reg(), operand->type_info(), |
7033 deferred); | |
7033 deferred->BindExit(); | 7034 deferred->BindExit(); |
7034 answer = *operand; | 7035 answer = *operand; |
7035 } else { | 7036 } else { |
7036 // Use a fresh temporary for nonzero shift values. | 7037 // Use a fresh temporary for nonzero shift values. |
7037 answer = allocator()->Allocate(); | 7038 answer = allocator()->Allocate(); |
7038 ASSERT(answer.is_valid()); | 7039 ASSERT(answer.is_valid()); |
7039 DeferredInlineSmiOperation* deferred = | 7040 DeferredInlineSmiOperation* deferred = |
7040 new DeferredInlineSmiOperation(op, | 7041 new DeferredInlineSmiOperation(op, |
7041 answer.reg(), | 7042 answer.reg(), |
7042 operand->reg(), | 7043 operand->reg(), |
7043 smi_value, | 7044 smi_value, |
7044 overwrite_mode); | 7045 overwrite_mode); |
7045 __ JumpIfNotSmi(operand->reg(), deferred->entry_label()); | 7046 JumpIfNotSmiUsingTypeInfo(operand->reg(), operand->type_info(), |
7047 deferred); | |
7046 __ SmiShiftLeftConstant(answer.reg(), | 7048 __ SmiShiftLeftConstant(answer.reg(), |
7047 operand->reg(), | 7049 operand->reg(), |
7048 shift_value); | 7050 shift_value); |
7049 deferred->BindExit(); | 7051 deferred->BindExit(); |
7050 operand->Unuse(); | 7052 operand->Unuse(); |
7051 } | 7053 } |
7052 } | 7054 } |
7053 break; | 7055 break; |
7054 | 7056 |
7055 case Token::BIT_OR: | 7057 case Token::BIT_OR: |
7056 case Token::BIT_XOR: | 7058 case Token::BIT_XOR: |
7057 case Token::BIT_AND: { | 7059 case Token::BIT_AND: { |
7058 operand->ToRegister(); | 7060 operand->ToRegister(); |
7059 frame_->Spill(operand->reg()); | 7061 frame_->Spill(operand->reg()); |
7060 if (reversed) { | 7062 if (reversed) { |
7061 // Bit operations with a constant smi are commutative. | 7063 // Bit operations with a constant smi are commutative. |
7062 // We can swap left and right operands with no problem. | 7064 // We can swap left and right operands with no problem. |
7063 // Swap left and right overwrite modes. 0->0, 1->2, 2->1. | 7065 // Swap left and right overwrite modes. 0->0, 1->2, 2->1. |
7064 overwrite_mode = static_cast<OverwriteMode>((2 * overwrite_mode) % 3); | 7066 overwrite_mode = static_cast<OverwriteMode>((2 * overwrite_mode) % 3); |
7065 } | 7067 } |
7066 DeferredCode* deferred = new DeferredInlineSmiOperation(op, | 7068 DeferredCode* deferred = new DeferredInlineSmiOperation(op, |
7067 operand->reg(), | 7069 operand->reg(), |
7068 operand->reg(), | 7070 operand->reg(), |
7069 smi_value, | 7071 smi_value, |
7070 overwrite_mode); | 7072 overwrite_mode); |
7071 __ JumpIfNotSmi(operand->reg(), deferred->entry_label()); | 7073 JumpIfNotSmiUsingTypeInfo(operand->reg(), operand->type_info(), |
7074 deferred); | |
7072 if (op == Token::BIT_AND) { | 7075 if (op == Token::BIT_AND) { |
7073 __ SmiAndConstant(operand->reg(), operand->reg(), smi_value); | 7076 __ SmiAndConstant(operand->reg(), operand->reg(), smi_value); |
7074 } else if (op == Token::BIT_XOR) { | 7077 } else if (op == Token::BIT_XOR) { |
7075 if (int_value != 0) { | 7078 if (int_value != 0) { |
7076 __ SmiXorConstant(operand->reg(), operand->reg(), smi_value); | 7079 __ SmiXorConstant(operand->reg(), operand->reg(), smi_value); |
7077 } | 7080 } |
7078 } else { | 7081 } else { |
7079 ASSERT(op == Token::BIT_OR); | 7082 ASSERT(op == Token::BIT_OR); |
7080 if (int_value != 0) { | 7083 if (int_value != 0) { |
7081 __ SmiOrConstant(operand->reg(), operand->reg(), smi_value); | 7084 __ SmiOrConstant(operand->reg(), operand->reg(), smi_value); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
7126 overwrite_mode); | 7129 overwrite_mode); |
7127 } | 7130 } |
7128 break; | 7131 break; |
7129 } | 7132 } |
7130 } | 7133 } |
7131 ASSERT(answer.is_valid()); | 7134 ASSERT(answer.is_valid()); |
7132 return answer; | 7135 return answer; |
7133 } | 7136 } |
7134 | 7137 |
7135 | 7138 |
7139 void CodeGenerator::JumpIfNotSmiUsingTypeInfo(Register reg, | |
7140 TypeInfo type, | |
7141 DeferredCode* deferred) { | |
7142 if (!type.IsSmi()) { | |
7143 __ JumpIfNotSmi(reg, deferred->entry_label()); | |
7144 } | |
Lasse Reichstein
2010/06/10 10:02:36
Is it possible to have a typeinfo that says that t
| |
7145 if (FLAG_debug_code) { | |
7146 __ AbortIfNotSmi(reg); | |
7147 } | |
7148 } | |
7149 | |
7150 | |
7136 void CodeGenerator::JumpIfNotBothSmiUsingTypeInfo(Register left, | 7151 void CodeGenerator::JumpIfNotBothSmiUsingTypeInfo(Register left, |
7137 Register right, | 7152 Register right, |
7138 TypeInfo left_info, | 7153 TypeInfo left_info, |
7139 TypeInfo right_info, | 7154 TypeInfo right_info, |
7140 DeferredCode* deferred) { | 7155 DeferredCode* deferred) { |
7141 if (!left_info.IsSmi() && !right_info.IsSmi()) { | 7156 if (!left_info.IsSmi() && !right_info.IsSmi()) { |
7142 __ JumpIfNotBothSmi(left, right, deferred->entry_label()); | 7157 __ JumpIfNotBothSmi(left, right, deferred->entry_label()); |
7143 } else if (!left_info.IsSmi()) { | 7158 } else if (!left_info.IsSmi()) { |
7144 __ JumpIfNotSmi(left, deferred->entry_label()); | 7159 __ JumpIfNotSmi(left, deferred->entry_label()); |
7145 } else if (!right_info.IsSmi()) { | 7160 } else if (!right_info.IsSmi()) { |
(...skipping 4784 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
11930 } | 11945 } |
11931 | 11946 |
11932 #endif | 11947 #endif |
11933 | 11948 |
11934 | 11949 |
11935 #undef __ | 11950 #undef __ |
11936 | 11951 |
11937 } } // namespace v8::internal | 11952 } } // namespace v8::internal |
11938 | 11953 |
11939 #endif // V8_TARGET_ARCH_X64 | 11954 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |