| 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 1051 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1062 __ CallStub(&stub); | 1062 __ CallStub(&stub); |
| 1063 RecordSafepointWithRegistersAndDoubles(instr->pointer_map(), | 1063 RecordSafepointWithRegistersAndDoubles(instr->pointer_map(), |
| 1064 0, | 1064 0, |
| 1065 Safepoint::kNoDeoptimizationIndex); | 1065 Safepoint::kNoDeoptimizationIndex); |
| 1066 // Overwrite the stored value of r0 with the result of the stub. | 1066 // Overwrite the stored value of r0 with the result of the stub. |
| 1067 __ StoreToSafepointRegistersAndDoublesSlot(r0, r0); | 1067 __ StoreToSafepointRegistersAndDoublesSlot(r0, r0); |
| 1068 } | 1068 } |
| 1069 | 1069 |
| 1070 | 1070 |
| 1071 void LCodeGen::DoMulI(LMulI* instr) { | 1071 void LCodeGen::DoMulI(LMulI* instr) { |
| 1072 LOperand* left_op = instr->InputAt(0); | 1072 Register scratch = scratch0(); |
| 1073 LOperand* right_op = instr->InputAt(1); | 1073 Register left = ToRegister(instr->InputAt(0)); |
| 1074 Register right = EmitLoadRegister(instr->InputAt(1), scratch); |
| 1074 | 1075 |
| 1075 Register scratch = scratch0(); | 1076 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero) && |
| 1076 Register left = ToRegister(left_op); | 1077 !instr->InputAt(1)->IsConstantOperand()) { |
| 1078 __ orr(ToRegister(instr->TempAt(0)), left, right); |
| 1079 } |
| 1077 | 1080 |
| 1078 ASSERT(left_op->Equals(instr->result())); | 1081 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |
| 1082 // scratch:left = left * right. |
| 1083 __ smull(left, scratch, left, right); |
| 1084 __ mov(ip, Operand(left, ASR, 31)); |
| 1085 __ cmp(ip, Operand(scratch)); |
| 1086 DeoptimizeIf(ne, instr->environment()); |
| 1087 } else { |
| 1088 __ mul(left, left, right); |
| 1089 } |
| 1079 | 1090 |
| 1080 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); | 1091 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1081 bool bailout_on_minus_zero = | 1092 // Bail out if the result is supposed to be negative zero. |
| 1082 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero); | 1093 Label done; |
| 1083 | 1094 __ cmp(left, Operand(0)); |
| 1084 if (right_op->IsConstantOperand()) { | 1095 __ b(ne, &done); |
| 1085 // Use optimized code for specific constants. | 1096 if (instr->InputAt(1)->IsConstantOperand()) { |
| 1086 int32_t constant = ToInteger32(LConstantOperand::cast(right_op)); | 1097 if (ToInteger32(LConstantOperand::cast(instr->InputAt(1))) <= 0) { |
| 1087 Condition overflow_deopt_cond = kNoCondition; | 1098 DeoptimizeIf(al, instr->environment()); |
| 1088 | 1099 } |
| 1089 switch (constant) { | |
| 1090 case -1: | |
| 1091 overflow_deopt_cond = can_overflow ? vs : kNoCondition; | |
| 1092 __ rsb(left, | |
| 1093 left, | |
| 1094 Operand(0), | |
| 1095 can_overflow ? SetCC : LeaveCC); | |
| 1096 break; | |
| 1097 case 0: | |
| 1098 if (bailout_on_minus_zero) { | |
| 1099 // If left is strictly negative and the constant is null, the | |
| 1100 // result is -0. Deoptimize if required, otherwise return 0. | |
| 1101 __ cmp(left, Operand(0)); | |
| 1102 DeoptimizeIf(mi, instr->environment()); | |
| 1103 } | |
| 1104 __ mov(left, Operand(0)); | |
| 1105 break; | |
| 1106 case 1: | |
| 1107 // Do nothing. | |
| 1108 break; | |
| 1109 default: | |
| 1110 // Multiplying by powers of two and powers of two plus or minus | |
| 1111 // one can be done faster with shifted operands. | |
| 1112 // For other constants we emit standard code. | |
| 1113 int32_t mask = constant >> 31; | |
| 1114 uint32_t constant_abs = (constant + mask) ^ mask; | |
| 1115 | |
| 1116 if (IsPowerOf2(constant_abs)) { | |
| 1117 if (!can_overflow) { | |
| 1118 int32_t shift = WhichPowerOf2(constant_abs); | |
| 1119 __ mov(left, Operand(left, LSL, shift)); | |
| 1120 if (constant < 0) __ rsb(left, left, Operand(0)); | |
| 1121 } else { | |
| 1122 // scratch:left = left * constant. | |
| 1123 __ mov(ip, Operand(constant)); | |
| 1124 __ smull(left, scratch, left, ip); | |
| 1125 __ cmp(scratch, Operand(left, ASR, 31)); | |
| 1126 overflow_deopt_cond = ne; | |
| 1127 } | |
| 1128 } else if (IsPowerOf2(constant_abs - 1)) { | |
| 1129 int32_t shift = WhichPowerOf2(constant_abs - 1); | |
| 1130 __ add(left, | |
| 1131 left, | |
| 1132 Operand(left, LSL, shift), | |
| 1133 can_overflow ? SetCC : LeaveCC); | |
| 1134 overflow_deopt_cond = can_overflow ? vs : kNoCondition; | |
| 1135 if (constant < 0) __ rsb(left, left, Operand(0)); | |
| 1136 } else if (IsPowerOf2(constant_abs + 1)) { | |
| 1137 int32_t shift = WhichPowerOf2(constant_abs + 1); | |
| 1138 __ rsb(left, | |
| 1139 left, | |
| 1140 Operand(left, LSL, shift), | |
| 1141 can_overflow ? SetCC : LeaveCC); | |
| 1142 overflow_deopt_cond = can_overflow ? vs : kNoCondition; | |
| 1143 if (constant < 0) __ rsb(left, left, Operand(0)); | |
| 1144 } else { | |
| 1145 if (!can_overflow) { | |
| 1146 __ mov(ip, Operand(constant)); | |
| 1147 __ mul(left, left, ip); | |
| 1148 } else { | |
| 1149 // scratch:left = left * constant. | |
| 1150 __ mov(ip, Operand(constant)); | |
| 1151 __ smull(left, scratch, left, ip); | |
| 1152 __ cmp(scratch, Operand(left, ASR, 31)); | |
| 1153 overflow_deopt_cond = ne; | |
| 1154 } | |
| 1155 } | |
| 1156 break; | |
| 1157 } | |
| 1158 | |
| 1159 | |
| 1160 if (can_overflow && (constant != 0) && (constant != 1)) { | |
| 1161 ASSERT(overflow_deopt_cond != kNoCondition); | |
| 1162 DeoptimizeIf(overflow_deopt_cond, instr->environment()); | |
| 1163 } | |
| 1164 | |
| 1165 if (bailout_on_minus_zero && (constant < 0)) { | |
| 1166 // The case of a null constant was handled separately. | |
| 1167 // If constant is negative and left is null, the result should be -0. | |
| 1168 __ cmp(left, Operand(0)); | |
| 1169 DeoptimizeIf(eq, instr->environment()); | |
| 1170 } | |
| 1171 | |
| 1172 } else { | |
| 1173 Register right = EmitLoadRegister(right_op, scratch); | |
| 1174 if (bailout_on_minus_zero) { | |
| 1175 __ orr(ToRegister(instr->TempAt(0)), left, right); | |
| 1176 } | |
| 1177 | |
| 1178 if (can_overflow) { | |
| 1179 // scratch:left = left * right. | |
| 1180 __ smull(left, scratch, left, right); | |
| 1181 __ cmp(scratch, Operand(left, ASR, 31)); | |
| 1182 DeoptimizeIf(ne, instr->environment()); | |
| 1183 } else { | 1100 } else { |
| 1184 __ mul(left, left, right); | 1101 // Test the non-zero operand for negative sign. |
| 1185 } | |
| 1186 | |
| 1187 if (bailout_on_minus_zero) { | |
| 1188 // Bail out if the result is supposed to be negative zero. | |
| 1189 Label done; | |
| 1190 __ cmp(left, Operand(0)); | |
| 1191 __ b(ne, &done); | |
| 1192 __ cmp(ToRegister(instr->TempAt(0)), Operand(0)); | 1102 __ cmp(ToRegister(instr->TempAt(0)), Operand(0)); |
| 1193 DeoptimizeIf(mi, instr->environment()); | 1103 DeoptimizeIf(mi, instr->environment()); |
| 1194 __ bind(&done); | |
| 1195 } | 1104 } |
| 1105 __ bind(&done); |
| 1196 } | 1106 } |
| 1197 } | 1107 } |
| 1198 | 1108 |
| 1199 | 1109 |
| 1200 void LCodeGen::DoBitI(LBitI* instr) { | 1110 void LCodeGen::DoBitI(LBitI* instr) { |
| 1201 LOperand* left = instr->InputAt(0); | 1111 LOperand* left = instr->InputAt(0); |
| 1202 LOperand* right = instr->InputAt(1); | 1112 LOperand* right = instr->InputAt(1); |
| 1203 ASSERT(left->Equals(instr->result())); | 1113 ASSERT(left->Equals(instr->result())); |
| 1204 ASSERT(left->IsRegister()); | 1114 ASSERT(left->IsRegister()); |
| 1205 Register result = ToRegister(left); | 1115 Register result = ToRegister(left); |
| (...skipping 3082 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4288 ASSERT(!environment->HasBeenRegistered()); | 4198 ASSERT(!environment->HasBeenRegistered()); |
| 4289 RegisterEnvironmentForDeoptimization(environment); | 4199 RegisterEnvironmentForDeoptimization(environment); |
| 4290 ASSERT(osr_pc_offset_ == -1); | 4200 ASSERT(osr_pc_offset_ == -1); |
| 4291 osr_pc_offset_ = masm()->pc_offset(); | 4201 osr_pc_offset_ = masm()->pc_offset(); |
| 4292 } | 4202 } |
| 4293 | 4203 |
| 4294 | 4204 |
| 4295 #undef __ | 4205 #undef __ |
| 4296 | 4206 |
| 4297 } } // namespace v8::internal | 4207 } } // namespace v8::internal |
| OLD | NEW |