OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_IA32 | 7 #if V8_TARGET_ARCH_IA32 |
8 | 8 |
9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
10 #include "src/code-factory.h" | 10 #include "src/code-factory.h" |
(...skipping 807 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
818 int deoptimization_index = deoptimizations_.length(); | 818 int deoptimization_index = deoptimizations_.length(); |
819 int pc_offset = masm()->pc_offset(); | 819 int pc_offset = masm()->pc_offset(); |
820 environment->Register(deoptimization_index, | 820 environment->Register(deoptimization_index, |
821 translation.index(), | 821 translation.index(), |
822 (mode == Safepoint::kLazyDeopt) ? pc_offset : -1); | 822 (mode == Safepoint::kLazyDeopt) ? pc_offset : -1); |
823 deoptimizations_.Add(environment, zone()); | 823 deoptimizations_.Add(environment, zone()); |
824 } | 824 } |
825 } | 825 } |
826 | 826 |
827 | 827 |
828 void LCodeGen::DeoptimizeIf(Condition cc, | 828 void LCodeGen::DeoptimizeIf(Condition cc, LInstruction* instr, |
829 LEnvironment* environment, | |
830 Deoptimizer::BailoutType bailout_type) { | 829 Deoptimizer::BailoutType bailout_type) { |
| 830 LEnvironment* environment = instr->environment(); |
831 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); | 831 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); |
832 DCHECK(environment->HasBeenRegistered()); | 832 DCHECK(environment->HasBeenRegistered()); |
833 int id = environment->deoptimization_index(); | 833 int id = environment->deoptimization_index(); |
834 DCHECK(info()->IsOptimizing() || info()->IsStub()); | 834 DCHECK(info()->IsOptimizing() || info()->IsStub()); |
835 Address entry = | 835 Address entry = |
836 Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type); | 836 Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type); |
837 if (entry == NULL) { | 837 if (entry == NULL) { |
838 Abort(kBailoutWasNotPrepared); | 838 Abort(kBailoutWasNotPrepared); |
839 return; | 839 return; |
840 } | 840 } |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
884 } | 884 } |
885 if (cc == no_condition) { | 885 if (cc == no_condition) { |
886 __ jmp(&jump_table_.last().label); | 886 __ jmp(&jump_table_.last().label); |
887 } else { | 887 } else { |
888 __ j(cc, &jump_table_.last().label); | 888 __ j(cc, &jump_table_.last().label); |
889 } | 889 } |
890 } | 890 } |
891 } | 891 } |
892 | 892 |
893 | 893 |
894 void LCodeGen::DeoptimizeIf(Condition cc, | 894 void LCodeGen::DeoptimizeIf(Condition cc, LInstruction* instr) { |
895 LEnvironment* environment) { | |
896 Deoptimizer::BailoutType bailout_type = info()->IsStub() | 895 Deoptimizer::BailoutType bailout_type = info()->IsStub() |
897 ? Deoptimizer::LAZY | 896 ? Deoptimizer::LAZY |
898 : Deoptimizer::EAGER; | 897 : Deoptimizer::EAGER; |
899 DeoptimizeIf(cc, environment, bailout_type); | 898 DeoptimizeIf(cc, instr, bailout_type); |
900 } | 899 } |
901 | 900 |
902 | 901 |
903 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { | 902 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { |
904 int length = deoptimizations_.length(); | 903 int length = deoptimizations_.length(); |
905 if (length == 0) return; | 904 if (length == 0) return; |
906 Handle<DeoptimizationInputData> data = | 905 Handle<DeoptimizationInputData> data = |
907 DeoptimizationInputData::New(isolate(), length, TENURED); | 906 DeoptimizationInputData::New(isolate(), length, TENURED); |
908 | 907 |
909 Handle<ByteArray> translations = | 908 Handle<ByteArray> translations = |
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1118 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); | 1117 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); |
1119 Label dividend_is_not_negative, done; | 1118 Label dividend_is_not_negative, done; |
1120 if (hmod->CheckFlag(HValue::kLeftCanBeNegative)) { | 1119 if (hmod->CheckFlag(HValue::kLeftCanBeNegative)) { |
1121 __ test(dividend, dividend); | 1120 __ test(dividend, dividend); |
1122 __ j(not_sign, ÷nd_is_not_negative, Label::kNear); | 1121 __ j(not_sign, ÷nd_is_not_negative, Label::kNear); |
1123 // Note that this is correct even for kMinInt operands. | 1122 // Note that this is correct even for kMinInt operands. |
1124 __ neg(dividend); | 1123 __ neg(dividend); |
1125 __ and_(dividend, mask); | 1124 __ and_(dividend, mask); |
1126 __ neg(dividend); | 1125 __ neg(dividend); |
1127 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1126 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1128 DeoptimizeIf(zero, instr->environment()); | 1127 DeoptimizeIf(zero, instr); |
1129 } | 1128 } |
1130 __ jmp(&done, Label::kNear); | 1129 __ jmp(&done, Label::kNear); |
1131 } | 1130 } |
1132 | 1131 |
1133 __ bind(÷nd_is_not_negative); | 1132 __ bind(÷nd_is_not_negative); |
1134 __ and_(dividend, mask); | 1133 __ and_(dividend, mask); |
1135 __ bind(&done); | 1134 __ bind(&done); |
1136 } | 1135 } |
1137 | 1136 |
1138 | 1137 |
1139 void LCodeGen::DoModByConstI(LModByConstI* instr) { | 1138 void LCodeGen::DoModByConstI(LModByConstI* instr) { |
1140 Register dividend = ToRegister(instr->dividend()); | 1139 Register dividend = ToRegister(instr->dividend()); |
1141 int32_t divisor = instr->divisor(); | 1140 int32_t divisor = instr->divisor(); |
1142 DCHECK(ToRegister(instr->result()).is(eax)); | 1141 DCHECK(ToRegister(instr->result()).is(eax)); |
1143 | 1142 |
1144 if (divisor == 0) { | 1143 if (divisor == 0) { |
1145 DeoptimizeIf(no_condition, instr->environment()); | 1144 DeoptimizeIf(no_condition, instr); |
1146 return; | 1145 return; |
1147 } | 1146 } |
1148 | 1147 |
1149 __ TruncatingDiv(dividend, Abs(divisor)); | 1148 __ TruncatingDiv(dividend, Abs(divisor)); |
1150 __ imul(edx, edx, Abs(divisor)); | 1149 __ imul(edx, edx, Abs(divisor)); |
1151 __ mov(eax, dividend); | 1150 __ mov(eax, dividend); |
1152 __ sub(eax, edx); | 1151 __ sub(eax, edx); |
1153 | 1152 |
1154 // Check for negative zero. | 1153 // Check for negative zero. |
1155 HMod* hmod = instr->hydrogen(); | 1154 HMod* hmod = instr->hydrogen(); |
1156 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1155 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1157 Label remainder_not_zero; | 1156 Label remainder_not_zero; |
1158 __ j(not_zero, &remainder_not_zero, Label::kNear); | 1157 __ j(not_zero, &remainder_not_zero, Label::kNear); |
1159 __ cmp(dividend, Immediate(0)); | 1158 __ cmp(dividend, Immediate(0)); |
1160 DeoptimizeIf(less, instr->environment()); | 1159 DeoptimizeIf(less, instr); |
1161 __ bind(&remainder_not_zero); | 1160 __ bind(&remainder_not_zero); |
1162 } | 1161 } |
1163 } | 1162 } |
1164 | 1163 |
1165 | 1164 |
1166 void LCodeGen::DoModI(LModI* instr) { | 1165 void LCodeGen::DoModI(LModI* instr) { |
1167 HMod* hmod = instr->hydrogen(); | 1166 HMod* hmod = instr->hydrogen(); |
1168 | 1167 |
1169 Register left_reg = ToRegister(instr->left()); | 1168 Register left_reg = ToRegister(instr->left()); |
1170 DCHECK(left_reg.is(eax)); | 1169 DCHECK(left_reg.is(eax)); |
1171 Register right_reg = ToRegister(instr->right()); | 1170 Register right_reg = ToRegister(instr->right()); |
1172 DCHECK(!right_reg.is(eax)); | 1171 DCHECK(!right_reg.is(eax)); |
1173 DCHECK(!right_reg.is(edx)); | 1172 DCHECK(!right_reg.is(edx)); |
1174 Register result_reg = ToRegister(instr->result()); | 1173 Register result_reg = ToRegister(instr->result()); |
1175 DCHECK(result_reg.is(edx)); | 1174 DCHECK(result_reg.is(edx)); |
1176 | 1175 |
1177 Label done; | 1176 Label done; |
1178 // Check for x % 0, idiv would signal a divide error. We have to | 1177 // Check for x % 0, idiv would signal a divide error. We have to |
1179 // deopt in this case because we can't return a NaN. | 1178 // deopt in this case because we can't return a NaN. |
1180 if (hmod->CheckFlag(HValue::kCanBeDivByZero)) { | 1179 if (hmod->CheckFlag(HValue::kCanBeDivByZero)) { |
1181 __ test(right_reg, Operand(right_reg)); | 1180 __ test(right_reg, Operand(right_reg)); |
1182 DeoptimizeIf(zero, instr->environment()); | 1181 DeoptimizeIf(zero, instr); |
1183 } | 1182 } |
1184 | 1183 |
1185 // Check for kMinInt % -1, idiv would signal a divide error. We | 1184 // Check for kMinInt % -1, idiv would signal a divide error. We |
1186 // have to deopt if we care about -0, because we can't return that. | 1185 // have to deopt if we care about -0, because we can't return that. |
1187 if (hmod->CheckFlag(HValue::kCanOverflow)) { | 1186 if (hmod->CheckFlag(HValue::kCanOverflow)) { |
1188 Label no_overflow_possible; | 1187 Label no_overflow_possible; |
1189 __ cmp(left_reg, kMinInt); | 1188 __ cmp(left_reg, kMinInt); |
1190 __ j(not_equal, &no_overflow_possible, Label::kNear); | 1189 __ j(not_equal, &no_overflow_possible, Label::kNear); |
1191 __ cmp(right_reg, -1); | 1190 __ cmp(right_reg, -1); |
1192 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1191 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1193 DeoptimizeIf(equal, instr->environment()); | 1192 DeoptimizeIf(equal, instr); |
1194 } else { | 1193 } else { |
1195 __ j(not_equal, &no_overflow_possible, Label::kNear); | 1194 __ j(not_equal, &no_overflow_possible, Label::kNear); |
1196 __ Move(result_reg, Immediate(0)); | 1195 __ Move(result_reg, Immediate(0)); |
1197 __ jmp(&done, Label::kNear); | 1196 __ jmp(&done, Label::kNear); |
1198 } | 1197 } |
1199 __ bind(&no_overflow_possible); | 1198 __ bind(&no_overflow_possible); |
1200 } | 1199 } |
1201 | 1200 |
1202 // Sign extend dividend in eax into edx:eax. | 1201 // Sign extend dividend in eax into edx:eax. |
1203 __ cdq(); | 1202 __ cdq(); |
1204 | 1203 |
1205 // If we care about -0, test if the dividend is <0 and the result is 0. | 1204 // If we care about -0, test if the dividend is <0 and the result is 0. |
1206 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1205 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1207 Label positive_left; | 1206 Label positive_left; |
1208 __ test(left_reg, Operand(left_reg)); | 1207 __ test(left_reg, Operand(left_reg)); |
1209 __ j(not_sign, &positive_left, Label::kNear); | 1208 __ j(not_sign, &positive_left, Label::kNear); |
1210 __ idiv(right_reg); | 1209 __ idiv(right_reg); |
1211 __ test(result_reg, Operand(result_reg)); | 1210 __ test(result_reg, Operand(result_reg)); |
1212 DeoptimizeIf(zero, instr->environment()); | 1211 DeoptimizeIf(zero, instr); |
1213 __ jmp(&done, Label::kNear); | 1212 __ jmp(&done, Label::kNear); |
1214 __ bind(&positive_left); | 1213 __ bind(&positive_left); |
1215 } | 1214 } |
1216 __ idiv(right_reg); | 1215 __ idiv(right_reg); |
1217 __ bind(&done); | 1216 __ bind(&done); |
1218 } | 1217 } |
1219 | 1218 |
1220 | 1219 |
1221 void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) { | 1220 void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) { |
1222 Register dividend = ToRegister(instr->dividend()); | 1221 Register dividend = ToRegister(instr->dividend()); |
1223 int32_t divisor = instr->divisor(); | 1222 int32_t divisor = instr->divisor(); |
1224 Register result = ToRegister(instr->result()); | 1223 Register result = ToRegister(instr->result()); |
1225 DCHECK(divisor == kMinInt || base::bits::IsPowerOfTwo32(Abs(divisor))); | 1224 DCHECK(divisor == kMinInt || base::bits::IsPowerOfTwo32(Abs(divisor))); |
1226 DCHECK(!result.is(dividend)); | 1225 DCHECK(!result.is(dividend)); |
1227 | 1226 |
1228 // Check for (0 / -x) that will produce negative zero. | 1227 // Check for (0 / -x) that will produce negative zero. |
1229 HDiv* hdiv = instr->hydrogen(); | 1228 HDiv* hdiv = instr->hydrogen(); |
1230 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { | 1229 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { |
1231 __ test(dividend, dividend); | 1230 __ test(dividend, dividend); |
1232 DeoptimizeIf(zero, instr->environment()); | 1231 DeoptimizeIf(zero, instr); |
1233 } | 1232 } |
1234 // Check for (kMinInt / -1). | 1233 // Check for (kMinInt / -1). |
1235 if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) { | 1234 if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) { |
1236 __ cmp(dividend, kMinInt); | 1235 __ cmp(dividend, kMinInt); |
1237 DeoptimizeIf(zero, instr->environment()); | 1236 DeoptimizeIf(zero, instr); |
1238 } | 1237 } |
1239 // Deoptimize if remainder will not be 0. | 1238 // Deoptimize if remainder will not be 0. |
1240 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) && | 1239 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) && |
1241 divisor != 1 && divisor != -1) { | 1240 divisor != 1 && divisor != -1) { |
1242 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); | 1241 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); |
1243 __ test(dividend, Immediate(mask)); | 1242 __ test(dividend, Immediate(mask)); |
1244 DeoptimizeIf(not_zero, instr->environment()); | 1243 DeoptimizeIf(not_zero, instr); |
1245 } | 1244 } |
1246 __ Move(result, dividend); | 1245 __ Move(result, dividend); |
1247 int32_t shift = WhichPowerOf2Abs(divisor); | 1246 int32_t shift = WhichPowerOf2Abs(divisor); |
1248 if (shift > 0) { | 1247 if (shift > 0) { |
1249 // The arithmetic shift is always OK, the 'if' is an optimization only. | 1248 // The arithmetic shift is always OK, the 'if' is an optimization only. |
1250 if (shift > 1) __ sar(result, 31); | 1249 if (shift > 1) __ sar(result, 31); |
1251 __ shr(result, 32 - shift); | 1250 __ shr(result, 32 - shift); |
1252 __ add(result, dividend); | 1251 __ add(result, dividend); |
1253 __ sar(result, shift); | 1252 __ sar(result, shift); |
1254 } | 1253 } |
1255 if (divisor < 0) __ neg(result); | 1254 if (divisor < 0) __ neg(result); |
1256 } | 1255 } |
1257 | 1256 |
1258 | 1257 |
1259 void LCodeGen::DoDivByConstI(LDivByConstI* instr) { | 1258 void LCodeGen::DoDivByConstI(LDivByConstI* instr) { |
1260 Register dividend = ToRegister(instr->dividend()); | 1259 Register dividend = ToRegister(instr->dividend()); |
1261 int32_t divisor = instr->divisor(); | 1260 int32_t divisor = instr->divisor(); |
1262 DCHECK(ToRegister(instr->result()).is(edx)); | 1261 DCHECK(ToRegister(instr->result()).is(edx)); |
1263 | 1262 |
1264 if (divisor == 0) { | 1263 if (divisor == 0) { |
1265 DeoptimizeIf(no_condition, instr->environment()); | 1264 DeoptimizeIf(no_condition, instr); |
1266 return; | 1265 return; |
1267 } | 1266 } |
1268 | 1267 |
1269 // Check for (0 / -x) that will produce negative zero. | 1268 // Check for (0 / -x) that will produce negative zero. |
1270 HDiv* hdiv = instr->hydrogen(); | 1269 HDiv* hdiv = instr->hydrogen(); |
1271 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { | 1270 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { |
1272 __ test(dividend, dividend); | 1271 __ test(dividend, dividend); |
1273 DeoptimizeIf(zero, instr->environment()); | 1272 DeoptimizeIf(zero, instr); |
1274 } | 1273 } |
1275 | 1274 |
1276 __ TruncatingDiv(dividend, Abs(divisor)); | 1275 __ TruncatingDiv(dividend, Abs(divisor)); |
1277 if (divisor < 0) __ neg(edx); | 1276 if (divisor < 0) __ neg(edx); |
1278 | 1277 |
1279 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) { | 1278 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) { |
1280 __ mov(eax, edx); | 1279 __ mov(eax, edx); |
1281 __ imul(eax, eax, divisor); | 1280 __ imul(eax, eax, divisor); |
1282 __ sub(eax, dividend); | 1281 __ sub(eax, dividend); |
1283 DeoptimizeIf(not_equal, instr->environment()); | 1282 DeoptimizeIf(not_equal, instr); |
1284 } | 1283 } |
1285 } | 1284 } |
1286 | 1285 |
1287 | 1286 |
1288 // TODO(svenpanne) Refactor this to avoid code duplication with DoFlooringDivI. | 1287 // TODO(svenpanne) Refactor this to avoid code duplication with DoFlooringDivI. |
1289 void LCodeGen::DoDivI(LDivI* instr) { | 1288 void LCodeGen::DoDivI(LDivI* instr) { |
1290 HBinaryOperation* hdiv = instr->hydrogen(); | 1289 HBinaryOperation* hdiv = instr->hydrogen(); |
1291 Register dividend = ToRegister(instr->dividend()); | 1290 Register dividend = ToRegister(instr->dividend()); |
1292 Register divisor = ToRegister(instr->divisor()); | 1291 Register divisor = ToRegister(instr->divisor()); |
1293 Register remainder = ToRegister(instr->temp()); | 1292 Register remainder = ToRegister(instr->temp()); |
1294 DCHECK(dividend.is(eax)); | 1293 DCHECK(dividend.is(eax)); |
1295 DCHECK(remainder.is(edx)); | 1294 DCHECK(remainder.is(edx)); |
1296 DCHECK(ToRegister(instr->result()).is(eax)); | 1295 DCHECK(ToRegister(instr->result()).is(eax)); |
1297 DCHECK(!divisor.is(eax)); | 1296 DCHECK(!divisor.is(eax)); |
1298 DCHECK(!divisor.is(edx)); | 1297 DCHECK(!divisor.is(edx)); |
1299 | 1298 |
1300 // Check for x / 0. | 1299 // Check for x / 0. |
1301 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { | 1300 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { |
1302 __ test(divisor, divisor); | 1301 __ test(divisor, divisor); |
1303 DeoptimizeIf(zero, instr->environment()); | 1302 DeoptimizeIf(zero, instr); |
1304 } | 1303 } |
1305 | 1304 |
1306 // Check for (0 / -x) that will produce negative zero. | 1305 // Check for (0 / -x) that will produce negative zero. |
1307 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1306 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1308 Label dividend_not_zero; | 1307 Label dividend_not_zero; |
1309 __ test(dividend, dividend); | 1308 __ test(dividend, dividend); |
1310 __ j(not_zero, ÷nd_not_zero, Label::kNear); | 1309 __ j(not_zero, ÷nd_not_zero, Label::kNear); |
1311 __ test(divisor, divisor); | 1310 __ test(divisor, divisor); |
1312 DeoptimizeIf(sign, instr->environment()); | 1311 DeoptimizeIf(sign, instr); |
1313 __ bind(÷nd_not_zero); | 1312 __ bind(÷nd_not_zero); |
1314 } | 1313 } |
1315 | 1314 |
1316 // Check for (kMinInt / -1). | 1315 // Check for (kMinInt / -1). |
1317 if (hdiv->CheckFlag(HValue::kCanOverflow)) { | 1316 if (hdiv->CheckFlag(HValue::kCanOverflow)) { |
1318 Label dividend_not_min_int; | 1317 Label dividend_not_min_int; |
1319 __ cmp(dividend, kMinInt); | 1318 __ cmp(dividend, kMinInt); |
1320 __ j(not_zero, ÷nd_not_min_int, Label::kNear); | 1319 __ j(not_zero, ÷nd_not_min_int, Label::kNear); |
1321 __ cmp(divisor, -1); | 1320 __ cmp(divisor, -1); |
1322 DeoptimizeIf(zero, instr->environment()); | 1321 DeoptimizeIf(zero, instr); |
1323 __ bind(÷nd_not_min_int); | 1322 __ bind(÷nd_not_min_int); |
1324 } | 1323 } |
1325 | 1324 |
1326 // Sign extend to edx (= remainder). | 1325 // Sign extend to edx (= remainder). |
1327 __ cdq(); | 1326 __ cdq(); |
1328 __ idiv(divisor); | 1327 __ idiv(divisor); |
1329 | 1328 |
1330 if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { | 1329 if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { |
1331 // Deoptimize if remainder is not 0. | 1330 // Deoptimize if remainder is not 0. |
1332 __ test(remainder, remainder); | 1331 __ test(remainder, remainder); |
1333 DeoptimizeIf(not_zero, instr->environment()); | 1332 DeoptimizeIf(not_zero, instr); |
1334 } | 1333 } |
1335 } | 1334 } |
1336 | 1335 |
1337 | 1336 |
1338 void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) { | 1337 void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) { |
1339 Register dividend = ToRegister(instr->dividend()); | 1338 Register dividend = ToRegister(instr->dividend()); |
1340 int32_t divisor = instr->divisor(); | 1339 int32_t divisor = instr->divisor(); |
1341 DCHECK(dividend.is(ToRegister(instr->result()))); | 1340 DCHECK(dividend.is(ToRegister(instr->result()))); |
1342 | 1341 |
1343 // If the divisor is positive, things are easy: There can be no deopts and we | 1342 // If the divisor is positive, things are easy: There can be no deopts and we |
1344 // can simply do an arithmetic right shift. | 1343 // can simply do an arithmetic right shift. |
1345 if (divisor == 1) return; | 1344 if (divisor == 1) return; |
1346 int32_t shift = WhichPowerOf2Abs(divisor); | 1345 int32_t shift = WhichPowerOf2Abs(divisor); |
1347 if (divisor > 1) { | 1346 if (divisor > 1) { |
1348 __ sar(dividend, shift); | 1347 __ sar(dividend, shift); |
1349 return; | 1348 return; |
1350 } | 1349 } |
1351 | 1350 |
1352 // If the divisor is negative, we have to negate and handle edge cases. | 1351 // If the divisor is negative, we have to negate and handle edge cases. |
1353 __ neg(dividend); | 1352 __ neg(dividend); |
1354 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1353 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1355 DeoptimizeIf(zero, instr->environment()); | 1354 DeoptimizeIf(zero, instr); |
1356 } | 1355 } |
1357 | 1356 |
1358 // Dividing by -1 is basically negation, unless we overflow. | 1357 // Dividing by -1 is basically negation, unless we overflow. |
1359 if (divisor == -1) { | 1358 if (divisor == -1) { |
1360 if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { | 1359 if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { |
1361 DeoptimizeIf(overflow, instr->environment()); | 1360 DeoptimizeIf(overflow, instr); |
1362 } | 1361 } |
1363 return; | 1362 return; |
1364 } | 1363 } |
1365 | 1364 |
1366 // If the negation could not overflow, simply shifting is OK. | 1365 // If the negation could not overflow, simply shifting is OK. |
1367 if (!instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { | 1366 if (!instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { |
1368 __ sar(dividend, shift); | 1367 __ sar(dividend, shift); |
1369 return; | 1368 return; |
1370 } | 1369 } |
1371 | 1370 |
1372 Label not_kmin_int, done; | 1371 Label not_kmin_int, done; |
1373 __ j(no_overflow, ¬_kmin_int, Label::kNear); | 1372 __ j(no_overflow, ¬_kmin_int, Label::kNear); |
1374 __ mov(dividend, Immediate(kMinInt / divisor)); | 1373 __ mov(dividend, Immediate(kMinInt / divisor)); |
1375 __ jmp(&done, Label::kNear); | 1374 __ jmp(&done, Label::kNear); |
1376 __ bind(¬_kmin_int); | 1375 __ bind(¬_kmin_int); |
1377 __ sar(dividend, shift); | 1376 __ sar(dividend, shift); |
1378 __ bind(&done); | 1377 __ bind(&done); |
1379 } | 1378 } |
1380 | 1379 |
1381 | 1380 |
1382 void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) { | 1381 void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) { |
1383 Register dividend = ToRegister(instr->dividend()); | 1382 Register dividend = ToRegister(instr->dividend()); |
1384 int32_t divisor = instr->divisor(); | 1383 int32_t divisor = instr->divisor(); |
1385 DCHECK(ToRegister(instr->result()).is(edx)); | 1384 DCHECK(ToRegister(instr->result()).is(edx)); |
1386 | 1385 |
1387 if (divisor == 0) { | 1386 if (divisor == 0) { |
1388 DeoptimizeIf(no_condition, instr->environment()); | 1387 DeoptimizeIf(no_condition, instr); |
1389 return; | 1388 return; |
1390 } | 1389 } |
1391 | 1390 |
1392 // Check for (0 / -x) that will produce negative zero. | 1391 // Check for (0 / -x) that will produce negative zero. |
1393 HMathFloorOfDiv* hdiv = instr->hydrogen(); | 1392 HMathFloorOfDiv* hdiv = instr->hydrogen(); |
1394 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { | 1393 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { |
1395 __ test(dividend, dividend); | 1394 __ test(dividend, dividend); |
1396 DeoptimizeIf(zero, instr->environment()); | 1395 DeoptimizeIf(zero, instr); |
1397 } | 1396 } |
1398 | 1397 |
1399 // Easy case: We need no dynamic check for the dividend and the flooring | 1398 // Easy case: We need no dynamic check for the dividend and the flooring |
1400 // division is the same as the truncating division. | 1399 // division is the same as the truncating division. |
1401 if ((divisor > 0 && !hdiv->CheckFlag(HValue::kLeftCanBeNegative)) || | 1400 if ((divisor > 0 && !hdiv->CheckFlag(HValue::kLeftCanBeNegative)) || |
1402 (divisor < 0 && !hdiv->CheckFlag(HValue::kLeftCanBePositive))) { | 1401 (divisor < 0 && !hdiv->CheckFlag(HValue::kLeftCanBePositive))) { |
1403 __ TruncatingDiv(dividend, Abs(divisor)); | 1402 __ TruncatingDiv(dividend, Abs(divisor)); |
1404 if (divisor < 0) __ neg(edx); | 1403 if (divisor < 0) __ neg(edx); |
1405 return; | 1404 return; |
1406 } | 1405 } |
(...skipping 26 matching lines...) Expand all Loading... |
1433 Register result = ToRegister(instr->result()); | 1432 Register result = ToRegister(instr->result()); |
1434 DCHECK(dividend.is(eax)); | 1433 DCHECK(dividend.is(eax)); |
1435 DCHECK(remainder.is(edx)); | 1434 DCHECK(remainder.is(edx)); |
1436 DCHECK(result.is(eax)); | 1435 DCHECK(result.is(eax)); |
1437 DCHECK(!divisor.is(eax)); | 1436 DCHECK(!divisor.is(eax)); |
1438 DCHECK(!divisor.is(edx)); | 1437 DCHECK(!divisor.is(edx)); |
1439 | 1438 |
1440 // Check for x / 0. | 1439 // Check for x / 0. |
1441 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { | 1440 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { |
1442 __ test(divisor, divisor); | 1441 __ test(divisor, divisor); |
1443 DeoptimizeIf(zero, instr->environment()); | 1442 DeoptimizeIf(zero, instr); |
1444 } | 1443 } |
1445 | 1444 |
1446 // Check for (0 / -x) that will produce negative zero. | 1445 // Check for (0 / -x) that will produce negative zero. |
1447 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1446 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1448 Label dividend_not_zero; | 1447 Label dividend_not_zero; |
1449 __ test(dividend, dividend); | 1448 __ test(dividend, dividend); |
1450 __ j(not_zero, ÷nd_not_zero, Label::kNear); | 1449 __ j(not_zero, ÷nd_not_zero, Label::kNear); |
1451 __ test(divisor, divisor); | 1450 __ test(divisor, divisor); |
1452 DeoptimizeIf(sign, instr->environment()); | 1451 DeoptimizeIf(sign, instr); |
1453 __ bind(÷nd_not_zero); | 1452 __ bind(÷nd_not_zero); |
1454 } | 1453 } |
1455 | 1454 |
1456 // Check for (kMinInt / -1). | 1455 // Check for (kMinInt / -1). |
1457 if (hdiv->CheckFlag(HValue::kCanOverflow)) { | 1456 if (hdiv->CheckFlag(HValue::kCanOverflow)) { |
1458 Label dividend_not_min_int; | 1457 Label dividend_not_min_int; |
1459 __ cmp(dividend, kMinInt); | 1458 __ cmp(dividend, kMinInt); |
1460 __ j(not_zero, ÷nd_not_min_int, Label::kNear); | 1459 __ j(not_zero, ÷nd_not_min_int, Label::kNear); |
1461 __ cmp(divisor, -1); | 1460 __ cmp(divisor, -1); |
1462 DeoptimizeIf(zero, instr->environment()); | 1461 DeoptimizeIf(zero, instr); |
1463 __ bind(÷nd_not_min_int); | 1462 __ bind(÷nd_not_min_int); |
1464 } | 1463 } |
1465 | 1464 |
1466 // Sign extend to edx (= remainder). | 1465 // Sign extend to edx (= remainder). |
1467 __ cdq(); | 1466 __ cdq(); |
1468 __ idiv(divisor); | 1467 __ idiv(divisor); |
1469 | 1468 |
1470 Label done; | 1469 Label done; |
1471 __ test(remainder, remainder); | 1470 __ test(remainder, remainder); |
1472 __ j(zero, &done, Label::kNear); | 1471 __ j(zero, &done, Label::kNear); |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1530 __ imul(left, left, constant); | 1529 __ imul(left, left, constant); |
1531 } | 1530 } |
1532 } else { | 1531 } else { |
1533 if (instr->hydrogen()->representation().IsSmi()) { | 1532 if (instr->hydrogen()->representation().IsSmi()) { |
1534 __ SmiUntag(left); | 1533 __ SmiUntag(left); |
1535 } | 1534 } |
1536 __ imul(left, ToOperand(right)); | 1535 __ imul(left, ToOperand(right)); |
1537 } | 1536 } |
1538 | 1537 |
1539 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { | 1538 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |
1540 DeoptimizeIf(overflow, instr->environment()); | 1539 DeoptimizeIf(overflow, instr); |
1541 } | 1540 } |
1542 | 1541 |
1543 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1542 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1544 // Bail out if the result is supposed to be negative zero. | 1543 // Bail out if the result is supposed to be negative zero. |
1545 Label done; | 1544 Label done; |
1546 __ test(left, Operand(left)); | 1545 __ test(left, Operand(left)); |
1547 __ j(not_zero, &done, Label::kNear); | 1546 __ j(not_zero, &done, Label::kNear); |
1548 if (right->IsConstantOperand()) { | 1547 if (right->IsConstantOperand()) { |
1549 if (ToInteger32(LConstantOperand::cast(right)) < 0) { | 1548 if (ToInteger32(LConstantOperand::cast(right)) < 0) { |
1550 DeoptimizeIf(no_condition, instr->environment()); | 1549 DeoptimizeIf(no_condition, instr); |
1551 } else if (ToInteger32(LConstantOperand::cast(right)) == 0) { | 1550 } else if (ToInteger32(LConstantOperand::cast(right)) == 0) { |
1552 __ cmp(ToRegister(instr->temp()), Immediate(0)); | 1551 __ cmp(ToRegister(instr->temp()), Immediate(0)); |
1553 DeoptimizeIf(less, instr->environment()); | 1552 DeoptimizeIf(less, instr); |
1554 } | 1553 } |
1555 } else { | 1554 } else { |
1556 // Test the non-zero operand for negative sign. | 1555 // Test the non-zero operand for negative sign. |
1557 __ or_(ToRegister(instr->temp()), ToOperand(right)); | 1556 __ or_(ToRegister(instr->temp()), ToOperand(right)); |
1558 DeoptimizeIf(sign, instr->environment()); | 1557 DeoptimizeIf(sign, instr); |
1559 } | 1558 } |
1560 __ bind(&done); | 1559 __ bind(&done); |
1561 } | 1560 } |
1562 } | 1561 } |
1563 | 1562 |
1564 | 1563 |
1565 void LCodeGen::DoBitI(LBitI* instr) { | 1564 void LCodeGen::DoBitI(LBitI* instr) { |
1566 LOperand* left = instr->left(); | 1565 LOperand* left = instr->left(); |
1567 LOperand* right = instr->right(); | 1566 LOperand* right = instr->right(); |
1568 DCHECK(left->Equals(instr->result())); | 1567 DCHECK(left->Equals(instr->result())); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1615 DCHECK(left->Equals(instr->result())); | 1614 DCHECK(left->Equals(instr->result())); |
1616 DCHECK(left->IsRegister()); | 1615 DCHECK(left->IsRegister()); |
1617 if (right->IsRegister()) { | 1616 if (right->IsRegister()) { |
1618 DCHECK(ToRegister(right).is(ecx)); | 1617 DCHECK(ToRegister(right).is(ecx)); |
1619 | 1618 |
1620 switch (instr->op()) { | 1619 switch (instr->op()) { |
1621 case Token::ROR: | 1620 case Token::ROR: |
1622 __ ror_cl(ToRegister(left)); | 1621 __ ror_cl(ToRegister(left)); |
1623 if (instr->can_deopt()) { | 1622 if (instr->can_deopt()) { |
1624 __ test(ToRegister(left), ToRegister(left)); | 1623 __ test(ToRegister(left), ToRegister(left)); |
1625 DeoptimizeIf(sign, instr->environment()); | 1624 DeoptimizeIf(sign, instr); |
1626 } | 1625 } |
1627 break; | 1626 break; |
1628 case Token::SAR: | 1627 case Token::SAR: |
1629 __ sar_cl(ToRegister(left)); | 1628 __ sar_cl(ToRegister(left)); |
1630 break; | 1629 break; |
1631 case Token::SHR: | 1630 case Token::SHR: |
1632 __ shr_cl(ToRegister(left)); | 1631 __ shr_cl(ToRegister(left)); |
1633 if (instr->can_deopt()) { | 1632 if (instr->can_deopt()) { |
1634 __ test(ToRegister(left), ToRegister(left)); | 1633 __ test(ToRegister(left), ToRegister(left)); |
1635 DeoptimizeIf(sign, instr->environment()); | 1634 DeoptimizeIf(sign, instr); |
1636 } | 1635 } |
1637 break; | 1636 break; |
1638 case Token::SHL: | 1637 case Token::SHL: |
1639 __ shl_cl(ToRegister(left)); | 1638 __ shl_cl(ToRegister(left)); |
1640 break; | 1639 break; |
1641 default: | 1640 default: |
1642 UNREACHABLE(); | 1641 UNREACHABLE(); |
1643 break; | 1642 break; |
1644 } | 1643 } |
1645 } else { | 1644 } else { |
1646 int value = ToInteger32(LConstantOperand::cast(right)); | 1645 int value = ToInteger32(LConstantOperand::cast(right)); |
1647 uint8_t shift_count = static_cast<uint8_t>(value & 0x1F); | 1646 uint8_t shift_count = static_cast<uint8_t>(value & 0x1F); |
1648 switch (instr->op()) { | 1647 switch (instr->op()) { |
1649 case Token::ROR: | 1648 case Token::ROR: |
1650 if (shift_count == 0 && instr->can_deopt()) { | 1649 if (shift_count == 0 && instr->can_deopt()) { |
1651 __ test(ToRegister(left), ToRegister(left)); | 1650 __ test(ToRegister(left), ToRegister(left)); |
1652 DeoptimizeIf(sign, instr->environment()); | 1651 DeoptimizeIf(sign, instr); |
1653 } else { | 1652 } else { |
1654 __ ror(ToRegister(left), shift_count); | 1653 __ ror(ToRegister(left), shift_count); |
1655 } | 1654 } |
1656 break; | 1655 break; |
1657 case Token::SAR: | 1656 case Token::SAR: |
1658 if (shift_count != 0) { | 1657 if (shift_count != 0) { |
1659 __ sar(ToRegister(left), shift_count); | 1658 __ sar(ToRegister(left), shift_count); |
1660 } | 1659 } |
1661 break; | 1660 break; |
1662 case Token::SHR: | 1661 case Token::SHR: |
1663 if (shift_count != 0) { | 1662 if (shift_count != 0) { |
1664 __ shr(ToRegister(left), shift_count); | 1663 __ shr(ToRegister(left), shift_count); |
1665 } else if (instr->can_deopt()) { | 1664 } else if (instr->can_deopt()) { |
1666 __ test(ToRegister(left), ToRegister(left)); | 1665 __ test(ToRegister(left), ToRegister(left)); |
1667 DeoptimizeIf(sign, instr->environment()); | 1666 DeoptimizeIf(sign, instr); |
1668 } | 1667 } |
1669 break; | 1668 break; |
1670 case Token::SHL: | 1669 case Token::SHL: |
1671 if (shift_count != 0) { | 1670 if (shift_count != 0) { |
1672 if (instr->hydrogen_value()->representation().IsSmi() && | 1671 if (instr->hydrogen_value()->representation().IsSmi() && |
1673 instr->can_deopt()) { | 1672 instr->can_deopt()) { |
1674 if (shift_count != 1) { | 1673 if (shift_count != 1) { |
1675 __ shl(ToRegister(left), shift_count - 1); | 1674 __ shl(ToRegister(left), shift_count - 1); |
1676 } | 1675 } |
1677 __ SmiTag(ToRegister(left)); | 1676 __ SmiTag(ToRegister(left)); |
1678 DeoptimizeIf(overflow, instr->environment()); | 1677 DeoptimizeIf(overflow, instr); |
1679 } else { | 1678 } else { |
1680 __ shl(ToRegister(left), shift_count); | 1679 __ shl(ToRegister(left), shift_count); |
1681 } | 1680 } |
1682 } | 1681 } |
1683 break; | 1682 break; |
1684 default: | 1683 default: |
1685 UNREACHABLE(); | 1684 UNREACHABLE(); |
1686 break; | 1685 break; |
1687 } | 1686 } |
1688 } | 1687 } |
1689 } | 1688 } |
1690 | 1689 |
1691 | 1690 |
1692 void LCodeGen::DoSubI(LSubI* instr) { | 1691 void LCodeGen::DoSubI(LSubI* instr) { |
1693 LOperand* left = instr->left(); | 1692 LOperand* left = instr->left(); |
1694 LOperand* right = instr->right(); | 1693 LOperand* right = instr->right(); |
1695 DCHECK(left->Equals(instr->result())); | 1694 DCHECK(left->Equals(instr->result())); |
1696 | 1695 |
1697 if (right->IsConstantOperand()) { | 1696 if (right->IsConstantOperand()) { |
1698 __ sub(ToOperand(left), | 1697 __ sub(ToOperand(left), |
1699 ToImmediate(right, instr->hydrogen()->representation())); | 1698 ToImmediate(right, instr->hydrogen()->representation())); |
1700 } else { | 1699 } else { |
1701 __ sub(ToRegister(left), ToOperand(right)); | 1700 __ sub(ToRegister(left), ToOperand(right)); |
1702 } | 1701 } |
1703 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { | 1702 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |
1704 DeoptimizeIf(overflow, instr->environment()); | 1703 DeoptimizeIf(overflow, instr); |
1705 } | 1704 } |
1706 } | 1705 } |
1707 | 1706 |
1708 | 1707 |
1709 void LCodeGen::DoConstantI(LConstantI* instr) { | 1708 void LCodeGen::DoConstantI(LConstantI* instr) { |
1710 __ Move(ToRegister(instr->result()), Immediate(instr->value())); | 1709 __ Move(ToRegister(instr->result()), Immediate(instr->value())); |
1711 } | 1710 } |
1712 | 1711 |
1713 | 1712 |
1714 void LCodeGen::DoConstantS(LConstantS* instr) { | 1713 void LCodeGen::DoConstantS(LConstantS* instr) { |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1778 void LCodeGen::DoDateField(LDateField* instr) { | 1777 void LCodeGen::DoDateField(LDateField* instr) { |
1779 Register object = ToRegister(instr->date()); | 1778 Register object = ToRegister(instr->date()); |
1780 Register result = ToRegister(instr->result()); | 1779 Register result = ToRegister(instr->result()); |
1781 Register scratch = ToRegister(instr->temp()); | 1780 Register scratch = ToRegister(instr->temp()); |
1782 Smi* index = instr->index(); | 1781 Smi* index = instr->index(); |
1783 Label runtime, done; | 1782 Label runtime, done; |
1784 DCHECK(object.is(result)); | 1783 DCHECK(object.is(result)); |
1785 DCHECK(object.is(eax)); | 1784 DCHECK(object.is(eax)); |
1786 | 1785 |
1787 __ test(object, Immediate(kSmiTagMask)); | 1786 __ test(object, Immediate(kSmiTagMask)); |
1788 DeoptimizeIf(zero, instr->environment()); | 1787 DeoptimizeIf(zero, instr); |
1789 __ CmpObjectType(object, JS_DATE_TYPE, scratch); | 1788 __ CmpObjectType(object, JS_DATE_TYPE, scratch); |
1790 DeoptimizeIf(not_equal, instr->environment()); | 1789 DeoptimizeIf(not_equal, instr); |
1791 | 1790 |
1792 if (index->value() == 0) { | 1791 if (index->value() == 0) { |
1793 __ mov(result, FieldOperand(object, JSDate::kValueOffset)); | 1792 __ mov(result, FieldOperand(object, JSDate::kValueOffset)); |
1794 } else { | 1793 } else { |
1795 if (index->value() < JSDate::kFirstUncachedField) { | 1794 if (index->value() < JSDate::kFirstUncachedField) { |
1796 ExternalReference stamp = ExternalReference::date_cache_stamp(isolate()); | 1795 ExternalReference stamp = ExternalReference::date_cache_stamp(isolate()); |
1797 __ mov(scratch, Operand::StaticVariable(stamp)); | 1796 __ mov(scratch, Operand::StaticVariable(stamp)); |
1798 __ cmp(scratch, FieldOperand(object, JSDate::kCacheStampOffset)); | 1797 __ cmp(scratch, FieldOperand(object, JSDate::kCacheStampOffset)); |
1799 __ j(not_equal, &runtime, Label::kNear); | 1798 __ j(not_equal, &runtime, Label::kNear); |
1800 __ mov(result, FieldOperand(object, JSDate::kValueOffset + | 1799 __ mov(result, FieldOperand(object, JSDate::kValueOffset + |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1910 __ lea(ToRegister(instr->result()), address); | 1909 __ lea(ToRegister(instr->result()), address); |
1911 } | 1910 } |
1912 } else { | 1911 } else { |
1913 if (right->IsConstantOperand()) { | 1912 if (right->IsConstantOperand()) { |
1914 __ add(ToOperand(left), | 1913 __ add(ToOperand(left), |
1915 ToImmediate(right, instr->hydrogen()->representation())); | 1914 ToImmediate(right, instr->hydrogen()->representation())); |
1916 } else { | 1915 } else { |
1917 __ add(ToRegister(left), ToOperand(right)); | 1916 __ add(ToRegister(left), ToOperand(right)); |
1918 } | 1917 } |
1919 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { | 1918 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |
1920 DeoptimizeIf(overflow, instr->environment()); | 1919 DeoptimizeIf(overflow, instr); |
1921 } | 1920 } |
1922 } | 1921 } |
1923 } | 1922 } |
1924 | 1923 |
1925 | 1924 |
1926 void LCodeGen::DoMathMinMax(LMathMinMax* instr) { | 1925 void LCodeGen::DoMathMinMax(LMathMinMax* instr) { |
1927 LOperand* left = instr->left(); | 1926 LOperand* left = instr->left(); |
1928 LOperand* right = instr->right(); | 1927 LOperand* right = instr->right(); |
1929 DCHECK(left->Equals(instr->result())); | 1928 DCHECK(left->Equals(instr->result())); |
1930 HMathMinMax::Operation operation = instr->hydrogen()->operation(); | 1929 HMathMinMax::Operation operation = instr->hydrogen()->operation(); |
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2134 } | 2133 } |
2135 | 2134 |
2136 if (expected.Contains(ToBooleanStub::SMI)) { | 2135 if (expected.Contains(ToBooleanStub::SMI)) { |
2137 // Smis: 0 -> false, all other -> true. | 2136 // Smis: 0 -> false, all other -> true. |
2138 __ test(reg, Operand(reg)); | 2137 __ test(reg, Operand(reg)); |
2139 __ j(equal, instr->FalseLabel(chunk_)); | 2138 __ j(equal, instr->FalseLabel(chunk_)); |
2140 __ JumpIfSmi(reg, instr->TrueLabel(chunk_)); | 2139 __ JumpIfSmi(reg, instr->TrueLabel(chunk_)); |
2141 } else if (expected.NeedsMap()) { | 2140 } else if (expected.NeedsMap()) { |
2142 // If we need a map later and have a Smi -> deopt. | 2141 // If we need a map later and have a Smi -> deopt. |
2143 __ test(reg, Immediate(kSmiTagMask)); | 2142 __ test(reg, Immediate(kSmiTagMask)); |
2144 DeoptimizeIf(zero, instr->environment()); | 2143 DeoptimizeIf(zero, instr); |
2145 } | 2144 } |
2146 | 2145 |
2147 Register map = no_reg; // Keep the compiler happy. | 2146 Register map = no_reg; // Keep the compiler happy. |
2148 if (expected.NeedsMap()) { | 2147 if (expected.NeedsMap()) { |
2149 map = ToRegister(instr->temp()); | 2148 map = ToRegister(instr->temp()); |
2150 DCHECK(!map.is(reg)); | 2149 DCHECK(!map.is(reg)); |
2151 __ mov(map, FieldOperand(reg, HeapObject::kMapOffset)); | 2150 __ mov(map, FieldOperand(reg, HeapObject::kMapOffset)); |
2152 | 2151 |
2153 if (expected.CanBeUndetectable()) { | 2152 if (expected.CanBeUndetectable()) { |
2154 // Undetectable -> false. | 2153 // Undetectable -> false. |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2191 __ xorps(xmm_scratch, xmm_scratch); | 2190 __ xorps(xmm_scratch, xmm_scratch); |
2192 __ ucomisd(xmm_scratch, FieldOperand(reg, HeapNumber::kValueOffset)); | 2191 __ ucomisd(xmm_scratch, FieldOperand(reg, HeapNumber::kValueOffset)); |
2193 __ j(zero, instr->FalseLabel(chunk_)); | 2192 __ j(zero, instr->FalseLabel(chunk_)); |
2194 __ jmp(instr->TrueLabel(chunk_)); | 2193 __ jmp(instr->TrueLabel(chunk_)); |
2195 __ bind(¬_heap_number); | 2194 __ bind(¬_heap_number); |
2196 } | 2195 } |
2197 | 2196 |
2198 if (!expected.IsGeneric()) { | 2197 if (!expected.IsGeneric()) { |
2199 // We've seen something for the first time -> deopt. | 2198 // We've seen something for the first time -> deopt. |
2200 // This can only happen if we are not generic already. | 2199 // This can only happen if we are not generic already. |
2201 DeoptimizeIf(no_condition, instr->environment()); | 2200 DeoptimizeIf(no_condition, instr); |
2202 } | 2201 } |
2203 } | 2202 } |
2204 } | 2203 } |
2205 } | 2204 } |
2206 | 2205 |
2207 | 2206 |
2208 void LCodeGen::EmitGoto(int block) { | 2207 void LCodeGen::EmitGoto(int block) { |
2209 if (!IsNextEmittedBlock(block)) { | 2208 if (!IsNextEmittedBlock(block)) { |
2210 __ jmp(chunk_->GetAssemblyLabel(LookupDestination(block))); | 2209 __ jmp(chunk_->GetAssemblyLabel(LookupDestination(block))); |
2211 } | 2210 } |
(...skipping 609 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2821 info()->AddNoFrameRange(no_frame_start, masm_->pc_offset()); | 2820 info()->AddNoFrameRange(no_frame_start, masm_->pc_offset()); |
2822 } | 2821 } |
2823 } | 2822 } |
2824 | 2823 |
2825 | 2824 |
2826 void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) { | 2825 void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) { |
2827 Register result = ToRegister(instr->result()); | 2826 Register result = ToRegister(instr->result()); |
2828 __ mov(result, Operand::ForCell(instr->hydrogen()->cell().handle())); | 2827 __ mov(result, Operand::ForCell(instr->hydrogen()->cell().handle())); |
2829 if (instr->hydrogen()->RequiresHoleCheck()) { | 2828 if (instr->hydrogen()->RequiresHoleCheck()) { |
2830 __ cmp(result, factory()->the_hole_value()); | 2829 __ cmp(result, factory()->the_hole_value()); |
2831 DeoptimizeIf(equal, instr->environment()); | 2830 DeoptimizeIf(equal, instr); |
2832 } | 2831 } |
2833 } | 2832 } |
2834 | 2833 |
2835 | 2834 |
2836 template <class T> | 2835 template <class T> |
2837 void LCodeGen::EmitVectorLoadICRegisters(T* instr) { | 2836 void LCodeGen::EmitVectorLoadICRegisters(T* instr) { |
2838 DCHECK(FLAG_vector_ics); | 2837 DCHECK(FLAG_vector_ics); |
2839 Register vector = ToRegister(instr->temp_vector()); | 2838 Register vector = ToRegister(instr->temp_vector()); |
2840 DCHECK(vector.is(VectorLoadICDescriptor::VectorRegister())); | 2839 DCHECK(vector.is(VectorLoadICDescriptor::VectorRegister())); |
2841 __ mov(vector, instr->hydrogen()->feedback_vector()); | 2840 __ mov(vector, instr->hydrogen()->feedback_vector()); |
(...skipping 23 matching lines...) Expand all Loading... |
2865 void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) { | 2864 void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) { |
2866 Register value = ToRegister(instr->value()); | 2865 Register value = ToRegister(instr->value()); |
2867 Handle<PropertyCell> cell_handle = instr->hydrogen()->cell().handle(); | 2866 Handle<PropertyCell> cell_handle = instr->hydrogen()->cell().handle(); |
2868 | 2867 |
2869 // If the cell we are storing to contains the hole it could have | 2868 // If the cell we are storing to contains the hole it could have |
2870 // been deleted from the property dictionary. In that case, we need | 2869 // been deleted from the property dictionary. In that case, we need |
2871 // to update the property details in the property dictionary to mark | 2870 // to update the property details in the property dictionary to mark |
2872 // it as no longer deleted. We deoptimize in that case. | 2871 // it as no longer deleted. We deoptimize in that case. |
2873 if (instr->hydrogen()->RequiresHoleCheck()) { | 2872 if (instr->hydrogen()->RequiresHoleCheck()) { |
2874 __ cmp(Operand::ForCell(cell_handle), factory()->the_hole_value()); | 2873 __ cmp(Operand::ForCell(cell_handle), factory()->the_hole_value()); |
2875 DeoptimizeIf(equal, instr->environment()); | 2874 DeoptimizeIf(equal, instr); |
2876 } | 2875 } |
2877 | 2876 |
2878 // Store the value. | 2877 // Store the value. |
2879 __ mov(Operand::ForCell(cell_handle), value); | 2878 __ mov(Operand::ForCell(cell_handle), value); |
2880 // Cells are always rescanned, so no write barrier here. | 2879 // Cells are always rescanned, so no write barrier here. |
2881 } | 2880 } |
2882 | 2881 |
2883 | 2882 |
2884 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { | 2883 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { |
2885 Register context = ToRegister(instr->context()); | 2884 Register context = ToRegister(instr->context()); |
2886 Register result = ToRegister(instr->result()); | 2885 Register result = ToRegister(instr->result()); |
2887 __ mov(result, ContextOperand(context, instr->slot_index())); | 2886 __ mov(result, ContextOperand(context, instr->slot_index())); |
2888 | 2887 |
2889 if (instr->hydrogen()->RequiresHoleCheck()) { | 2888 if (instr->hydrogen()->RequiresHoleCheck()) { |
2890 __ cmp(result, factory()->the_hole_value()); | 2889 __ cmp(result, factory()->the_hole_value()); |
2891 if (instr->hydrogen()->DeoptimizesOnHole()) { | 2890 if (instr->hydrogen()->DeoptimizesOnHole()) { |
2892 DeoptimizeIf(equal, instr->environment()); | 2891 DeoptimizeIf(equal, instr); |
2893 } else { | 2892 } else { |
2894 Label is_not_hole; | 2893 Label is_not_hole; |
2895 __ j(not_equal, &is_not_hole, Label::kNear); | 2894 __ j(not_equal, &is_not_hole, Label::kNear); |
2896 __ mov(result, factory()->undefined_value()); | 2895 __ mov(result, factory()->undefined_value()); |
2897 __ bind(&is_not_hole); | 2896 __ bind(&is_not_hole); |
2898 } | 2897 } |
2899 } | 2898 } |
2900 } | 2899 } |
2901 | 2900 |
2902 | 2901 |
2903 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { | 2902 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { |
2904 Register context = ToRegister(instr->context()); | 2903 Register context = ToRegister(instr->context()); |
2905 Register value = ToRegister(instr->value()); | 2904 Register value = ToRegister(instr->value()); |
2906 | 2905 |
2907 Label skip_assignment; | 2906 Label skip_assignment; |
2908 | 2907 |
2909 Operand target = ContextOperand(context, instr->slot_index()); | 2908 Operand target = ContextOperand(context, instr->slot_index()); |
2910 if (instr->hydrogen()->RequiresHoleCheck()) { | 2909 if (instr->hydrogen()->RequiresHoleCheck()) { |
2911 __ cmp(target, factory()->the_hole_value()); | 2910 __ cmp(target, factory()->the_hole_value()); |
2912 if (instr->hydrogen()->DeoptimizesOnHole()) { | 2911 if (instr->hydrogen()->DeoptimizesOnHole()) { |
2913 DeoptimizeIf(equal, instr->environment()); | 2912 DeoptimizeIf(equal, instr); |
2914 } else { | 2913 } else { |
2915 __ j(not_equal, &skip_assignment, Label::kNear); | 2914 __ j(not_equal, &skip_assignment, Label::kNear); |
2916 } | 2915 } |
2917 } | 2916 } |
2918 | 2917 |
2919 __ mov(target, value); | 2918 __ mov(target, value); |
2920 if (instr->hydrogen()->NeedsWriteBarrier()) { | 2919 if (instr->hydrogen()->NeedsWriteBarrier()) { |
2921 SmiCheck check_needed = | 2920 SmiCheck check_needed = |
2922 instr->hydrogen()->value()->type().IsHeapObject() | 2921 instr->hydrogen()->value()->type().IsHeapObject() |
2923 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; | 2922 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3002 Register function = ToRegister(instr->function()); | 3001 Register function = ToRegister(instr->function()); |
3003 Register temp = ToRegister(instr->temp()); | 3002 Register temp = ToRegister(instr->temp()); |
3004 Register result = ToRegister(instr->result()); | 3003 Register result = ToRegister(instr->result()); |
3005 | 3004 |
3006 // Get the prototype or initial map from the function. | 3005 // Get the prototype or initial map from the function. |
3007 __ mov(result, | 3006 __ mov(result, |
3008 FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); | 3007 FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); |
3009 | 3008 |
3010 // Check that the function has a prototype or an initial map. | 3009 // Check that the function has a prototype or an initial map. |
3011 __ cmp(Operand(result), Immediate(factory()->the_hole_value())); | 3010 __ cmp(Operand(result), Immediate(factory()->the_hole_value())); |
3012 DeoptimizeIf(equal, instr->environment()); | 3011 DeoptimizeIf(equal, instr); |
3013 | 3012 |
3014 // If the function does not have an initial map, we're done. | 3013 // If the function does not have an initial map, we're done. |
3015 Label done; | 3014 Label done; |
3016 __ CmpObjectType(result, MAP_TYPE, temp); | 3015 __ CmpObjectType(result, MAP_TYPE, temp); |
3017 __ j(not_equal, &done, Label::kNear); | 3016 __ j(not_equal, &done, Label::kNear); |
3018 | 3017 |
3019 // Get the prototype from the initial map. | 3018 // Get the prototype from the initial map. |
3020 __ mov(result, FieldOperand(result, Map::kPrototypeOffset)); | 3019 __ mov(result, FieldOperand(result, Map::kPrototypeOffset)); |
3021 | 3020 |
3022 // All done. | 3021 // All done. |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3095 break; | 3094 break; |
3096 case EXTERNAL_INT32_ELEMENTS: | 3095 case EXTERNAL_INT32_ELEMENTS: |
3097 case INT32_ELEMENTS: | 3096 case INT32_ELEMENTS: |
3098 __ mov(result, operand); | 3097 __ mov(result, operand); |
3099 break; | 3098 break; |
3100 case EXTERNAL_UINT32_ELEMENTS: | 3099 case EXTERNAL_UINT32_ELEMENTS: |
3101 case UINT32_ELEMENTS: | 3100 case UINT32_ELEMENTS: |
3102 __ mov(result, operand); | 3101 __ mov(result, operand); |
3103 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) { | 3102 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) { |
3104 __ test(result, Operand(result)); | 3103 __ test(result, Operand(result)); |
3105 DeoptimizeIf(negative, instr->environment()); | 3104 DeoptimizeIf(negative, instr); |
3106 } | 3105 } |
3107 break; | 3106 break; |
3108 case EXTERNAL_FLOAT32_ELEMENTS: | 3107 case EXTERNAL_FLOAT32_ELEMENTS: |
3109 case EXTERNAL_FLOAT64_ELEMENTS: | 3108 case EXTERNAL_FLOAT64_ELEMENTS: |
3110 case FLOAT32_ELEMENTS: | 3109 case FLOAT32_ELEMENTS: |
3111 case FLOAT64_ELEMENTS: | 3110 case FLOAT64_ELEMENTS: |
3112 case FAST_SMI_ELEMENTS: | 3111 case FAST_SMI_ELEMENTS: |
3113 case FAST_ELEMENTS: | 3112 case FAST_ELEMENTS: |
3114 case FAST_DOUBLE_ELEMENTS: | 3113 case FAST_DOUBLE_ELEMENTS: |
3115 case FAST_HOLEY_SMI_ELEMENTS: | 3114 case FAST_HOLEY_SMI_ELEMENTS: |
3116 case FAST_HOLEY_ELEMENTS: | 3115 case FAST_HOLEY_ELEMENTS: |
3117 case FAST_HOLEY_DOUBLE_ELEMENTS: | 3116 case FAST_HOLEY_DOUBLE_ELEMENTS: |
3118 case DICTIONARY_ELEMENTS: | 3117 case DICTIONARY_ELEMENTS: |
3119 case SLOPPY_ARGUMENTS_ELEMENTS: | 3118 case SLOPPY_ARGUMENTS_ELEMENTS: |
3120 UNREACHABLE(); | 3119 UNREACHABLE(); |
3121 break; | 3120 break; |
3122 } | 3121 } |
3123 } | 3122 } |
3124 } | 3123 } |
3125 | 3124 |
3126 | 3125 |
3127 void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) { | 3126 void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) { |
3128 if (instr->hydrogen()->RequiresHoleCheck()) { | 3127 if (instr->hydrogen()->RequiresHoleCheck()) { |
3129 Operand hole_check_operand = BuildFastArrayOperand( | 3128 Operand hole_check_operand = BuildFastArrayOperand( |
3130 instr->elements(), instr->key(), | 3129 instr->elements(), instr->key(), |
3131 instr->hydrogen()->key()->representation(), | 3130 instr->hydrogen()->key()->representation(), |
3132 FAST_DOUBLE_ELEMENTS, | 3131 FAST_DOUBLE_ELEMENTS, |
3133 instr->base_offset() + sizeof(kHoleNanLower32)); | 3132 instr->base_offset() + sizeof(kHoleNanLower32)); |
3134 __ cmp(hole_check_operand, Immediate(kHoleNanUpper32)); | 3133 __ cmp(hole_check_operand, Immediate(kHoleNanUpper32)); |
3135 DeoptimizeIf(equal, instr->environment()); | 3134 DeoptimizeIf(equal, instr); |
3136 } | 3135 } |
3137 | 3136 |
3138 Operand double_load_operand = BuildFastArrayOperand( | 3137 Operand double_load_operand = BuildFastArrayOperand( |
3139 instr->elements(), | 3138 instr->elements(), |
3140 instr->key(), | 3139 instr->key(), |
3141 instr->hydrogen()->key()->representation(), | 3140 instr->hydrogen()->key()->representation(), |
3142 FAST_DOUBLE_ELEMENTS, | 3141 FAST_DOUBLE_ELEMENTS, |
3143 instr->base_offset()); | 3142 instr->base_offset()); |
3144 XMMRegister result = ToDoubleRegister(instr->result()); | 3143 XMMRegister result = ToDoubleRegister(instr->result()); |
3145 __ movsd(result, double_load_operand); | 3144 __ movsd(result, double_load_operand); |
3146 } | 3145 } |
3147 | 3146 |
3148 | 3147 |
3149 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { | 3148 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { |
3150 Register result = ToRegister(instr->result()); | 3149 Register result = ToRegister(instr->result()); |
3151 | 3150 |
3152 // Load the result. | 3151 // Load the result. |
3153 __ mov(result, | 3152 __ mov(result, |
3154 BuildFastArrayOperand(instr->elements(), instr->key(), | 3153 BuildFastArrayOperand(instr->elements(), instr->key(), |
3155 instr->hydrogen()->key()->representation(), | 3154 instr->hydrogen()->key()->representation(), |
3156 FAST_ELEMENTS, instr->base_offset())); | 3155 FAST_ELEMENTS, instr->base_offset())); |
3157 | 3156 |
3158 // Check for the hole value. | 3157 // Check for the hole value. |
3159 if (instr->hydrogen()->RequiresHoleCheck()) { | 3158 if (instr->hydrogen()->RequiresHoleCheck()) { |
3160 if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) { | 3159 if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) { |
3161 __ test(result, Immediate(kSmiTagMask)); | 3160 __ test(result, Immediate(kSmiTagMask)); |
3162 DeoptimizeIf(not_equal, instr->environment()); | 3161 DeoptimizeIf(not_equal, instr); |
3163 } else { | 3162 } else { |
3164 __ cmp(result, factory()->the_hole_value()); | 3163 __ cmp(result, factory()->the_hole_value()); |
3165 DeoptimizeIf(equal, instr->environment()); | 3164 DeoptimizeIf(equal, instr); |
3166 } | 3165 } |
3167 } | 3166 } |
3168 } | 3167 } |
3169 | 3168 |
3170 | 3169 |
3171 void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) { | 3170 void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) { |
3172 if (instr->is_typed_elements()) { | 3171 if (instr->is_typed_elements()) { |
3173 DoLoadKeyedExternalArray(instr); | 3172 DoLoadKeyedExternalArray(instr); |
3174 } else if (instr->hydrogen()->representation().IsDouble()) { | 3173 } else if (instr->hydrogen()->representation().IsDouble()) { |
3175 DoLoadKeyedFixedDoubleArray(instr); | 3174 DoLoadKeyedFixedDoubleArray(instr); |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3302 } | 3301 } |
3303 | 3302 |
3304 // Normal function. Replace undefined or null with global receiver. | 3303 // Normal function. Replace undefined or null with global receiver. |
3305 __ cmp(receiver, factory()->null_value()); | 3304 __ cmp(receiver, factory()->null_value()); |
3306 __ j(equal, &global_object, Label::kNear); | 3305 __ j(equal, &global_object, Label::kNear); |
3307 __ cmp(receiver, factory()->undefined_value()); | 3306 __ cmp(receiver, factory()->undefined_value()); |
3308 __ j(equal, &global_object, Label::kNear); | 3307 __ j(equal, &global_object, Label::kNear); |
3309 | 3308 |
3310 // The receiver should be a JS object. | 3309 // The receiver should be a JS object. |
3311 __ test(receiver, Immediate(kSmiTagMask)); | 3310 __ test(receiver, Immediate(kSmiTagMask)); |
3312 DeoptimizeIf(equal, instr->environment()); | 3311 DeoptimizeIf(equal, instr); |
3313 __ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, scratch); | 3312 __ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, scratch); |
3314 DeoptimizeIf(below, instr->environment()); | 3313 DeoptimizeIf(below, instr); |
3315 | 3314 |
3316 __ jmp(&receiver_ok, Label::kNear); | 3315 __ jmp(&receiver_ok, Label::kNear); |
3317 __ bind(&global_object); | 3316 __ bind(&global_object); |
3318 __ mov(receiver, FieldOperand(function, JSFunction::kContextOffset)); | 3317 __ mov(receiver, FieldOperand(function, JSFunction::kContextOffset)); |
3319 const int global_offset = Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX); | 3318 const int global_offset = Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX); |
3320 __ mov(receiver, Operand(receiver, global_offset)); | 3319 __ mov(receiver, Operand(receiver, global_offset)); |
3321 const int proxy_offset = GlobalObject::kGlobalProxyOffset; | 3320 const int proxy_offset = GlobalObject::kGlobalProxyOffset; |
3322 __ mov(receiver, FieldOperand(receiver, proxy_offset)); | 3321 __ mov(receiver, FieldOperand(receiver, proxy_offset)); |
3323 __ bind(&receiver_ok); | 3322 __ bind(&receiver_ok); |
3324 } | 3323 } |
3325 | 3324 |
3326 | 3325 |
3327 void LCodeGen::DoApplyArguments(LApplyArguments* instr) { | 3326 void LCodeGen::DoApplyArguments(LApplyArguments* instr) { |
3328 Register receiver = ToRegister(instr->receiver()); | 3327 Register receiver = ToRegister(instr->receiver()); |
3329 Register function = ToRegister(instr->function()); | 3328 Register function = ToRegister(instr->function()); |
3330 Register length = ToRegister(instr->length()); | 3329 Register length = ToRegister(instr->length()); |
3331 Register elements = ToRegister(instr->elements()); | 3330 Register elements = ToRegister(instr->elements()); |
3332 DCHECK(receiver.is(eax)); // Used for parameter count. | 3331 DCHECK(receiver.is(eax)); // Used for parameter count. |
3333 DCHECK(function.is(edi)); // Required by InvokeFunction. | 3332 DCHECK(function.is(edi)); // Required by InvokeFunction. |
3334 DCHECK(ToRegister(instr->result()).is(eax)); | 3333 DCHECK(ToRegister(instr->result()).is(eax)); |
3335 | 3334 |
3336 // Copy the arguments to this function possibly from the | 3335 // Copy the arguments to this function possibly from the |
3337 // adaptor frame below it. | 3336 // adaptor frame below it. |
3338 const uint32_t kArgumentsLimit = 1 * KB; | 3337 const uint32_t kArgumentsLimit = 1 * KB; |
3339 __ cmp(length, kArgumentsLimit); | 3338 __ cmp(length, kArgumentsLimit); |
3340 DeoptimizeIf(above, instr->environment()); | 3339 DeoptimizeIf(above, instr); |
3341 | 3340 |
3342 __ push(receiver); | 3341 __ push(receiver); |
3343 __ mov(receiver, length); | 3342 __ mov(receiver, length); |
3344 | 3343 |
3345 // Loop through the arguments pushing them onto the execution | 3344 // Loop through the arguments pushing them onto the execution |
3346 // stack. | 3345 // stack. |
3347 Label invoke, loop; | 3346 Label invoke, loop; |
3348 // length is a small non-negative integer, due to the test above. | 3347 // length is a small non-negative integer, due to the test above. |
3349 __ test(length, Operand(length)); | 3348 __ test(length, Operand(length)); |
3350 __ j(zero, &invoke, Label::kNear); | 3349 __ j(zero, &invoke, Label::kNear); |
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3523 } | 3522 } |
3524 | 3523 |
3525 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); | 3524 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); |
3526 } | 3525 } |
3527 | 3526 |
3528 | 3527 |
3529 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { | 3528 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { |
3530 Register input_reg = ToRegister(instr->value()); | 3529 Register input_reg = ToRegister(instr->value()); |
3531 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), | 3530 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), |
3532 factory()->heap_number_map()); | 3531 factory()->heap_number_map()); |
3533 DeoptimizeIf(not_equal, instr->environment()); | 3532 DeoptimizeIf(not_equal, instr); |
3534 | 3533 |
3535 Label slow, allocated, done; | 3534 Label slow, allocated, done; |
3536 Register tmp = input_reg.is(eax) ? ecx : eax; | 3535 Register tmp = input_reg.is(eax) ? ecx : eax; |
3537 Register tmp2 = tmp.is(ecx) ? edx : input_reg.is(ecx) ? edx : ecx; | 3536 Register tmp2 = tmp.is(ecx) ? edx : input_reg.is(ecx) ? edx : ecx; |
3538 | 3537 |
3539 // Preserve the value of all registers. | 3538 // Preserve the value of all registers. |
3540 PushSafepointRegistersScope scope(this); | 3539 PushSafepointRegistersScope scope(this); |
3541 | 3540 |
3542 __ mov(tmp, FieldOperand(input_reg, HeapNumber::kExponentOffset)); | 3541 __ mov(tmp, FieldOperand(input_reg, HeapNumber::kExponentOffset)); |
3543 // Check the sign of the argument. If the argument is positive, just | 3542 // Check the sign of the argument. If the argument is positive, just |
(...skipping 26 matching lines...) Expand all Loading... |
3570 __ bind(&done); | 3569 __ bind(&done); |
3571 } | 3570 } |
3572 | 3571 |
3573 | 3572 |
3574 void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) { | 3573 void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) { |
3575 Register input_reg = ToRegister(instr->value()); | 3574 Register input_reg = ToRegister(instr->value()); |
3576 __ test(input_reg, Operand(input_reg)); | 3575 __ test(input_reg, Operand(input_reg)); |
3577 Label is_positive; | 3576 Label is_positive; |
3578 __ j(not_sign, &is_positive, Label::kNear); | 3577 __ j(not_sign, &is_positive, Label::kNear); |
3579 __ neg(input_reg); // Sets flags. | 3578 __ neg(input_reg); // Sets flags. |
3580 DeoptimizeIf(negative, instr->environment()); | 3579 DeoptimizeIf(negative, instr); |
3581 __ bind(&is_positive); | 3580 __ bind(&is_positive); |
3582 } | 3581 } |
3583 | 3582 |
3584 | 3583 |
3585 void LCodeGen::DoMathAbs(LMathAbs* instr) { | 3584 void LCodeGen::DoMathAbs(LMathAbs* instr) { |
3586 // Class for deferred case. | 3585 // Class for deferred case. |
3587 class DeferredMathAbsTaggedHeapNumber FINAL : public LDeferredCode { | 3586 class DeferredMathAbsTaggedHeapNumber FINAL : public LDeferredCode { |
3588 public: | 3587 public: |
3589 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, | 3588 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, |
3590 LMathAbs* instr) | 3589 LMathAbs* instr) |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3628 if (CpuFeatures::IsSupported(SSE4_1)) { | 3627 if (CpuFeatures::IsSupported(SSE4_1)) { |
3629 CpuFeatureScope scope(masm(), SSE4_1); | 3628 CpuFeatureScope scope(masm(), SSE4_1); |
3630 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3629 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
3631 // Deoptimize on negative zero. | 3630 // Deoptimize on negative zero. |
3632 Label non_zero; | 3631 Label non_zero; |
3633 __ xorps(xmm_scratch, xmm_scratch); // Zero the register. | 3632 __ xorps(xmm_scratch, xmm_scratch); // Zero the register. |
3634 __ ucomisd(input_reg, xmm_scratch); | 3633 __ ucomisd(input_reg, xmm_scratch); |
3635 __ j(not_equal, &non_zero, Label::kNear); | 3634 __ j(not_equal, &non_zero, Label::kNear); |
3636 __ movmskpd(output_reg, input_reg); | 3635 __ movmskpd(output_reg, input_reg); |
3637 __ test(output_reg, Immediate(1)); | 3636 __ test(output_reg, Immediate(1)); |
3638 DeoptimizeIf(not_zero, instr->environment()); | 3637 DeoptimizeIf(not_zero, instr); |
3639 __ bind(&non_zero); | 3638 __ bind(&non_zero); |
3640 } | 3639 } |
3641 __ roundsd(xmm_scratch, input_reg, Assembler::kRoundDown); | 3640 __ roundsd(xmm_scratch, input_reg, Assembler::kRoundDown); |
3642 __ cvttsd2si(output_reg, Operand(xmm_scratch)); | 3641 __ cvttsd2si(output_reg, Operand(xmm_scratch)); |
3643 // Overflow is signalled with minint. | 3642 // Overflow is signalled with minint. |
3644 __ cmp(output_reg, 0x1); | 3643 __ cmp(output_reg, 0x1); |
3645 DeoptimizeIf(overflow, instr->environment()); | 3644 DeoptimizeIf(overflow, instr); |
3646 } else { | 3645 } else { |
3647 Label negative_sign, done; | 3646 Label negative_sign, done; |
3648 // Deoptimize on unordered. | 3647 // Deoptimize on unordered. |
3649 __ xorps(xmm_scratch, xmm_scratch); // Zero the register. | 3648 __ xorps(xmm_scratch, xmm_scratch); // Zero the register. |
3650 __ ucomisd(input_reg, xmm_scratch); | 3649 __ ucomisd(input_reg, xmm_scratch); |
3651 DeoptimizeIf(parity_even, instr->environment()); | 3650 DeoptimizeIf(parity_even, instr); |
3652 __ j(below, &negative_sign, Label::kNear); | 3651 __ j(below, &negative_sign, Label::kNear); |
3653 | 3652 |
3654 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3653 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
3655 // Check for negative zero. | 3654 // Check for negative zero. |
3656 Label positive_sign; | 3655 Label positive_sign; |
3657 __ j(above, &positive_sign, Label::kNear); | 3656 __ j(above, &positive_sign, Label::kNear); |
3658 __ movmskpd(output_reg, input_reg); | 3657 __ movmskpd(output_reg, input_reg); |
3659 __ test(output_reg, Immediate(1)); | 3658 __ test(output_reg, Immediate(1)); |
3660 DeoptimizeIf(not_zero, instr->environment()); | 3659 DeoptimizeIf(not_zero, instr); |
3661 __ Move(output_reg, Immediate(0)); | 3660 __ Move(output_reg, Immediate(0)); |
3662 __ jmp(&done, Label::kNear); | 3661 __ jmp(&done, Label::kNear); |
3663 __ bind(&positive_sign); | 3662 __ bind(&positive_sign); |
3664 } | 3663 } |
3665 | 3664 |
3666 // Use truncating instruction (OK because input is positive). | 3665 // Use truncating instruction (OK because input is positive). |
3667 __ cvttsd2si(output_reg, Operand(input_reg)); | 3666 __ cvttsd2si(output_reg, Operand(input_reg)); |
3668 // Overflow is signalled with minint. | 3667 // Overflow is signalled with minint. |
3669 __ cmp(output_reg, 0x1); | 3668 __ cmp(output_reg, 0x1); |
3670 DeoptimizeIf(overflow, instr->environment()); | 3669 DeoptimizeIf(overflow, instr); |
3671 __ jmp(&done, Label::kNear); | 3670 __ jmp(&done, Label::kNear); |
3672 | 3671 |
3673 // Non-zero negative reaches here. | 3672 // Non-zero negative reaches here. |
3674 __ bind(&negative_sign); | 3673 __ bind(&negative_sign); |
3675 // Truncate, then compare and compensate. | 3674 // Truncate, then compare and compensate. |
3676 __ cvttsd2si(output_reg, Operand(input_reg)); | 3675 __ cvttsd2si(output_reg, Operand(input_reg)); |
3677 __ Cvtsi2sd(xmm_scratch, output_reg); | 3676 __ Cvtsi2sd(xmm_scratch, output_reg); |
3678 __ ucomisd(input_reg, xmm_scratch); | 3677 __ ucomisd(input_reg, xmm_scratch); |
3679 __ j(equal, &done, Label::kNear); | 3678 __ j(equal, &done, Label::kNear); |
3680 __ sub(output_reg, Immediate(1)); | 3679 __ sub(output_reg, Immediate(1)); |
3681 DeoptimizeIf(overflow, instr->environment()); | 3680 DeoptimizeIf(overflow, instr); |
3682 | 3681 |
3683 __ bind(&done); | 3682 __ bind(&done); |
3684 } | 3683 } |
3685 } | 3684 } |
3686 | 3685 |
3687 | 3686 |
3688 void LCodeGen::DoMathRound(LMathRound* instr) { | 3687 void LCodeGen::DoMathRound(LMathRound* instr) { |
3689 Register output_reg = ToRegister(instr->result()); | 3688 Register output_reg = ToRegister(instr->result()); |
3690 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 3689 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
3691 XMMRegister xmm_scratch = double_scratch0(); | 3690 XMMRegister xmm_scratch = double_scratch0(); |
3692 XMMRegister input_temp = ToDoubleRegister(instr->temp()); | 3691 XMMRegister input_temp = ToDoubleRegister(instr->temp()); |
3693 ExternalReference one_half = ExternalReference::address_of_one_half(); | 3692 ExternalReference one_half = ExternalReference::address_of_one_half(); |
3694 ExternalReference minus_one_half = | 3693 ExternalReference minus_one_half = |
3695 ExternalReference::address_of_minus_one_half(); | 3694 ExternalReference::address_of_minus_one_half(); |
3696 | 3695 |
3697 Label done, round_to_zero, below_one_half, do_not_compensate; | 3696 Label done, round_to_zero, below_one_half, do_not_compensate; |
3698 Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear; | 3697 Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear; |
3699 | 3698 |
3700 __ movsd(xmm_scratch, Operand::StaticVariable(one_half)); | 3699 __ movsd(xmm_scratch, Operand::StaticVariable(one_half)); |
3701 __ ucomisd(xmm_scratch, input_reg); | 3700 __ ucomisd(xmm_scratch, input_reg); |
3702 __ j(above, &below_one_half, Label::kNear); | 3701 __ j(above, &below_one_half, Label::kNear); |
3703 | 3702 |
3704 // CVTTSD2SI rounds towards zero, since 0.5 <= x, we use floor(0.5 + x). | 3703 // CVTTSD2SI rounds towards zero, since 0.5 <= x, we use floor(0.5 + x). |
3705 __ addsd(xmm_scratch, input_reg); | 3704 __ addsd(xmm_scratch, input_reg); |
3706 __ cvttsd2si(output_reg, Operand(xmm_scratch)); | 3705 __ cvttsd2si(output_reg, Operand(xmm_scratch)); |
3707 // Overflow is signalled with minint. | 3706 // Overflow is signalled with minint. |
3708 __ cmp(output_reg, 0x1); | 3707 __ cmp(output_reg, 0x1); |
3709 __ RecordComment("D2I conversion overflow"); | 3708 __ RecordComment("D2I conversion overflow"); |
3710 DeoptimizeIf(overflow, instr->environment()); | 3709 DeoptimizeIf(overflow, instr); |
3711 __ jmp(&done, dist); | 3710 __ jmp(&done, dist); |
3712 | 3711 |
3713 __ bind(&below_one_half); | 3712 __ bind(&below_one_half); |
3714 __ movsd(xmm_scratch, Operand::StaticVariable(minus_one_half)); | 3713 __ movsd(xmm_scratch, Operand::StaticVariable(minus_one_half)); |
3715 __ ucomisd(xmm_scratch, input_reg); | 3714 __ ucomisd(xmm_scratch, input_reg); |
3716 __ j(below_equal, &round_to_zero, Label::kNear); | 3715 __ j(below_equal, &round_to_zero, Label::kNear); |
3717 | 3716 |
3718 // CVTTSD2SI rounds towards zero, we use ceil(x - (-0.5)) and then | 3717 // CVTTSD2SI rounds towards zero, we use ceil(x - (-0.5)) and then |
3719 // compare and compensate. | 3718 // compare and compensate. |
3720 __ movaps(input_temp, input_reg); // Do not alter input_reg. | 3719 __ movaps(input_temp, input_reg); // Do not alter input_reg. |
3721 __ subsd(input_temp, xmm_scratch); | 3720 __ subsd(input_temp, xmm_scratch); |
3722 __ cvttsd2si(output_reg, Operand(input_temp)); | 3721 __ cvttsd2si(output_reg, Operand(input_temp)); |
3723 // Catch minint due to overflow, and to prevent overflow when compensating. | 3722 // Catch minint due to overflow, and to prevent overflow when compensating. |
3724 __ cmp(output_reg, 0x1); | 3723 __ cmp(output_reg, 0x1); |
3725 __ RecordComment("D2I conversion overflow"); | 3724 __ RecordComment("D2I conversion overflow"); |
3726 DeoptimizeIf(overflow, instr->environment()); | 3725 DeoptimizeIf(overflow, instr); |
3727 | 3726 |
3728 __ Cvtsi2sd(xmm_scratch, output_reg); | 3727 __ Cvtsi2sd(xmm_scratch, output_reg); |
3729 __ ucomisd(xmm_scratch, input_temp); | 3728 __ ucomisd(xmm_scratch, input_temp); |
3730 __ j(equal, &done, dist); | 3729 __ j(equal, &done, dist); |
3731 __ sub(output_reg, Immediate(1)); | 3730 __ sub(output_reg, Immediate(1)); |
3732 // No overflow because we already ruled out minint. | 3731 // No overflow because we already ruled out minint. |
3733 __ jmp(&done, dist); | 3732 __ jmp(&done, dist); |
3734 | 3733 |
3735 __ bind(&round_to_zero); | 3734 __ bind(&round_to_zero); |
3736 // We return 0 for the input range [+0, 0.5[, or [-0.5, 0.5[ if | 3735 // We return 0 for the input range [+0, 0.5[, or [-0.5, 0.5[ if |
3737 // we can ignore the difference between a result of -0 and +0. | 3736 // we can ignore the difference between a result of -0 and +0. |
3738 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3737 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
3739 // If the sign is positive, we return +0. | 3738 // If the sign is positive, we return +0. |
3740 __ movmskpd(output_reg, input_reg); | 3739 __ movmskpd(output_reg, input_reg); |
3741 __ test(output_reg, Immediate(1)); | 3740 __ test(output_reg, Immediate(1)); |
3742 __ RecordComment("Minus zero"); | 3741 __ RecordComment("Minus zero"); |
3743 DeoptimizeIf(not_zero, instr->environment()); | 3742 DeoptimizeIf(not_zero, instr); |
3744 } | 3743 } |
3745 __ Move(output_reg, Immediate(0)); | 3744 __ Move(output_reg, Immediate(0)); |
3746 __ bind(&done); | 3745 __ bind(&done); |
3747 } | 3746 } |
3748 | 3747 |
3749 | 3748 |
3750 void LCodeGen::DoMathFround(LMathFround* instr) { | 3749 void LCodeGen::DoMathFround(LMathFround* instr) { |
3751 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 3750 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
3752 XMMRegister output_reg = ToDoubleRegister(instr->result()); | 3751 XMMRegister output_reg = ToDoubleRegister(instr->result()); |
3753 __ cvtsd2ss(output_reg, input_reg); | 3752 __ cvtsd2ss(output_reg, input_reg); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3809 DCHECK(ToDoubleRegister(instr->result()).is(xmm3)); | 3808 DCHECK(ToDoubleRegister(instr->result()).is(xmm3)); |
3810 | 3809 |
3811 if (exponent_type.IsSmi()) { | 3810 if (exponent_type.IsSmi()) { |
3812 MathPowStub stub(isolate(), MathPowStub::TAGGED); | 3811 MathPowStub stub(isolate(), MathPowStub::TAGGED); |
3813 __ CallStub(&stub); | 3812 __ CallStub(&stub); |
3814 } else if (exponent_type.IsTagged()) { | 3813 } else if (exponent_type.IsTagged()) { |
3815 Label no_deopt; | 3814 Label no_deopt; |
3816 __ JumpIfSmi(tagged_exponent, &no_deopt); | 3815 __ JumpIfSmi(tagged_exponent, &no_deopt); |
3817 DCHECK(!ecx.is(tagged_exponent)); | 3816 DCHECK(!ecx.is(tagged_exponent)); |
3818 __ CmpObjectType(tagged_exponent, HEAP_NUMBER_TYPE, ecx); | 3817 __ CmpObjectType(tagged_exponent, HEAP_NUMBER_TYPE, ecx); |
3819 DeoptimizeIf(not_equal, instr->environment()); | 3818 DeoptimizeIf(not_equal, instr); |
3820 __ bind(&no_deopt); | 3819 __ bind(&no_deopt); |
3821 MathPowStub stub(isolate(), MathPowStub::TAGGED); | 3820 MathPowStub stub(isolate(), MathPowStub::TAGGED); |
3822 __ CallStub(&stub); | 3821 __ CallStub(&stub); |
3823 } else if (exponent_type.IsInteger32()) { | 3822 } else if (exponent_type.IsInteger32()) { |
3824 MathPowStub stub(isolate(), MathPowStub::INTEGER); | 3823 MathPowStub stub(isolate(), MathPowStub::INTEGER); |
3825 __ CallStub(&stub); | 3824 __ CallStub(&stub); |
3826 } else { | 3825 } else { |
3827 DCHECK(exponent_type.IsDouble()); | 3826 DCHECK(exponent_type.IsDouble()); |
3828 MathPowStub stub(isolate(), MathPowStub::DOUBLE); | 3827 MathPowStub stub(isolate(), MathPowStub::DOUBLE); |
3829 __ CallStub(&stub); | 3828 __ CallStub(&stub); |
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4121 instr->hydrogen()->index()->representation())); | 4120 instr->hydrogen()->index()->representation())); |
4122 } else { | 4121 } else { |
4123 __ cmp(ToRegister(instr->index()), ToOperand(instr->length())); | 4122 __ cmp(ToRegister(instr->index()), ToOperand(instr->length())); |
4124 } | 4123 } |
4125 if (FLAG_debug_code && instr->hydrogen()->skip_check()) { | 4124 if (FLAG_debug_code && instr->hydrogen()->skip_check()) { |
4126 Label done; | 4125 Label done; |
4127 __ j(NegateCondition(cc), &done, Label::kNear); | 4126 __ j(NegateCondition(cc), &done, Label::kNear); |
4128 __ int3(); | 4127 __ int3(); |
4129 __ bind(&done); | 4128 __ bind(&done); |
4130 } else { | 4129 } else { |
4131 DeoptimizeIf(cc, instr->environment()); | 4130 DeoptimizeIf(cc, instr); |
4132 } | 4131 } |
4133 } | 4132 } |
4134 | 4133 |
4135 | 4134 |
4136 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) { | 4135 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) { |
4137 ElementsKind elements_kind = instr->elements_kind(); | 4136 ElementsKind elements_kind = instr->elements_kind(); |
4138 LOperand* key = instr->key(); | 4137 LOperand* key = instr->key(); |
4139 if (!key->IsConstantOperand() && | 4138 if (!key->IsConstantOperand() && |
4140 ExternalArrayOpRequiresTemp(instr->hydrogen()->key()->representation(), | 4139 ExternalArrayOpRequiresTemp(instr->hydrogen()->key()->representation(), |
4141 elements_kind)) { | 4140 elements_kind)) { |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4289 CodeFactory::KeyedStoreIC(isolate(), instr->strict_mode()).code(); | 4288 CodeFactory::KeyedStoreIC(isolate(), instr->strict_mode()).code(); |
4290 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 4289 CallCode(ic, RelocInfo::CODE_TARGET, instr); |
4291 } | 4290 } |
4292 | 4291 |
4293 | 4292 |
4294 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) { | 4293 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) { |
4295 Register object = ToRegister(instr->object()); | 4294 Register object = ToRegister(instr->object()); |
4296 Register temp = ToRegister(instr->temp()); | 4295 Register temp = ToRegister(instr->temp()); |
4297 Label no_memento_found; | 4296 Label no_memento_found; |
4298 __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found); | 4297 __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found); |
4299 DeoptimizeIf(equal, instr->environment()); | 4298 DeoptimizeIf(equal, instr); |
4300 __ bind(&no_memento_found); | 4299 __ bind(&no_memento_found); |
4301 } | 4300 } |
4302 | 4301 |
4303 | 4302 |
4304 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { | 4303 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { |
4305 Register object_reg = ToRegister(instr->object()); | 4304 Register object_reg = ToRegister(instr->object()); |
4306 | 4305 |
4307 Handle<Map> from_map = instr->original_map(); | 4306 Handle<Map> from_map = instr->original_map(); |
4308 Handle<Map> to_map = instr->transitioned_map(); | 4307 Handle<Map> to_map = instr->transitioned_map(); |
4309 ElementsKind from_kind = instr->from_kind(); | 4308 ElementsKind from_kind = instr->from_kind(); |
(...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4634 __ StoreToSafepointRegisterSlot(reg, eax); | 4633 __ StoreToSafepointRegisterSlot(reg, eax); |
4635 } | 4634 } |
4636 | 4635 |
4637 | 4636 |
4638 void LCodeGen::DoSmiTag(LSmiTag* instr) { | 4637 void LCodeGen::DoSmiTag(LSmiTag* instr) { |
4639 HChange* hchange = instr->hydrogen(); | 4638 HChange* hchange = instr->hydrogen(); |
4640 Register input = ToRegister(instr->value()); | 4639 Register input = ToRegister(instr->value()); |
4641 if (hchange->CheckFlag(HValue::kCanOverflow) && | 4640 if (hchange->CheckFlag(HValue::kCanOverflow) && |
4642 hchange->value()->CheckFlag(HValue::kUint32)) { | 4641 hchange->value()->CheckFlag(HValue::kUint32)) { |
4643 __ test(input, Immediate(0xc0000000)); | 4642 __ test(input, Immediate(0xc0000000)); |
4644 DeoptimizeIf(not_zero, instr->environment()); | 4643 DeoptimizeIf(not_zero, instr); |
4645 } | 4644 } |
4646 __ SmiTag(input); | 4645 __ SmiTag(input); |
4647 if (hchange->CheckFlag(HValue::kCanOverflow) && | 4646 if (hchange->CheckFlag(HValue::kCanOverflow) && |
4648 !hchange->value()->CheckFlag(HValue::kUint32)) { | 4647 !hchange->value()->CheckFlag(HValue::kUint32)) { |
4649 DeoptimizeIf(overflow, instr->environment()); | 4648 DeoptimizeIf(overflow, instr); |
4650 } | 4649 } |
4651 } | 4650 } |
4652 | 4651 |
4653 | 4652 |
4654 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { | 4653 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { |
4655 LOperand* input = instr->value(); | 4654 LOperand* input = instr->value(); |
4656 Register result = ToRegister(input); | 4655 Register result = ToRegister(input); |
4657 DCHECK(input->IsRegister() && input->Equals(instr->result())); | 4656 DCHECK(input->IsRegister() && input->Equals(instr->result())); |
4658 if (instr->needs_check()) { | 4657 if (instr->needs_check()) { |
4659 __ test(result, Immediate(kSmiTagMask)); | 4658 __ test(result, Immediate(kSmiTagMask)); |
4660 DeoptimizeIf(not_zero, instr->environment()); | 4659 DeoptimizeIf(not_zero, instr); |
4661 } else { | 4660 } else { |
4662 __ AssertSmi(result); | 4661 __ AssertSmi(result); |
4663 } | 4662 } |
4664 __ SmiUntag(result); | 4663 __ SmiUntag(result); |
4665 } | 4664 } |
4666 | 4665 |
4667 | 4666 |
4668 void LCodeGen::EmitNumberUntagD(Register input_reg, | 4667 void LCodeGen::EmitNumberUntagD(LNumberUntagD* instr, Register input_reg, |
4669 Register temp_reg, | 4668 Register temp_reg, XMMRegister result_reg, |
4670 XMMRegister result_reg, | |
4671 bool can_convert_undefined_to_nan, | |
4672 bool deoptimize_on_minus_zero, | |
4673 LEnvironment* env, | |
4674 NumberUntagDMode mode) { | 4669 NumberUntagDMode mode) { |
| 4670 bool can_convert_undefined_to_nan = |
| 4671 instr->hydrogen()->can_convert_undefined_to_nan(); |
| 4672 bool deoptimize_on_minus_zero = instr->hydrogen()->deoptimize_on_minus_zero(); |
| 4673 |
4675 Label convert, load_smi, done; | 4674 Label convert, load_smi, done; |
4676 | 4675 |
4677 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) { | 4676 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) { |
4678 // Smi check. | 4677 // Smi check. |
4679 __ JumpIfSmi(input_reg, &load_smi, Label::kNear); | 4678 __ JumpIfSmi(input_reg, &load_smi, Label::kNear); |
4680 | 4679 |
4681 // Heap number map check. | 4680 // Heap number map check. |
4682 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), | 4681 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), |
4683 factory()->heap_number_map()); | 4682 factory()->heap_number_map()); |
4684 if (can_convert_undefined_to_nan) { | 4683 if (can_convert_undefined_to_nan) { |
4685 __ j(not_equal, &convert, Label::kNear); | 4684 __ j(not_equal, &convert, Label::kNear); |
4686 } else { | 4685 } else { |
4687 DeoptimizeIf(not_equal, env); | 4686 DeoptimizeIf(not_equal, instr); |
4688 } | 4687 } |
4689 | 4688 |
4690 // Heap number to XMM conversion. | 4689 // Heap number to XMM conversion. |
4691 __ movsd(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset)); | 4690 __ movsd(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
4692 | 4691 |
4693 if (deoptimize_on_minus_zero) { | 4692 if (deoptimize_on_minus_zero) { |
4694 XMMRegister xmm_scratch = double_scratch0(); | 4693 XMMRegister xmm_scratch = double_scratch0(); |
4695 __ xorps(xmm_scratch, xmm_scratch); | 4694 __ xorps(xmm_scratch, xmm_scratch); |
4696 __ ucomisd(result_reg, xmm_scratch); | 4695 __ ucomisd(result_reg, xmm_scratch); |
4697 __ j(not_zero, &done, Label::kNear); | 4696 __ j(not_zero, &done, Label::kNear); |
4698 __ movmskpd(temp_reg, result_reg); | 4697 __ movmskpd(temp_reg, result_reg); |
4699 __ test_b(temp_reg, 1); | 4698 __ test_b(temp_reg, 1); |
4700 DeoptimizeIf(not_zero, env); | 4699 DeoptimizeIf(not_zero, instr); |
4701 } | 4700 } |
4702 __ jmp(&done, Label::kNear); | 4701 __ jmp(&done, Label::kNear); |
4703 | 4702 |
4704 if (can_convert_undefined_to_nan) { | 4703 if (can_convert_undefined_to_nan) { |
4705 __ bind(&convert); | 4704 __ bind(&convert); |
4706 | 4705 |
4707 // Convert undefined (and hole) to NaN. | 4706 // Convert undefined (and hole) to NaN. |
4708 __ cmp(input_reg, factory()->undefined_value()); | 4707 __ cmp(input_reg, factory()->undefined_value()); |
4709 DeoptimizeIf(not_equal, env); | 4708 DeoptimizeIf(not_equal, instr); |
4710 | 4709 |
4711 ExternalReference nan = | 4710 ExternalReference nan = |
4712 ExternalReference::address_of_canonical_non_hole_nan(); | 4711 ExternalReference::address_of_canonical_non_hole_nan(); |
4713 __ movsd(result_reg, Operand::StaticVariable(nan)); | 4712 __ movsd(result_reg, Operand::StaticVariable(nan)); |
4714 __ jmp(&done, Label::kNear); | 4713 __ jmp(&done, Label::kNear); |
4715 } | 4714 } |
4716 } else { | 4715 } else { |
4717 DCHECK(mode == NUMBER_CANDIDATE_IS_SMI); | 4716 DCHECK(mode == NUMBER_CANDIDATE_IS_SMI); |
4718 } | 4717 } |
4719 | 4718 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4754 | 4753 |
4755 __ bind(&check_bools); | 4754 __ bind(&check_bools); |
4756 __ cmp(input_reg, factory()->true_value()); | 4755 __ cmp(input_reg, factory()->true_value()); |
4757 __ j(not_equal, &check_false, Label::kNear); | 4756 __ j(not_equal, &check_false, Label::kNear); |
4758 __ Move(input_reg, Immediate(1)); | 4757 __ Move(input_reg, Immediate(1)); |
4759 __ jmp(done); | 4758 __ jmp(done); |
4760 | 4759 |
4761 __ bind(&check_false); | 4760 __ bind(&check_false); |
4762 __ cmp(input_reg, factory()->false_value()); | 4761 __ cmp(input_reg, factory()->false_value()); |
4763 __ RecordComment("Deferred TaggedToI: cannot truncate"); | 4762 __ RecordComment("Deferred TaggedToI: cannot truncate"); |
4764 DeoptimizeIf(not_equal, instr->environment()); | 4763 DeoptimizeIf(not_equal, instr); |
4765 __ Move(input_reg, Immediate(0)); | 4764 __ Move(input_reg, Immediate(0)); |
4766 } else { | 4765 } else { |
4767 XMMRegister scratch = ToDoubleRegister(instr->temp()); | 4766 XMMRegister scratch = ToDoubleRegister(instr->temp()); |
4768 DCHECK(!scratch.is(xmm0)); | 4767 DCHECK(!scratch.is(xmm0)); |
4769 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), | 4768 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), |
4770 isolate()->factory()->heap_number_map()); | 4769 isolate()->factory()->heap_number_map()); |
4771 __ RecordComment("Deferred TaggedToI: not a heap number"); | 4770 __ RecordComment("Deferred TaggedToI: not a heap number"); |
4772 DeoptimizeIf(not_equal, instr->environment()); | 4771 DeoptimizeIf(not_equal, instr); |
4773 __ movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); | 4772 __ movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
4774 __ cvttsd2si(input_reg, Operand(xmm0)); | 4773 __ cvttsd2si(input_reg, Operand(xmm0)); |
4775 __ Cvtsi2sd(scratch, Operand(input_reg)); | 4774 __ Cvtsi2sd(scratch, Operand(input_reg)); |
4776 __ ucomisd(xmm0, scratch); | 4775 __ ucomisd(xmm0, scratch); |
4777 __ RecordComment("Deferred TaggedToI: lost precision"); | 4776 __ RecordComment("Deferred TaggedToI: lost precision"); |
4778 DeoptimizeIf(not_equal, instr->environment()); | 4777 DeoptimizeIf(not_equal, instr); |
4779 __ RecordComment("Deferred TaggedToI: NaN"); | 4778 __ RecordComment("Deferred TaggedToI: NaN"); |
4780 DeoptimizeIf(parity_even, instr->environment()); | 4779 DeoptimizeIf(parity_even, instr); |
4781 if (instr->hydrogen()->GetMinusZeroMode() == FAIL_ON_MINUS_ZERO) { | 4780 if (instr->hydrogen()->GetMinusZeroMode() == FAIL_ON_MINUS_ZERO) { |
4782 __ test(input_reg, Operand(input_reg)); | 4781 __ test(input_reg, Operand(input_reg)); |
4783 __ j(not_zero, done); | 4782 __ j(not_zero, done); |
4784 __ movmskpd(input_reg, xmm0); | 4783 __ movmskpd(input_reg, xmm0); |
4785 __ and_(input_reg, 1); | 4784 __ and_(input_reg, 1); |
4786 __ RecordComment("Deferred TaggedToI: minus zero"); | 4785 __ RecordComment("Deferred TaggedToI: minus zero"); |
4787 DeoptimizeIf(not_zero, instr->environment()); | 4786 DeoptimizeIf(not_zero, instr); |
4788 } | 4787 } |
4789 } | 4788 } |
4790 } | 4789 } |
4791 | 4790 |
4792 | 4791 |
4793 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { | 4792 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { |
4794 class DeferredTaggedToI FINAL : public LDeferredCode { | 4793 class DeferredTaggedToI FINAL : public LDeferredCode { |
4795 public: | 4794 public: |
4796 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) | 4795 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) |
4797 : LDeferredCode(codegen), instr_(instr) { } | 4796 : LDeferredCode(codegen), instr_(instr) { } |
(...skipping 29 matching lines...) Expand all Loading... |
4827 | 4826 |
4828 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { | 4827 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { |
4829 LOperand* input = instr->value(); | 4828 LOperand* input = instr->value(); |
4830 DCHECK(input->IsRegister()); | 4829 DCHECK(input->IsRegister()); |
4831 LOperand* temp = instr->temp(); | 4830 LOperand* temp = instr->temp(); |
4832 DCHECK(temp->IsRegister()); | 4831 DCHECK(temp->IsRegister()); |
4833 LOperand* result = instr->result(); | 4832 LOperand* result = instr->result(); |
4834 DCHECK(result->IsDoubleRegister()); | 4833 DCHECK(result->IsDoubleRegister()); |
4835 | 4834 |
4836 Register input_reg = ToRegister(input); | 4835 Register input_reg = ToRegister(input); |
4837 bool deoptimize_on_minus_zero = | |
4838 instr->hydrogen()->deoptimize_on_minus_zero(); | |
4839 Register temp_reg = ToRegister(temp); | 4836 Register temp_reg = ToRegister(temp); |
4840 | 4837 |
4841 HValue* value = instr->hydrogen()->value(); | 4838 HValue* value = instr->hydrogen()->value(); |
4842 NumberUntagDMode mode = value->representation().IsSmi() | 4839 NumberUntagDMode mode = value->representation().IsSmi() |
4843 ? NUMBER_CANDIDATE_IS_SMI : NUMBER_CANDIDATE_IS_ANY_TAGGED; | 4840 ? NUMBER_CANDIDATE_IS_SMI : NUMBER_CANDIDATE_IS_ANY_TAGGED; |
4844 | 4841 |
4845 XMMRegister result_reg = ToDoubleRegister(result); | 4842 XMMRegister result_reg = ToDoubleRegister(result); |
4846 EmitNumberUntagD(input_reg, | 4843 EmitNumberUntagD(instr, input_reg, temp_reg, result_reg, mode); |
4847 temp_reg, | |
4848 result_reg, | |
4849 instr->hydrogen()->can_convert_undefined_to_nan(), | |
4850 deoptimize_on_minus_zero, | |
4851 instr->environment(), | |
4852 mode); | |
4853 } | 4844 } |
4854 | 4845 |
4855 | 4846 |
4856 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { | 4847 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { |
4857 LOperand* input = instr->value(); | 4848 LOperand* input = instr->value(); |
4858 DCHECK(input->IsDoubleRegister()); | 4849 DCHECK(input->IsDoubleRegister()); |
4859 LOperand* result = instr->result(); | 4850 LOperand* result = instr->result(); |
4860 DCHECK(result->IsRegister()); | 4851 DCHECK(result->IsRegister()); |
4861 Register result_reg = ToRegister(result); | 4852 Register result_reg = ToRegister(result); |
4862 | 4853 |
4863 if (instr->truncating()) { | 4854 if (instr->truncating()) { |
4864 XMMRegister input_reg = ToDoubleRegister(input); | 4855 XMMRegister input_reg = ToDoubleRegister(input); |
4865 __ TruncateDoubleToI(result_reg, input_reg); | 4856 __ TruncateDoubleToI(result_reg, input_reg); |
4866 } else { | 4857 } else { |
4867 Label bailout, done; | 4858 Label bailout, done; |
4868 XMMRegister input_reg = ToDoubleRegister(input); | 4859 XMMRegister input_reg = ToDoubleRegister(input); |
4869 XMMRegister xmm_scratch = double_scratch0(); | 4860 XMMRegister xmm_scratch = double_scratch0(); |
4870 __ DoubleToI(result_reg, input_reg, xmm_scratch, | 4861 __ DoubleToI(result_reg, input_reg, xmm_scratch, |
4871 instr->hydrogen()->GetMinusZeroMode(), &bailout, Label::kNear); | 4862 instr->hydrogen()->GetMinusZeroMode(), &bailout, Label::kNear); |
4872 __ jmp(&done, Label::kNear); | 4863 __ jmp(&done, Label::kNear); |
4873 __ bind(&bailout); | 4864 __ bind(&bailout); |
4874 DeoptimizeIf(no_condition, instr->environment()); | 4865 DeoptimizeIf(no_condition, instr); |
4875 __ bind(&done); | 4866 __ bind(&done); |
4876 } | 4867 } |
4877 } | 4868 } |
4878 | 4869 |
4879 | 4870 |
4880 void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) { | 4871 void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) { |
4881 LOperand* input = instr->value(); | 4872 LOperand* input = instr->value(); |
4882 DCHECK(input->IsDoubleRegister()); | 4873 DCHECK(input->IsDoubleRegister()); |
4883 LOperand* result = instr->result(); | 4874 LOperand* result = instr->result(); |
4884 DCHECK(result->IsRegister()); | 4875 DCHECK(result->IsRegister()); |
4885 Register result_reg = ToRegister(result); | 4876 Register result_reg = ToRegister(result); |
4886 | 4877 |
4887 Label bailout, done; | 4878 Label bailout, done; |
4888 XMMRegister input_reg = ToDoubleRegister(input); | 4879 XMMRegister input_reg = ToDoubleRegister(input); |
4889 XMMRegister xmm_scratch = double_scratch0(); | 4880 XMMRegister xmm_scratch = double_scratch0(); |
4890 __ DoubleToI(result_reg, input_reg, xmm_scratch, | 4881 __ DoubleToI(result_reg, input_reg, xmm_scratch, |
4891 instr->hydrogen()->GetMinusZeroMode(), &bailout, Label::kNear); | 4882 instr->hydrogen()->GetMinusZeroMode(), &bailout, Label::kNear); |
4892 __ jmp(&done, Label::kNear); | 4883 __ jmp(&done, Label::kNear); |
4893 __ bind(&bailout); | 4884 __ bind(&bailout); |
4894 DeoptimizeIf(no_condition, instr->environment()); | 4885 DeoptimizeIf(no_condition, instr); |
4895 __ bind(&done); | 4886 __ bind(&done); |
4896 | 4887 |
4897 __ SmiTag(result_reg); | 4888 __ SmiTag(result_reg); |
4898 DeoptimizeIf(overflow, instr->environment()); | 4889 DeoptimizeIf(overflow, instr); |
4899 } | 4890 } |
4900 | 4891 |
4901 | 4892 |
4902 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { | 4893 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { |
4903 LOperand* input = instr->value(); | 4894 LOperand* input = instr->value(); |
4904 __ test(ToOperand(input), Immediate(kSmiTagMask)); | 4895 __ test(ToOperand(input), Immediate(kSmiTagMask)); |
4905 DeoptimizeIf(not_zero, instr->environment()); | 4896 DeoptimizeIf(not_zero, instr); |
4906 } | 4897 } |
4907 | 4898 |
4908 | 4899 |
4909 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { | 4900 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { |
4910 if (!instr->hydrogen()->value()->type().IsHeapObject()) { | 4901 if (!instr->hydrogen()->value()->type().IsHeapObject()) { |
4911 LOperand* input = instr->value(); | 4902 LOperand* input = instr->value(); |
4912 __ test(ToOperand(input), Immediate(kSmiTagMask)); | 4903 __ test(ToOperand(input), Immediate(kSmiTagMask)); |
4913 DeoptimizeIf(zero, instr->environment()); | 4904 DeoptimizeIf(zero, instr); |
4914 } | 4905 } |
4915 } | 4906 } |
4916 | 4907 |
4917 | 4908 |
4918 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { | 4909 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { |
4919 Register input = ToRegister(instr->value()); | 4910 Register input = ToRegister(instr->value()); |
4920 Register temp = ToRegister(instr->temp()); | 4911 Register temp = ToRegister(instr->temp()); |
4921 | 4912 |
4922 __ mov(temp, FieldOperand(input, HeapObject::kMapOffset)); | 4913 __ mov(temp, FieldOperand(input, HeapObject::kMapOffset)); |
4923 | 4914 |
4924 if (instr->hydrogen()->is_interval_check()) { | 4915 if (instr->hydrogen()->is_interval_check()) { |
4925 InstanceType first; | 4916 InstanceType first; |
4926 InstanceType last; | 4917 InstanceType last; |
4927 instr->hydrogen()->GetCheckInterval(&first, &last); | 4918 instr->hydrogen()->GetCheckInterval(&first, &last); |
4928 | 4919 |
4929 __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset), | 4920 __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset), |
4930 static_cast<int8_t>(first)); | 4921 static_cast<int8_t>(first)); |
4931 | 4922 |
4932 // If there is only one type in the interval check for equality. | 4923 // If there is only one type in the interval check for equality. |
4933 if (first == last) { | 4924 if (first == last) { |
4934 DeoptimizeIf(not_equal, instr->environment()); | 4925 DeoptimizeIf(not_equal, instr); |
4935 } else { | 4926 } else { |
4936 DeoptimizeIf(below, instr->environment()); | 4927 DeoptimizeIf(below, instr); |
4937 // Omit check for the last type. | 4928 // Omit check for the last type. |
4938 if (last != LAST_TYPE) { | 4929 if (last != LAST_TYPE) { |
4939 __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset), | 4930 __ cmpb(FieldOperand(temp, Map::kInstanceTypeOffset), |
4940 static_cast<int8_t>(last)); | 4931 static_cast<int8_t>(last)); |
4941 DeoptimizeIf(above, instr->environment()); | 4932 DeoptimizeIf(above, instr); |
4942 } | 4933 } |
4943 } | 4934 } |
4944 } else { | 4935 } else { |
4945 uint8_t mask; | 4936 uint8_t mask; |
4946 uint8_t tag; | 4937 uint8_t tag; |
4947 instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag); | 4938 instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag); |
4948 | 4939 |
4949 if (base::bits::IsPowerOfTwo32(mask)) { | 4940 if (base::bits::IsPowerOfTwo32(mask)) { |
4950 DCHECK(tag == 0 || base::bits::IsPowerOfTwo32(tag)); | 4941 DCHECK(tag == 0 || base::bits::IsPowerOfTwo32(tag)); |
4951 __ test_b(FieldOperand(temp, Map::kInstanceTypeOffset), mask); | 4942 __ test_b(FieldOperand(temp, Map::kInstanceTypeOffset), mask); |
4952 DeoptimizeIf(tag == 0 ? not_zero : zero, instr->environment()); | 4943 DeoptimizeIf(tag == 0 ? not_zero : zero, instr); |
4953 } else { | 4944 } else { |
4954 __ movzx_b(temp, FieldOperand(temp, Map::kInstanceTypeOffset)); | 4945 __ movzx_b(temp, FieldOperand(temp, Map::kInstanceTypeOffset)); |
4955 __ and_(temp, mask); | 4946 __ and_(temp, mask); |
4956 __ cmp(temp, tag); | 4947 __ cmp(temp, tag); |
4957 DeoptimizeIf(not_equal, instr->environment()); | 4948 DeoptimizeIf(not_equal, instr); |
4958 } | 4949 } |
4959 } | 4950 } |
4960 } | 4951 } |
4961 | 4952 |
4962 | 4953 |
4963 void LCodeGen::DoCheckValue(LCheckValue* instr) { | 4954 void LCodeGen::DoCheckValue(LCheckValue* instr) { |
4964 Handle<HeapObject> object = instr->hydrogen()->object().handle(); | 4955 Handle<HeapObject> object = instr->hydrogen()->object().handle(); |
4965 if (instr->hydrogen()->object_in_new_space()) { | 4956 if (instr->hydrogen()->object_in_new_space()) { |
4966 Register reg = ToRegister(instr->value()); | 4957 Register reg = ToRegister(instr->value()); |
4967 Handle<Cell> cell = isolate()->factory()->NewCell(object); | 4958 Handle<Cell> cell = isolate()->factory()->NewCell(object); |
4968 __ cmp(reg, Operand::ForCell(cell)); | 4959 __ cmp(reg, Operand::ForCell(cell)); |
4969 } else { | 4960 } else { |
4970 Operand operand = ToOperand(instr->value()); | 4961 Operand operand = ToOperand(instr->value()); |
4971 __ cmp(operand, object); | 4962 __ cmp(operand, object); |
4972 } | 4963 } |
4973 DeoptimizeIf(not_equal, instr->environment()); | 4964 DeoptimizeIf(not_equal, instr); |
4974 } | 4965 } |
4975 | 4966 |
4976 | 4967 |
4977 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) { | 4968 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) { |
4978 { | 4969 { |
4979 PushSafepointRegistersScope scope(this); | 4970 PushSafepointRegistersScope scope(this); |
4980 __ push(object); | 4971 __ push(object); |
4981 __ xor_(esi, esi); | 4972 __ xor_(esi, esi); |
4982 __ CallRuntimeSaveDoubles(Runtime::kTryMigrateInstance); | 4973 __ CallRuntimeSaveDoubles(Runtime::kTryMigrateInstance); |
4983 RecordSafepointWithRegisters( | 4974 RecordSafepointWithRegisters( |
4984 instr->pointer_map(), 1, Safepoint::kNoLazyDeopt); | 4975 instr->pointer_map(), 1, Safepoint::kNoLazyDeopt); |
4985 | 4976 |
4986 __ test(eax, Immediate(kSmiTagMask)); | 4977 __ test(eax, Immediate(kSmiTagMask)); |
4987 } | 4978 } |
4988 DeoptimizeIf(zero, instr->environment()); | 4979 DeoptimizeIf(zero, instr); |
4989 } | 4980 } |
4990 | 4981 |
4991 | 4982 |
4992 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { | 4983 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { |
4993 class DeferredCheckMaps FINAL : public LDeferredCode { | 4984 class DeferredCheckMaps FINAL : public LDeferredCode { |
4994 public: | 4985 public: |
4995 DeferredCheckMaps(LCodeGen* codegen, LCheckMaps* instr, Register object) | 4986 DeferredCheckMaps(LCodeGen* codegen, LCheckMaps* instr, Register object) |
4996 : LDeferredCode(codegen), instr_(instr), object_(object) { | 4987 : LDeferredCode(codegen), instr_(instr), object_(object) { |
4997 SetExit(check_maps()); | 4988 SetExit(check_maps()); |
4998 } | 4989 } |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5031 Handle<Map> map = maps->at(i).handle(); | 5022 Handle<Map> map = maps->at(i).handle(); |
5032 __ CompareMap(reg, map); | 5023 __ CompareMap(reg, map); |
5033 __ j(equal, &success, Label::kNear); | 5024 __ j(equal, &success, Label::kNear); |
5034 } | 5025 } |
5035 | 5026 |
5036 Handle<Map> map = maps->at(maps->size() - 1).handle(); | 5027 Handle<Map> map = maps->at(maps->size() - 1).handle(); |
5037 __ CompareMap(reg, map); | 5028 __ CompareMap(reg, map); |
5038 if (instr->hydrogen()->HasMigrationTarget()) { | 5029 if (instr->hydrogen()->HasMigrationTarget()) { |
5039 __ j(not_equal, deferred->entry()); | 5030 __ j(not_equal, deferred->entry()); |
5040 } else { | 5031 } else { |
5041 DeoptimizeIf(not_equal, instr->environment()); | 5032 DeoptimizeIf(not_equal, instr); |
5042 } | 5033 } |
5043 | 5034 |
5044 __ bind(&success); | 5035 __ bind(&success); |
5045 } | 5036 } |
5046 | 5037 |
5047 | 5038 |
5048 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { | 5039 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { |
5049 XMMRegister value_reg = ToDoubleRegister(instr->unclamped()); | 5040 XMMRegister value_reg = ToDoubleRegister(instr->unclamped()); |
5050 XMMRegister xmm_scratch = double_scratch0(); | 5041 XMMRegister xmm_scratch = double_scratch0(); |
5051 Register result_reg = ToRegister(instr->result()); | 5042 Register result_reg = ToRegister(instr->result()); |
(...skipping 18 matching lines...) Expand all Loading... |
5070 __ JumpIfSmi(input_reg, &is_smi); | 5061 __ JumpIfSmi(input_reg, &is_smi); |
5071 | 5062 |
5072 // Check for heap number | 5063 // Check for heap number |
5073 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), | 5064 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), |
5074 factory()->heap_number_map()); | 5065 factory()->heap_number_map()); |
5075 __ j(equal, &heap_number, Label::kNear); | 5066 __ j(equal, &heap_number, Label::kNear); |
5076 | 5067 |
5077 // Check for undefined. Undefined is converted to zero for clamping | 5068 // Check for undefined. Undefined is converted to zero for clamping |
5078 // conversions. | 5069 // conversions. |
5079 __ cmp(input_reg, factory()->undefined_value()); | 5070 __ cmp(input_reg, factory()->undefined_value()); |
5080 DeoptimizeIf(not_equal, instr->environment()); | 5071 DeoptimizeIf(not_equal, instr); |
5081 __ mov(input_reg, 0); | 5072 __ mov(input_reg, 0); |
5082 __ jmp(&done, Label::kNear); | 5073 __ jmp(&done, Label::kNear); |
5083 | 5074 |
5084 // Heap number | 5075 // Heap number |
5085 __ bind(&heap_number); | 5076 __ bind(&heap_number); |
5086 __ movsd(xmm_scratch, FieldOperand(input_reg, HeapNumber::kValueOffset)); | 5077 __ movsd(xmm_scratch, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
5087 __ ClampDoubleToUint8(xmm_scratch, temp_xmm_reg, input_reg); | 5078 __ ClampDoubleToUint8(xmm_scratch, temp_xmm_reg, input_reg); |
5088 __ jmp(&done, Label::kNear); | 5079 __ jmp(&done, Label::kNear); |
5089 | 5080 |
5090 // smi | 5081 // smi |
(...skipping 375 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5466 void LCodeGen::DoDeoptimize(LDeoptimize* instr) { | 5457 void LCodeGen::DoDeoptimize(LDeoptimize* instr) { |
5467 Deoptimizer::BailoutType type = instr->hydrogen()->type(); | 5458 Deoptimizer::BailoutType type = instr->hydrogen()->type(); |
5468 // TODO(danno): Stubs expect all deopts to be lazy for historical reasons (the | 5459 // TODO(danno): Stubs expect all deopts to be lazy for historical reasons (the |
5469 // needed return address), even though the implementation of LAZY and EAGER is | 5460 // needed return address), even though the implementation of LAZY and EAGER is |
5470 // now identical. When LAZY is eventually completely folded into EAGER, remove | 5461 // now identical. When LAZY is eventually completely folded into EAGER, remove |
5471 // the special case below. | 5462 // the special case below. |
5472 if (info()->IsStub() && type == Deoptimizer::EAGER) { | 5463 if (info()->IsStub() && type == Deoptimizer::EAGER) { |
5473 type = Deoptimizer::LAZY; | 5464 type = Deoptimizer::LAZY; |
5474 } | 5465 } |
5475 Comment(";;; deoptimize: %s", instr->hydrogen()->reason()); | 5466 Comment(";;; deoptimize: %s", instr->hydrogen()->reason()); |
5476 DeoptimizeIf(no_condition, instr->environment(), type); | 5467 DeoptimizeIf(no_condition, instr, type); |
5477 } | 5468 } |
5478 | 5469 |
5479 | 5470 |
5480 void LCodeGen::DoDummy(LDummy* instr) { | 5471 void LCodeGen::DoDummy(LDummy* instr) { |
5481 // Nothing to see here, move on! | 5472 // Nothing to see here, move on! |
5482 } | 5473 } |
5483 | 5474 |
5484 | 5475 |
5485 void LCodeGen::DoDummyUse(LDummyUse* instr) { | 5476 void LCodeGen::DoDummyUse(LDummyUse* instr) { |
5486 // Nothing to see here, move on! | 5477 // Nothing to see here, move on! |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5561 DCHECK(!environment->HasBeenRegistered()); | 5552 DCHECK(!environment->HasBeenRegistered()); |
5562 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); | 5553 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); |
5563 | 5554 |
5564 GenerateOsrPrologue(); | 5555 GenerateOsrPrologue(); |
5565 } | 5556 } |
5566 | 5557 |
5567 | 5558 |
5568 void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) { | 5559 void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) { |
5569 DCHECK(ToRegister(instr->context()).is(esi)); | 5560 DCHECK(ToRegister(instr->context()).is(esi)); |
5570 __ cmp(eax, isolate()->factory()->undefined_value()); | 5561 __ cmp(eax, isolate()->factory()->undefined_value()); |
5571 DeoptimizeIf(equal, instr->environment()); | 5562 DeoptimizeIf(equal, instr); |
5572 | 5563 |
5573 __ cmp(eax, isolate()->factory()->null_value()); | 5564 __ cmp(eax, isolate()->factory()->null_value()); |
5574 DeoptimizeIf(equal, instr->environment()); | 5565 DeoptimizeIf(equal, instr); |
5575 | 5566 |
5576 __ test(eax, Immediate(kSmiTagMask)); | 5567 __ test(eax, Immediate(kSmiTagMask)); |
5577 DeoptimizeIf(zero, instr->environment()); | 5568 DeoptimizeIf(zero, instr); |
5578 | 5569 |
5579 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); | 5570 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); |
5580 __ CmpObjectType(eax, LAST_JS_PROXY_TYPE, ecx); | 5571 __ CmpObjectType(eax, LAST_JS_PROXY_TYPE, ecx); |
5581 DeoptimizeIf(below_equal, instr->environment()); | 5572 DeoptimizeIf(below_equal, instr); |
5582 | 5573 |
5583 Label use_cache, call_runtime; | 5574 Label use_cache, call_runtime; |
5584 __ CheckEnumCache(&call_runtime); | 5575 __ CheckEnumCache(&call_runtime); |
5585 | 5576 |
5586 __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset)); | 5577 __ mov(eax, FieldOperand(eax, HeapObject::kMapOffset)); |
5587 __ jmp(&use_cache, Label::kNear); | 5578 __ jmp(&use_cache, Label::kNear); |
5588 | 5579 |
5589 // Get the set of properties to enumerate. | 5580 // Get the set of properties to enumerate. |
5590 __ bind(&call_runtime); | 5581 __ bind(&call_runtime); |
5591 __ push(eax); | 5582 __ push(eax); |
5592 CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr); | 5583 CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr); |
5593 | 5584 |
5594 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), | 5585 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), |
5595 isolate()->factory()->meta_map()); | 5586 isolate()->factory()->meta_map()); |
5596 DeoptimizeIf(not_equal, instr->environment()); | 5587 DeoptimizeIf(not_equal, instr); |
5597 __ bind(&use_cache); | 5588 __ bind(&use_cache); |
5598 } | 5589 } |
5599 | 5590 |
5600 | 5591 |
5601 void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) { | 5592 void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) { |
5602 Register map = ToRegister(instr->map()); | 5593 Register map = ToRegister(instr->map()); |
5603 Register result = ToRegister(instr->result()); | 5594 Register result = ToRegister(instr->result()); |
5604 Label load_cache, done; | 5595 Label load_cache, done; |
5605 __ EnumLength(result, map); | 5596 __ EnumLength(result, map); |
5606 __ cmp(result, Immediate(Smi::FromInt(0))); | 5597 __ cmp(result, Immediate(Smi::FromInt(0))); |
5607 __ j(not_equal, &load_cache, Label::kNear); | 5598 __ j(not_equal, &load_cache, Label::kNear); |
5608 __ mov(result, isolate()->factory()->empty_fixed_array()); | 5599 __ mov(result, isolate()->factory()->empty_fixed_array()); |
5609 __ jmp(&done, Label::kNear); | 5600 __ jmp(&done, Label::kNear); |
5610 | 5601 |
5611 __ bind(&load_cache); | 5602 __ bind(&load_cache); |
5612 __ LoadInstanceDescriptors(map, result); | 5603 __ LoadInstanceDescriptors(map, result); |
5613 __ mov(result, | 5604 __ mov(result, |
5614 FieldOperand(result, DescriptorArray::kEnumCacheOffset)); | 5605 FieldOperand(result, DescriptorArray::kEnumCacheOffset)); |
5615 __ mov(result, | 5606 __ mov(result, |
5616 FieldOperand(result, FixedArray::SizeFor(instr->idx()))); | 5607 FieldOperand(result, FixedArray::SizeFor(instr->idx()))); |
5617 __ bind(&done); | 5608 __ bind(&done); |
5618 __ test(result, result); | 5609 __ test(result, result); |
5619 DeoptimizeIf(equal, instr->environment()); | 5610 DeoptimizeIf(equal, instr); |
5620 } | 5611 } |
5621 | 5612 |
5622 | 5613 |
5623 void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) { | 5614 void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) { |
5624 Register object = ToRegister(instr->value()); | 5615 Register object = ToRegister(instr->value()); |
5625 __ cmp(ToRegister(instr->map()), | 5616 __ cmp(ToRegister(instr->map()), |
5626 FieldOperand(object, HeapObject::kMapOffset)); | 5617 FieldOperand(object, HeapObject::kMapOffset)); |
5627 DeoptimizeIf(not_equal, instr->environment()); | 5618 DeoptimizeIf(not_equal, instr); |
5628 } | 5619 } |
5629 | 5620 |
5630 | 5621 |
5631 void LCodeGen::DoDeferredLoadMutableDouble(LLoadFieldByIndex* instr, | 5622 void LCodeGen::DoDeferredLoadMutableDouble(LLoadFieldByIndex* instr, |
5632 Register object, | 5623 Register object, |
5633 Register index) { | 5624 Register index) { |
5634 PushSafepointRegistersScope scope(this); | 5625 PushSafepointRegistersScope scope(this); |
5635 __ push(object); | 5626 __ push(object); |
5636 __ push(index); | 5627 __ push(index); |
5637 __ xor_(esi, esi); | 5628 __ xor_(esi, esi); |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5711 CallRuntime(Runtime::kPushBlockContext, 2, instr); | 5702 CallRuntime(Runtime::kPushBlockContext, 2, instr); |
5712 RecordSafepoint(Safepoint::kNoLazyDeopt); | 5703 RecordSafepoint(Safepoint::kNoLazyDeopt); |
5713 } | 5704 } |
5714 | 5705 |
5715 | 5706 |
5716 #undef __ | 5707 #undef __ |
5717 | 5708 |
5718 } } // namespace v8::internal | 5709 } } // namespace v8::internal |
5719 | 5710 |
5720 #endif // V8_TARGET_ARCH_IA32 | 5711 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |