Chromium Code Reviews| 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 |