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 1024 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1035 RecordSafepointWithRegistersAndDoubles(instr->pointer_map(), | 1035 RecordSafepointWithRegistersAndDoubles(instr->pointer_map(), |
1036 0, | 1036 0, |
1037 Safepoint::kNoDeoptimizationIndex); | 1037 Safepoint::kNoDeoptimizationIndex); |
1038 // Overwrite the stored value of r0 with the result of the stub. | 1038 // Overwrite the stored value of r0 with the result of the stub. |
1039 __ StoreToSafepointRegistersAndDoublesSlot(r0, r0); | 1039 __ StoreToSafepointRegistersAndDoublesSlot(r0, r0); |
1040 __ PopSafepointRegistersAndDoubles(); | 1040 __ PopSafepointRegistersAndDoubles(); |
1041 } | 1041 } |
1042 | 1042 |
1043 | 1043 |
1044 void LCodeGen::DoMulI(LMulI* instr) { | 1044 void LCodeGen::DoMulI(LMulI* instr) { |
| 1045 LOperand* left_op = instr->InputAt(0); |
| 1046 LOperand* right_op = instr->InputAt(1); |
| 1047 |
1045 Register scratch = scratch0(); | 1048 Register scratch = scratch0(); |
1046 Register left = ToRegister(instr->InputAt(0)); | 1049 Register left = ToRegister(left_op); |
1047 Register right = EmitLoadRegister(instr->InputAt(1), scratch); | |
1048 | 1050 |
1049 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero) && | 1051 ASSERT(left_op->Equals(instr->result())); |
1050 !instr->InputAt(1)->IsConstantOperand()) { | |
1051 __ orr(ToRegister(instr->TempAt(0)), left, right); | |
1052 } | |
1053 | 1052 |
1054 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { | 1053 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); |
1055 // scratch:left = left * right. | 1054 bool bailout_on_minus_zero = |
1056 __ smull(left, scratch, left, right); | 1055 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero); |
1057 __ mov(ip, Operand(left, ASR, 31)); | 1056 |
1058 __ cmp(ip, Operand(scratch)); | 1057 if (right_op->IsConstantOperand()) { |
1059 DeoptimizeIf(ne, instr->environment()); | 1058 // Use optimized code for specific constants. |
| 1059 int32_t constant = ToInteger32(LConstantOperand::cast(right_op)); |
| 1060 Condition overflow_deopt_cond = kNoCondition; |
| 1061 |
| 1062 switch (constant) { |
| 1063 case -1: |
| 1064 overflow_deopt_cond = can_overflow ? vs : kNoCondition; |
| 1065 __ rsb(left, |
| 1066 left, |
| 1067 Operand(0), |
| 1068 can_overflow ? SetCC : LeaveCC); |
| 1069 break; |
| 1070 case 0: |
| 1071 if (bailout_on_minus_zero) { |
| 1072 // If left is strictly negative and the constant is null, the |
| 1073 // result is -0. Deoptimize if required, otherwise return 0. |
| 1074 __ cmp(left, Operand(0)); |
| 1075 DeoptimizeIf(mi, instr->environment()); |
| 1076 } |
| 1077 __ mov(left, Operand(0)); |
| 1078 break; |
| 1079 case 1: |
| 1080 // Do nothing. |
| 1081 break; |
| 1082 default: |
| 1083 // Multiplying by powers of two and powers of two plus or minus |
| 1084 // one can be done faster with shifted operands. |
| 1085 // For other constants we emit standard code. |
| 1086 int32_t mask = constant >> 31; |
| 1087 uint32_t constant_abs = (constant + mask) ^ mask; |
| 1088 |
| 1089 if (IsPowerOf2(constant_abs)) { |
| 1090 if (!can_overflow) { |
| 1091 int32_t shift = WhichPowerOf2(constant_abs); |
| 1092 __ mov(left, Operand(left, LSL, shift)); |
| 1093 if (constant < 0) __ rsb(left, left, Operand(0)); |
| 1094 } else { |
| 1095 // scratch:left = left * constant. |
| 1096 __ mov(ip, Operand(constant)); |
| 1097 __ smull(left, scratch, left, ip); |
| 1098 __ cmp(scratch, Operand(left, ASR, 31)); |
| 1099 overflow_deopt_cond = ne; |
| 1100 } |
| 1101 } else if (IsPowerOf2(constant_abs - 1)) { |
| 1102 int32_t shift = WhichPowerOf2(constant_abs - 1); |
| 1103 __ add(left, |
| 1104 left, |
| 1105 Operand(left, LSL, shift), |
| 1106 can_overflow ? SetCC : LeaveCC); |
| 1107 overflow_deopt_cond = can_overflow ? vs : kNoCondition; |
| 1108 if (constant < 0) __ rsb(left, left, Operand(0)); |
| 1109 } else if (IsPowerOf2(constant_abs + 1)) { |
| 1110 int32_t shift = WhichPowerOf2(constant_abs + 1); |
| 1111 __ rsb(left, |
| 1112 left, |
| 1113 Operand(left, LSL, shift), |
| 1114 can_overflow ? SetCC : LeaveCC); |
| 1115 overflow_deopt_cond = can_overflow ? vs : kNoCondition; |
| 1116 if (constant < 0) __ rsb(left, left, Operand(0)); |
| 1117 } else { |
| 1118 if (!can_overflow) { |
| 1119 __ mov(ip, Operand(constant)); |
| 1120 __ mul(left, left, ip); |
| 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 } |
| 1129 break; |
| 1130 } |
| 1131 |
| 1132 |
| 1133 if (can_overflow && (constant != 0) && (constant != 1)) { |
| 1134 ASSERT(overflow_deopt_cond != kNoCondition); |
| 1135 DeoptimizeIf(overflow_deopt_cond, instr->environment()); |
| 1136 } |
| 1137 |
| 1138 if (bailout_on_minus_zero && (constant < 0)) { |
| 1139 // The case of a null constant was handled separately. |
| 1140 // If constant is negative and left is null, the result should be -0. |
| 1141 __ cmp(left, Operand(0)); |
| 1142 DeoptimizeIf(eq, instr->environment()); |
| 1143 } |
| 1144 |
1060 } else { | 1145 } else { |
1061 __ mul(left, left, right); | 1146 Register right = EmitLoadRegister(right_op, scratch); |
1062 } | 1147 if (bailout_on_minus_zero) { |
| 1148 __ orr(ToRegister(instr->TempAt(0)), left, right); |
| 1149 } |
1063 | 1150 |
1064 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1151 if (can_overflow) { |
1065 // Bail out if the result is supposed to be negative zero. | 1152 // scratch:left = left * right. |
1066 Label done; | 1153 __ smull(left, scratch, left, right); |
1067 __ cmp(left, Operand(0)); | 1154 __ cmp(scratch, Operand(left, ASR, 31)); |
1068 __ b(ne, &done); | 1155 DeoptimizeIf(ne, instr->environment()); |
1069 if (instr->InputAt(1)->IsConstantOperand()) { | |
1070 if (ToInteger32(LConstantOperand::cast(instr->InputAt(1))) <= 0) { | |
1071 DeoptimizeIf(al, instr->environment()); | |
1072 } | |
1073 } else { | 1156 } else { |
1074 // Test the non-zero operand for negative sign. | 1157 __ mul(left, left, right); |
| 1158 } |
| 1159 |
| 1160 if (bailout_on_minus_zero) { |
| 1161 // Bail out if the result is supposed to be negative zero. |
| 1162 Label done; |
| 1163 __ cmp(left, Operand(0)); |
| 1164 __ b(ne, &done); |
1075 __ cmp(ToRegister(instr->TempAt(0)), Operand(0)); | 1165 __ cmp(ToRegister(instr->TempAt(0)), Operand(0)); |
1076 DeoptimizeIf(mi, instr->environment()); | 1166 DeoptimizeIf(mi, instr->environment()); |
| 1167 __ bind(&done); |
1077 } | 1168 } |
1078 __ bind(&done); | |
1079 } | 1169 } |
1080 } | 1170 } |
1081 | 1171 |
1082 | 1172 |
1083 void LCodeGen::DoBitI(LBitI* instr) { | 1173 void LCodeGen::DoBitI(LBitI* instr) { |
1084 LOperand* left = instr->InputAt(0); | 1174 LOperand* left = instr->InputAt(0); |
1085 LOperand* right = instr->InputAt(1); | 1175 LOperand* right = instr->InputAt(1); |
1086 ASSERT(left->Equals(instr->result())); | 1176 ASSERT(left->Equals(instr->result())); |
1087 ASSERT(left->IsRegister()); | 1177 ASSERT(left->IsRegister()); |
1088 Register result = ToRegister(left); | 1178 Register result = ToRegister(left); |
(...skipping 3012 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4101 ASSERT(!environment->HasBeenRegistered()); | 4191 ASSERT(!environment->HasBeenRegistered()); |
4102 RegisterEnvironmentForDeoptimization(environment); | 4192 RegisterEnvironmentForDeoptimization(environment); |
4103 ASSERT(osr_pc_offset_ == -1); | 4193 ASSERT(osr_pc_offset_ == -1); |
4104 osr_pc_offset_ = masm()->pc_offset(); | 4194 osr_pc_offset_ = masm()->pc_offset(); |
4105 } | 4195 } |
4106 | 4196 |
4107 | 4197 |
4108 #undef __ | 4198 #undef __ |
4109 | 4199 |
4110 } } // namespace v8::internal | 4200 } } // namespace v8::internal |
OLD | NEW |