OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 1100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1111 __ CallStub(&stub); | 1111 __ CallStub(&stub); |
1112 RecordSafepointWithRegistersAndDoubles(instr->pointer_map(), | 1112 RecordSafepointWithRegistersAndDoubles(instr->pointer_map(), |
1113 0, | 1113 0, |
1114 Safepoint::kNoDeoptimizationIndex); | 1114 Safepoint::kNoDeoptimizationIndex); |
1115 // Overwrite the stored value of r0 with the result of the stub. | 1115 // Overwrite the stored value of r0 with the result of the stub. |
1116 __ StoreToSafepointRegistersAndDoublesSlot(r0, r0); | 1116 __ StoreToSafepointRegistersAndDoublesSlot(r0, r0); |
1117 } | 1117 } |
1118 | 1118 |
1119 | 1119 |
1120 void LCodeGen::DoMulI(LMulI* instr) { | 1120 void LCodeGen::DoMulI(LMulI* instr) { |
| 1121 ASSERT(instr->result()->Equals(instr->InputAt(0))); |
1121 Register scratch = scratch0(); | 1122 Register scratch = scratch0(); |
| 1123 Register result = ToRegister(instr->result()); |
1122 Register left = ToRegister(instr->InputAt(0)); | 1124 Register left = ToRegister(instr->InputAt(0)); |
1123 Register right = EmitLoadRegister(instr->InputAt(1), scratch); | 1125 LOperand* right_op = instr->InputAt(1); |
1124 | 1126 |
1125 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero) && | 1127 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); |
1126 !instr->InputAt(1)->IsConstantOperand()) { | 1128 bool bailout_on_minus_zero = |
1127 __ orr(ToRegister(instr->TempAt(0)), left, right); | 1129 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero); |
1128 } | |
1129 | 1130 |
1130 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { | 1131 if (right_op->IsConstantOperand() && !can_overflow) { |
1131 // scratch:left = left * right. | 1132 // Use optimized code for specific constants. |
1132 __ smull(left, scratch, left, right); | 1133 int32_t constant = ToInteger32(LConstantOperand::cast(right_op)); |
1133 __ mov(ip, Operand(left, ASR, 31)); | 1134 |
1134 __ cmp(ip, Operand(scratch)); | 1135 if (bailout_on_minus_zero && (constant < 0)) { |
1135 DeoptimizeIf(ne, instr->environment()); | 1136 // The case of a null constant will be handled separately. |
| 1137 // If constant is negative and left is null, the result should be -0. |
| 1138 __ cmp(left, Operand(0)); |
| 1139 DeoptimizeIf(eq, instr->environment()); |
| 1140 } |
| 1141 |
| 1142 switch (constant) { |
| 1143 case -1: |
| 1144 __ rsb(result, left, Operand(0)); |
| 1145 break; |
| 1146 case 0: |
| 1147 if (bailout_on_minus_zero) { |
| 1148 // If left is strictly negative and the constant is null, the |
| 1149 // result is -0. Deoptimize if required, otherwise return 0. |
| 1150 __ cmp(left, Operand(0)); |
| 1151 DeoptimizeIf(mi, instr->environment()); |
| 1152 } |
| 1153 __ mov(result, Operand(0)); |
| 1154 break; |
| 1155 case 1: |
| 1156 // Nothing to do. |
| 1157 break; |
| 1158 default: |
| 1159 // Multiplying by powers of two and powers of two plus or minus |
| 1160 // one can be done faster with shifted operands. |
| 1161 // For other constants we emit standard code. |
| 1162 int32_t mask = constant >> 31; |
| 1163 uint32_t constant_abs = (constant + mask) ^ mask; |
| 1164 |
| 1165 if (IsPowerOf2(constant_abs) || |
| 1166 IsPowerOf2(constant_abs - 1) || |
| 1167 IsPowerOf2(constant_abs + 1)) { |
| 1168 if (IsPowerOf2(constant_abs)) { |
| 1169 int32_t shift = WhichPowerOf2(constant_abs); |
| 1170 __ mov(result, Operand(left, LSL, shift)); |
| 1171 } else if (IsPowerOf2(constant_abs - 1)) { |
| 1172 int32_t shift = WhichPowerOf2(constant_abs - 1); |
| 1173 __ add(result, left, Operand(left, LSL, shift)); |
| 1174 } else if (IsPowerOf2(constant_abs + 1)) { |
| 1175 int32_t shift = WhichPowerOf2(constant_abs + 1); |
| 1176 __ rsb(result, left, Operand(left, LSL, shift)); |
| 1177 } |
| 1178 |
| 1179 // Correct the sign of the result is the constant is negative. |
| 1180 if (constant < 0) __ rsb(result, result, Operand(0)); |
| 1181 |
| 1182 } else { |
| 1183 // Generate standard code. |
| 1184 __ mov(ip, Operand(constant)); |
| 1185 __ mul(result, left, ip); |
| 1186 } |
| 1187 } |
| 1188 |
1136 } else { | 1189 } else { |
1137 __ mul(left, left, right); | 1190 Register right = EmitLoadRegister(right_op, scratch); |
1138 } | 1191 if (bailout_on_minus_zero) { |
| 1192 __ orr(ToRegister(instr->TempAt(0)), left, right); |
| 1193 } |
1139 | 1194 |
1140 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1195 if (can_overflow) { |
1141 // Bail out if the result is supposed to be negative zero. | 1196 // scratch:result = left * right. |
1142 Label done; | 1197 __ smull(result, scratch, left, right); |
1143 __ cmp(left, Operand(0)); | 1198 __ cmp(scratch, Operand(result, ASR, 31)); |
1144 __ b(ne, &done); | 1199 DeoptimizeIf(ne, instr->environment()); |
1145 if (instr->InputAt(1)->IsConstantOperand()) { | |
1146 if (ToInteger32(LConstantOperand::cast(instr->InputAt(1))) <= 0) { | |
1147 DeoptimizeIf(al, instr->environment()); | |
1148 } | |
1149 } else { | 1200 } else { |
1150 // Test the non-zero operand for negative sign. | 1201 __ mul(result, left, right); |
| 1202 } |
| 1203 |
| 1204 if (bailout_on_minus_zero) { |
| 1205 // Bail out if the result is supposed to be negative zero. |
| 1206 Label done; |
| 1207 __ cmp(result, Operand(0)); |
| 1208 __ b(ne, &done); |
1151 __ cmp(ToRegister(instr->TempAt(0)), Operand(0)); | 1209 __ cmp(ToRegister(instr->TempAt(0)), Operand(0)); |
1152 DeoptimizeIf(mi, instr->environment()); | 1210 DeoptimizeIf(mi, instr->environment()); |
| 1211 __ bind(&done); |
1153 } | 1212 } |
1154 __ bind(&done); | |
1155 } | 1213 } |
1156 } | 1214 } |
1157 | 1215 |
1158 | 1216 |
1159 void LCodeGen::DoBitI(LBitI* instr) { | 1217 void LCodeGen::DoBitI(LBitI* instr) { |
1160 LOperand* left = instr->InputAt(0); | 1218 LOperand* left = instr->InputAt(0); |
1161 LOperand* right = instr->InputAt(1); | 1219 LOperand* right = instr->InputAt(1); |
1162 ASSERT(left->Equals(instr->result())); | 1220 ASSERT(left->Equals(instr->result())); |
1163 ASSERT(left->IsRegister()); | 1221 ASSERT(left->IsRegister()); |
1164 Register result = ToRegister(left); | 1222 Register result = ToRegister(left); |
(...skipping 3381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4546 ASSERT(osr_pc_offset_ == -1); | 4604 ASSERT(osr_pc_offset_ == -1); |
4547 osr_pc_offset_ = masm()->pc_offset(); | 4605 osr_pc_offset_ = masm()->pc_offset(); |
4548 } | 4606 } |
4549 | 4607 |
4550 | 4608 |
4551 | 4609 |
4552 | 4610 |
4553 #undef __ | 4611 #undef __ |
4554 | 4612 |
4555 } } // namespace v8::internal | 4613 } } // namespace v8::internal |
OLD | NEW |