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 #include "src/arm/lithium-codegen-arm.h" | 7 #include "src/arm/lithium-codegen-arm.h" |
8 #include "src/arm/lithium-gap-resolver-arm.h" | 8 #include "src/arm/lithium-gap-resolver-arm.h" |
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 822 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
833 int pc_offset = masm()->pc_offset(); | 833 int pc_offset = masm()->pc_offset(); |
834 environment->Register(deoptimization_index, | 834 environment->Register(deoptimization_index, |
835 translation.index(), | 835 translation.index(), |
836 (mode == Safepoint::kLazyDeopt) ? pc_offset : -1); | 836 (mode == Safepoint::kLazyDeopt) ? pc_offset : -1); |
837 deoptimizations_.Add(environment, zone()); | 837 deoptimizations_.Add(environment, zone()); |
838 } | 838 } |
839 } | 839 } |
840 | 840 |
841 | 841 |
842 void LCodeGen::DeoptimizeIf(Condition condition, LInstruction* instr, | 842 void LCodeGen::DeoptimizeIf(Condition condition, LInstruction* instr, |
843 Deoptimizer::DeoptReason deopt_reason, | 843 const char* detail, |
844 Deoptimizer::BailoutType bailout_type) { | 844 Deoptimizer::BailoutType bailout_type) { |
845 LEnvironment* environment = instr->environment(); | 845 LEnvironment* environment = instr->environment(); |
846 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); | 846 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); |
847 DCHECK(environment->HasBeenRegistered()); | 847 DCHECK(environment->HasBeenRegistered()); |
848 int id = environment->deoptimization_index(); | 848 int id = environment->deoptimization_index(); |
849 DCHECK(info()->IsOptimizing() || info()->IsStub()); | 849 DCHECK(info()->IsOptimizing() || info()->IsStub()); |
850 Address entry = | 850 Address entry = |
851 Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type); | 851 Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type); |
852 if (entry == NULL) { | 852 if (entry == NULL) { |
853 Abort(kBailoutWasNotPrepared); | 853 Abort(kBailoutWasNotPrepared); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
887 condition = ne; | 887 condition = ne; |
888 __ cmp(scratch, Operand::Zero()); | 888 __ cmp(scratch, Operand::Zero()); |
889 } | 889 } |
890 } | 890 } |
891 | 891 |
892 if (info()->ShouldTrapOnDeopt()) { | 892 if (info()->ShouldTrapOnDeopt()) { |
893 __ stop("trap_on_deopt", condition); | 893 __ stop("trap_on_deopt", condition); |
894 } | 894 } |
895 | 895 |
896 Deoptimizer::Reason reason(instr->hydrogen_value()->position().raw(), | 896 Deoptimizer::Reason reason(instr->hydrogen_value()->position().raw(), |
897 instr->Mnemonic(), deopt_reason); | 897 instr->Mnemonic(), detail); |
898 DCHECK(info()->IsStub() || frame_is_built_); | 898 DCHECK(info()->IsStub() || frame_is_built_); |
899 // Go through jump table if we need to handle condition, build frame, or | 899 // Go through jump table if we need to handle condition, build frame, or |
900 // restore caller doubles. | 900 // restore caller doubles. |
901 if (condition == al && frame_is_built_ && | 901 if (condition == al && frame_is_built_ && |
902 !info()->saves_caller_doubles()) { | 902 !info()->saves_caller_doubles()) { |
903 DeoptComment(reason); | 903 DeoptComment(reason); |
904 __ Call(entry, RelocInfo::RUNTIME_ENTRY); | 904 __ Call(entry, RelocInfo::RUNTIME_ENTRY); |
905 } else { | 905 } else { |
906 Deoptimizer::JumpTableEntry table_entry(entry, reason, bailout_type, | 906 Deoptimizer::JumpTableEntry table_entry(entry, reason, bailout_type, |
907 !frame_is_built_); | 907 !frame_is_built_); |
908 // We often have several deopts to the same entry, reuse the last | 908 // We often have several deopts to the same entry, reuse the last |
909 // jump entry if this is the case. | 909 // jump entry if this is the case. |
910 if (jump_table_.is_empty() || | 910 if (jump_table_.is_empty() || |
911 !table_entry.IsEquivalentTo(jump_table_.last())) { | 911 !table_entry.IsEquivalentTo(jump_table_.last())) { |
912 jump_table_.Add(table_entry, zone()); | 912 jump_table_.Add(table_entry, zone()); |
913 } | 913 } |
914 __ b(condition, &jump_table_.last().label); | 914 __ b(condition, &jump_table_.last().label); |
915 } | 915 } |
916 } | 916 } |
917 | 917 |
918 | 918 |
919 void LCodeGen::DeoptimizeIf(Condition condition, LInstruction* instr, | 919 void LCodeGen::DeoptimizeIf(Condition condition, LInstruction* instr, |
920 Deoptimizer::DeoptReason deopt_reason) { | 920 const char* detail) { |
921 Deoptimizer::BailoutType bailout_type = info()->IsStub() | 921 Deoptimizer::BailoutType bailout_type = info()->IsStub() |
922 ? Deoptimizer::LAZY | 922 ? Deoptimizer::LAZY |
923 : Deoptimizer::EAGER; | 923 : Deoptimizer::EAGER; |
924 DeoptimizeIf(condition, instr, deopt_reason, bailout_type); | 924 DeoptimizeIf(condition, instr, detail, bailout_type); |
925 } | 925 } |
926 | 926 |
927 | 927 |
928 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { | 928 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { |
929 int length = deoptimizations_.length(); | 929 int length = deoptimizations_.length(); |
930 if (length == 0) return; | 930 if (length == 0) return; |
931 Handle<DeoptimizationInputData> data = | 931 Handle<DeoptimizationInputData> data = |
932 DeoptimizationInputData::New(isolate(), length, TENURED); | 932 DeoptimizationInputData::New(isolate(), length, TENURED); |
933 | 933 |
934 Handle<ByteArray> translations = | 934 Handle<ByteArray> translations = |
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1150 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); | 1150 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); |
1151 Label dividend_is_not_negative, done; | 1151 Label dividend_is_not_negative, done; |
1152 if (hmod->CheckFlag(HValue::kLeftCanBeNegative)) { | 1152 if (hmod->CheckFlag(HValue::kLeftCanBeNegative)) { |
1153 __ cmp(dividend, Operand::Zero()); | 1153 __ cmp(dividend, Operand::Zero()); |
1154 __ b(pl, ÷nd_is_not_negative); | 1154 __ b(pl, ÷nd_is_not_negative); |
1155 // Note that this is correct even for kMinInt operands. | 1155 // Note that this is correct even for kMinInt operands. |
1156 __ rsb(dividend, dividend, Operand::Zero()); | 1156 __ rsb(dividend, dividend, Operand::Zero()); |
1157 __ and_(dividend, dividend, Operand(mask)); | 1157 __ and_(dividend, dividend, Operand(mask)); |
1158 __ rsb(dividend, dividend, Operand::Zero(), SetCC); | 1158 __ rsb(dividend, dividend, Operand::Zero(), SetCC); |
1159 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1159 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1160 DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero); | 1160 DeoptimizeIf(eq, instr, "minus zero"); |
1161 } | 1161 } |
1162 __ b(&done); | 1162 __ b(&done); |
1163 } | 1163 } |
1164 | 1164 |
1165 __ bind(÷nd_is_not_negative); | 1165 __ bind(÷nd_is_not_negative); |
1166 __ and_(dividend, dividend, Operand(mask)); | 1166 __ and_(dividend, dividend, Operand(mask)); |
1167 __ bind(&done); | 1167 __ bind(&done); |
1168 } | 1168 } |
1169 | 1169 |
1170 | 1170 |
1171 void LCodeGen::DoModByConstI(LModByConstI* instr) { | 1171 void LCodeGen::DoModByConstI(LModByConstI* instr) { |
1172 Register dividend = ToRegister(instr->dividend()); | 1172 Register dividend = ToRegister(instr->dividend()); |
1173 int32_t divisor = instr->divisor(); | 1173 int32_t divisor = instr->divisor(); |
1174 Register result = ToRegister(instr->result()); | 1174 Register result = ToRegister(instr->result()); |
1175 DCHECK(!dividend.is(result)); | 1175 DCHECK(!dividend.is(result)); |
1176 | 1176 |
1177 if (divisor == 0) { | 1177 if (divisor == 0) { |
1178 DeoptimizeIf(al, instr, Deoptimizer::kDivisionByZero); | 1178 DeoptimizeIf(al, instr, "division by zero"); |
1179 return; | 1179 return; |
1180 } | 1180 } |
1181 | 1181 |
1182 __ TruncatingDiv(result, dividend, Abs(divisor)); | 1182 __ TruncatingDiv(result, dividend, Abs(divisor)); |
1183 __ mov(ip, Operand(Abs(divisor))); | 1183 __ mov(ip, Operand(Abs(divisor))); |
1184 __ smull(result, ip, result, ip); | 1184 __ smull(result, ip, result, ip); |
1185 __ sub(result, dividend, result, SetCC); | 1185 __ sub(result, dividend, result, SetCC); |
1186 | 1186 |
1187 // Check for negative zero. | 1187 // Check for negative zero. |
1188 HMod* hmod = instr->hydrogen(); | 1188 HMod* hmod = instr->hydrogen(); |
1189 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1189 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1190 Label remainder_not_zero; | 1190 Label remainder_not_zero; |
1191 __ b(ne, &remainder_not_zero); | 1191 __ b(ne, &remainder_not_zero); |
1192 __ cmp(dividend, Operand::Zero()); | 1192 __ cmp(dividend, Operand::Zero()); |
1193 DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero); | 1193 DeoptimizeIf(lt, instr, "minus zero"); |
1194 __ bind(&remainder_not_zero); | 1194 __ bind(&remainder_not_zero); |
1195 } | 1195 } |
1196 } | 1196 } |
1197 | 1197 |
1198 | 1198 |
1199 void LCodeGen::DoModI(LModI* instr) { | 1199 void LCodeGen::DoModI(LModI* instr) { |
1200 HMod* hmod = instr->hydrogen(); | 1200 HMod* hmod = instr->hydrogen(); |
1201 if (CpuFeatures::IsSupported(SUDIV)) { | 1201 if (CpuFeatures::IsSupported(SUDIV)) { |
1202 CpuFeatureScope scope(masm(), SUDIV); | 1202 CpuFeatureScope scope(masm(), SUDIV); |
1203 | 1203 |
1204 Register left_reg = ToRegister(instr->left()); | 1204 Register left_reg = ToRegister(instr->left()); |
1205 Register right_reg = ToRegister(instr->right()); | 1205 Register right_reg = ToRegister(instr->right()); |
1206 Register result_reg = ToRegister(instr->result()); | 1206 Register result_reg = ToRegister(instr->result()); |
1207 | 1207 |
1208 Label done; | 1208 Label done; |
1209 // Check for x % 0, sdiv might signal an exception. We have to deopt in this | 1209 // Check for x % 0, sdiv might signal an exception. We have to deopt in this |
1210 // case because we can't return a NaN. | 1210 // case because we can't return a NaN. |
1211 if (hmod->CheckFlag(HValue::kCanBeDivByZero)) { | 1211 if (hmod->CheckFlag(HValue::kCanBeDivByZero)) { |
1212 __ cmp(right_reg, Operand::Zero()); | 1212 __ cmp(right_reg, Operand::Zero()); |
1213 DeoptimizeIf(eq, instr, Deoptimizer::kDivisionByZero); | 1213 DeoptimizeIf(eq, instr, "division by zero"); |
1214 } | 1214 } |
1215 | 1215 |
1216 // Check for kMinInt % -1, sdiv will return kMinInt, which is not what we | 1216 // Check for kMinInt % -1, sdiv will return kMinInt, which is not what we |
1217 // want. We have to deopt if we care about -0, because we can't return that. | 1217 // want. We have to deopt if we care about -0, because we can't return that. |
1218 if (hmod->CheckFlag(HValue::kCanOverflow)) { | 1218 if (hmod->CheckFlag(HValue::kCanOverflow)) { |
1219 Label no_overflow_possible; | 1219 Label no_overflow_possible; |
1220 __ cmp(left_reg, Operand(kMinInt)); | 1220 __ cmp(left_reg, Operand(kMinInt)); |
1221 __ b(ne, &no_overflow_possible); | 1221 __ b(ne, &no_overflow_possible); |
1222 __ cmp(right_reg, Operand(-1)); | 1222 __ cmp(right_reg, Operand(-1)); |
1223 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1223 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1224 DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero); | 1224 DeoptimizeIf(eq, instr, "minus zero"); |
1225 } else { | 1225 } else { |
1226 __ b(ne, &no_overflow_possible); | 1226 __ b(ne, &no_overflow_possible); |
1227 __ mov(result_reg, Operand::Zero()); | 1227 __ mov(result_reg, Operand::Zero()); |
1228 __ jmp(&done); | 1228 __ jmp(&done); |
1229 } | 1229 } |
1230 __ bind(&no_overflow_possible); | 1230 __ bind(&no_overflow_possible); |
1231 } | 1231 } |
1232 | 1232 |
1233 // For 'r3 = r1 % r2' we can have the following ARM code: | 1233 // For 'r3 = r1 % r2' we can have the following ARM code: |
1234 // sdiv r3, r1, r2 | 1234 // sdiv r3, r1, r2 |
1235 // mls r3, r3, r2, r1 | 1235 // mls r3, r3, r2, r1 |
1236 | 1236 |
1237 __ sdiv(result_reg, left_reg, right_reg); | 1237 __ sdiv(result_reg, left_reg, right_reg); |
1238 __ Mls(result_reg, result_reg, right_reg, left_reg); | 1238 __ Mls(result_reg, result_reg, right_reg, left_reg); |
1239 | 1239 |
1240 // If we care about -0, test if the dividend is <0 and the result is 0. | 1240 // If we care about -0, test if the dividend is <0 and the result is 0. |
1241 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1241 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1242 __ cmp(result_reg, Operand::Zero()); | 1242 __ cmp(result_reg, Operand::Zero()); |
1243 __ b(ne, &done); | 1243 __ b(ne, &done); |
1244 __ cmp(left_reg, Operand::Zero()); | 1244 __ cmp(left_reg, Operand::Zero()); |
1245 DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero); | 1245 DeoptimizeIf(lt, instr, "minus zero"); |
1246 } | 1246 } |
1247 __ bind(&done); | 1247 __ bind(&done); |
1248 | 1248 |
1249 } else { | 1249 } else { |
1250 // General case, without any SDIV support. | 1250 // General case, without any SDIV support. |
1251 Register left_reg = ToRegister(instr->left()); | 1251 Register left_reg = ToRegister(instr->left()); |
1252 Register right_reg = ToRegister(instr->right()); | 1252 Register right_reg = ToRegister(instr->right()); |
1253 Register result_reg = ToRegister(instr->result()); | 1253 Register result_reg = ToRegister(instr->result()); |
1254 Register scratch = scratch0(); | 1254 Register scratch = scratch0(); |
1255 DCHECK(!scratch.is(left_reg)); | 1255 DCHECK(!scratch.is(left_reg)); |
1256 DCHECK(!scratch.is(right_reg)); | 1256 DCHECK(!scratch.is(right_reg)); |
1257 DCHECK(!scratch.is(result_reg)); | 1257 DCHECK(!scratch.is(result_reg)); |
1258 DwVfpRegister dividend = ToDoubleRegister(instr->temp()); | 1258 DwVfpRegister dividend = ToDoubleRegister(instr->temp()); |
1259 DwVfpRegister divisor = ToDoubleRegister(instr->temp2()); | 1259 DwVfpRegister divisor = ToDoubleRegister(instr->temp2()); |
1260 DCHECK(!divisor.is(dividend)); | 1260 DCHECK(!divisor.is(dividend)); |
1261 LowDwVfpRegister quotient = double_scratch0(); | 1261 LowDwVfpRegister quotient = double_scratch0(); |
1262 DCHECK(!quotient.is(dividend)); | 1262 DCHECK(!quotient.is(dividend)); |
1263 DCHECK(!quotient.is(divisor)); | 1263 DCHECK(!quotient.is(divisor)); |
1264 | 1264 |
1265 Label done; | 1265 Label done; |
1266 // Check for x % 0, we have to deopt in this case because we can't return a | 1266 // Check for x % 0, we have to deopt in this case because we can't return a |
1267 // NaN. | 1267 // NaN. |
1268 if (hmod->CheckFlag(HValue::kCanBeDivByZero)) { | 1268 if (hmod->CheckFlag(HValue::kCanBeDivByZero)) { |
1269 __ cmp(right_reg, Operand::Zero()); | 1269 __ cmp(right_reg, Operand::Zero()); |
1270 DeoptimizeIf(eq, instr, Deoptimizer::kDivisionByZero); | 1270 DeoptimizeIf(eq, instr, "division by zero"); |
1271 } | 1271 } |
1272 | 1272 |
1273 __ Move(result_reg, left_reg); | 1273 __ Move(result_reg, left_reg); |
1274 // Load the arguments in VFP registers. The divisor value is preloaded | 1274 // Load the arguments in VFP registers. The divisor value is preloaded |
1275 // before. Be careful that 'right_reg' is only live on entry. | 1275 // before. Be careful that 'right_reg' is only live on entry. |
1276 // TODO(svenpanne) The last comments seems to be wrong nowadays. | 1276 // TODO(svenpanne) The last comments seems to be wrong nowadays. |
1277 __ vmov(double_scratch0().low(), left_reg); | 1277 __ vmov(double_scratch0().low(), left_reg); |
1278 __ vcvt_f64_s32(dividend, double_scratch0().low()); | 1278 __ vcvt_f64_s32(dividend, double_scratch0().low()); |
1279 __ vmov(double_scratch0().low(), right_reg); | 1279 __ vmov(double_scratch0().low(), right_reg); |
1280 __ vcvt_f64_s32(divisor, double_scratch0().low()); | 1280 __ vcvt_f64_s32(divisor, double_scratch0().low()); |
1281 | 1281 |
1282 // We do not care about the sign of the divisor. Note that we still handle | 1282 // We do not care about the sign of the divisor. Note that we still handle |
1283 // the kMinInt % -1 case correctly, though. | 1283 // the kMinInt % -1 case correctly, though. |
1284 __ vabs(divisor, divisor); | 1284 __ vabs(divisor, divisor); |
1285 // Compute the quotient and round it to a 32bit integer. | 1285 // Compute the quotient and round it to a 32bit integer. |
1286 __ vdiv(quotient, dividend, divisor); | 1286 __ vdiv(quotient, dividend, divisor); |
1287 __ vcvt_s32_f64(quotient.low(), quotient); | 1287 __ vcvt_s32_f64(quotient.low(), quotient); |
1288 __ vcvt_f64_s32(quotient, quotient.low()); | 1288 __ vcvt_f64_s32(quotient, quotient.low()); |
1289 | 1289 |
1290 // Compute the remainder in result. | 1290 // Compute the remainder in result. |
1291 __ vmul(double_scratch0(), divisor, quotient); | 1291 __ vmul(double_scratch0(), divisor, quotient); |
1292 __ vcvt_s32_f64(double_scratch0().low(), double_scratch0()); | 1292 __ vcvt_s32_f64(double_scratch0().low(), double_scratch0()); |
1293 __ vmov(scratch, double_scratch0().low()); | 1293 __ vmov(scratch, double_scratch0().low()); |
1294 __ sub(result_reg, left_reg, scratch, SetCC); | 1294 __ sub(result_reg, left_reg, scratch, SetCC); |
1295 | 1295 |
1296 // If we care about -0, test if the dividend is <0 and the result is 0. | 1296 // If we care about -0, test if the dividend is <0 and the result is 0. |
1297 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1297 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1298 __ b(ne, &done); | 1298 __ b(ne, &done); |
1299 __ cmp(left_reg, Operand::Zero()); | 1299 __ cmp(left_reg, Operand::Zero()); |
1300 DeoptimizeIf(mi, instr, Deoptimizer::kMinusZero); | 1300 DeoptimizeIf(mi, instr, "minus zero"); |
1301 } | 1301 } |
1302 __ bind(&done); | 1302 __ bind(&done); |
1303 } | 1303 } |
1304 } | 1304 } |
1305 | 1305 |
1306 | 1306 |
1307 void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) { | 1307 void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) { |
1308 Register dividend = ToRegister(instr->dividend()); | 1308 Register dividend = ToRegister(instr->dividend()); |
1309 int32_t divisor = instr->divisor(); | 1309 int32_t divisor = instr->divisor(); |
1310 Register result = ToRegister(instr->result()); | 1310 Register result = ToRegister(instr->result()); |
1311 DCHECK(divisor == kMinInt || base::bits::IsPowerOfTwo32(Abs(divisor))); | 1311 DCHECK(divisor == kMinInt || base::bits::IsPowerOfTwo32(Abs(divisor))); |
1312 DCHECK(!result.is(dividend)); | 1312 DCHECK(!result.is(dividend)); |
1313 | 1313 |
1314 // Check for (0 / -x) that will produce negative zero. | 1314 // Check for (0 / -x) that will produce negative zero. |
1315 HDiv* hdiv = instr->hydrogen(); | 1315 HDiv* hdiv = instr->hydrogen(); |
1316 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { | 1316 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { |
1317 __ cmp(dividend, Operand::Zero()); | 1317 __ cmp(dividend, Operand::Zero()); |
1318 DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero); | 1318 DeoptimizeIf(eq, instr, "minus zero"); |
1319 } | 1319 } |
1320 // Check for (kMinInt / -1). | 1320 // Check for (kMinInt / -1). |
1321 if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) { | 1321 if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) { |
1322 __ cmp(dividend, Operand(kMinInt)); | 1322 __ cmp(dividend, Operand(kMinInt)); |
1323 DeoptimizeIf(eq, instr, Deoptimizer::kOverflow); | 1323 DeoptimizeIf(eq, instr, "overflow"); |
1324 } | 1324 } |
1325 // Deoptimize if remainder will not be 0. | 1325 // Deoptimize if remainder will not be 0. |
1326 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) && | 1326 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) && |
1327 divisor != 1 && divisor != -1) { | 1327 divisor != 1 && divisor != -1) { |
1328 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); | 1328 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); |
1329 __ tst(dividend, Operand(mask)); | 1329 __ tst(dividend, Operand(mask)); |
1330 DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecision); | 1330 DeoptimizeIf(ne, instr, "lost precision"); |
1331 } | 1331 } |
1332 | 1332 |
1333 if (divisor == -1) { // Nice shortcut, not needed for correctness. | 1333 if (divisor == -1) { // Nice shortcut, not needed for correctness. |
1334 __ rsb(result, dividend, Operand(0)); | 1334 __ rsb(result, dividend, Operand(0)); |
1335 return; | 1335 return; |
1336 } | 1336 } |
1337 int32_t shift = WhichPowerOf2Abs(divisor); | 1337 int32_t shift = WhichPowerOf2Abs(divisor); |
1338 if (shift == 0) { | 1338 if (shift == 0) { |
1339 __ mov(result, dividend); | 1339 __ mov(result, dividend); |
1340 } else if (shift == 1) { | 1340 } else if (shift == 1) { |
1341 __ add(result, dividend, Operand(dividend, LSR, 31)); | 1341 __ add(result, dividend, Operand(dividend, LSR, 31)); |
1342 } else { | 1342 } else { |
1343 __ mov(result, Operand(dividend, ASR, 31)); | 1343 __ mov(result, Operand(dividend, ASR, 31)); |
1344 __ add(result, dividend, Operand(result, LSR, 32 - shift)); | 1344 __ add(result, dividend, Operand(result, LSR, 32 - shift)); |
1345 } | 1345 } |
1346 if (shift > 0) __ mov(result, Operand(result, ASR, shift)); | 1346 if (shift > 0) __ mov(result, Operand(result, ASR, shift)); |
1347 if (divisor < 0) __ rsb(result, result, Operand(0)); | 1347 if (divisor < 0) __ rsb(result, result, Operand(0)); |
1348 } | 1348 } |
1349 | 1349 |
1350 | 1350 |
1351 void LCodeGen::DoDivByConstI(LDivByConstI* instr) { | 1351 void LCodeGen::DoDivByConstI(LDivByConstI* instr) { |
1352 Register dividend = ToRegister(instr->dividend()); | 1352 Register dividend = ToRegister(instr->dividend()); |
1353 int32_t divisor = instr->divisor(); | 1353 int32_t divisor = instr->divisor(); |
1354 Register result = ToRegister(instr->result()); | 1354 Register result = ToRegister(instr->result()); |
1355 DCHECK(!dividend.is(result)); | 1355 DCHECK(!dividend.is(result)); |
1356 | 1356 |
1357 if (divisor == 0) { | 1357 if (divisor == 0) { |
1358 DeoptimizeIf(al, instr, Deoptimizer::kDivisionByZero); | 1358 DeoptimizeIf(al, instr, "division by zero"); |
1359 return; | 1359 return; |
1360 } | 1360 } |
1361 | 1361 |
1362 // Check for (0 / -x) that will produce negative zero. | 1362 // Check for (0 / -x) that will produce negative zero. |
1363 HDiv* hdiv = instr->hydrogen(); | 1363 HDiv* hdiv = instr->hydrogen(); |
1364 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { | 1364 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { |
1365 __ cmp(dividend, Operand::Zero()); | 1365 __ cmp(dividend, Operand::Zero()); |
1366 DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero); | 1366 DeoptimizeIf(eq, instr, "minus zero"); |
1367 } | 1367 } |
1368 | 1368 |
1369 __ TruncatingDiv(result, dividend, Abs(divisor)); | 1369 __ TruncatingDiv(result, dividend, Abs(divisor)); |
1370 if (divisor < 0) __ rsb(result, result, Operand::Zero()); | 1370 if (divisor < 0) __ rsb(result, result, Operand::Zero()); |
1371 | 1371 |
1372 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) { | 1372 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) { |
1373 __ mov(ip, Operand(divisor)); | 1373 __ mov(ip, Operand(divisor)); |
1374 __ smull(scratch0(), ip, result, ip); | 1374 __ smull(scratch0(), ip, result, ip); |
1375 __ sub(scratch0(), scratch0(), dividend, SetCC); | 1375 __ sub(scratch0(), scratch0(), dividend, SetCC); |
1376 DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecision); | 1376 DeoptimizeIf(ne, instr, "lost precision"); |
1377 } | 1377 } |
1378 } | 1378 } |
1379 | 1379 |
1380 | 1380 |
1381 // TODO(svenpanne) Refactor this to avoid code duplication with DoFlooringDivI. | 1381 // TODO(svenpanne) Refactor this to avoid code duplication with DoFlooringDivI. |
1382 void LCodeGen::DoDivI(LDivI* instr) { | 1382 void LCodeGen::DoDivI(LDivI* instr) { |
1383 HBinaryOperation* hdiv = instr->hydrogen(); | 1383 HBinaryOperation* hdiv = instr->hydrogen(); |
1384 Register dividend = ToRegister(instr->dividend()); | 1384 Register dividend = ToRegister(instr->dividend()); |
1385 Register divisor = ToRegister(instr->divisor()); | 1385 Register divisor = ToRegister(instr->divisor()); |
1386 Register result = ToRegister(instr->result()); | 1386 Register result = ToRegister(instr->result()); |
1387 | 1387 |
1388 // Check for x / 0. | 1388 // Check for x / 0. |
1389 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { | 1389 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { |
1390 __ cmp(divisor, Operand::Zero()); | 1390 __ cmp(divisor, Operand::Zero()); |
1391 DeoptimizeIf(eq, instr, Deoptimizer::kDivisionByZero); | 1391 DeoptimizeIf(eq, instr, "division by zero"); |
1392 } | 1392 } |
1393 | 1393 |
1394 // Check for (0 / -x) that will produce negative zero. | 1394 // Check for (0 / -x) that will produce negative zero. |
1395 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1395 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1396 Label positive; | 1396 Label positive; |
1397 if (!instr->hydrogen_value()->CheckFlag(HValue::kCanBeDivByZero)) { | 1397 if (!instr->hydrogen_value()->CheckFlag(HValue::kCanBeDivByZero)) { |
1398 // Do the test only if it hadn't be done above. | 1398 // Do the test only if it hadn't be done above. |
1399 __ cmp(divisor, Operand::Zero()); | 1399 __ cmp(divisor, Operand::Zero()); |
1400 } | 1400 } |
1401 __ b(pl, &positive); | 1401 __ b(pl, &positive); |
1402 __ cmp(dividend, Operand::Zero()); | 1402 __ cmp(dividend, Operand::Zero()); |
1403 DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero); | 1403 DeoptimizeIf(eq, instr, "minus zero"); |
1404 __ bind(&positive); | 1404 __ bind(&positive); |
1405 } | 1405 } |
1406 | 1406 |
1407 // Check for (kMinInt / -1). | 1407 // Check for (kMinInt / -1). |
1408 if (hdiv->CheckFlag(HValue::kCanOverflow) && | 1408 if (hdiv->CheckFlag(HValue::kCanOverflow) && |
1409 (!CpuFeatures::IsSupported(SUDIV) || | 1409 (!CpuFeatures::IsSupported(SUDIV) || |
1410 !hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32))) { | 1410 !hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32))) { |
1411 // We don't need to check for overflow when truncating with sdiv | 1411 // We don't need to check for overflow when truncating with sdiv |
1412 // support because, on ARM, sdiv kMinInt, -1 -> kMinInt. | 1412 // support because, on ARM, sdiv kMinInt, -1 -> kMinInt. |
1413 __ cmp(dividend, Operand(kMinInt)); | 1413 __ cmp(dividend, Operand(kMinInt)); |
1414 __ cmp(divisor, Operand(-1), eq); | 1414 __ cmp(divisor, Operand(-1), eq); |
1415 DeoptimizeIf(eq, instr, Deoptimizer::kOverflow); | 1415 DeoptimizeIf(eq, instr, "overflow"); |
1416 } | 1416 } |
1417 | 1417 |
1418 if (CpuFeatures::IsSupported(SUDIV)) { | 1418 if (CpuFeatures::IsSupported(SUDIV)) { |
1419 CpuFeatureScope scope(masm(), SUDIV); | 1419 CpuFeatureScope scope(masm(), SUDIV); |
1420 __ sdiv(result, dividend, divisor); | 1420 __ sdiv(result, dividend, divisor); |
1421 } else { | 1421 } else { |
1422 DoubleRegister vleft = ToDoubleRegister(instr->temp()); | 1422 DoubleRegister vleft = ToDoubleRegister(instr->temp()); |
1423 DoubleRegister vright = double_scratch0(); | 1423 DoubleRegister vright = double_scratch0(); |
1424 __ vmov(double_scratch0().low(), dividend); | 1424 __ vmov(double_scratch0().low(), dividend); |
1425 __ vcvt_f64_s32(vleft, double_scratch0().low()); | 1425 __ vcvt_f64_s32(vleft, double_scratch0().low()); |
1426 __ vmov(double_scratch0().low(), divisor); | 1426 __ vmov(double_scratch0().low(), divisor); |
1427 __ vcvt_f64_s32(vright, double_scratch0().low()); | 1427 __ vcvt_f64_s32(vright, double_scratch0().low()); |
1428 __ vdiv(vleft, vleft, vright); // vleft now contains the result. | 1428 __ vdiv(vleft, vleft, vright); // vleft now contains the result. |
1429 __ vcvt_s32_f64(double_scratch0().low(), vleft); | 1429 __ vcvt_s32_f64(double_scratch0().low(), vleft); |
1430 __ vmov(result, double_scratch0().low()); | 1430 __ vmov(result, double_scratch0().low()); |
1431 } | 1431 } |
1432 | 1432 |
1433 if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { | 1433 if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { |
1434 // Compute remainder and deopt if it's not zero. | 1434 // Compute remainder and deopt if it's not zero. |
1435 Register remainder = scratch0(); | 1435 Register remainder = scratch0(); |
1436 __ Mls(remainder, result, divisor, dividend); | 1436 __ Mls(remainder, result, divisor, dividend); |
1437 __ cmp(remainder, Operand::Zero()); | 1437 __ cmp(remainder, Operand::Zero()); |
1438 DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecision); | 1438 DeoptimizeIf(ne, instr, "lost precision"); |
1439 } | 1439 } |
1440 } | 1440 } |
1441 | 1441 |
1442 | 1442 |
1443 void LCodeGen::DoMultiplyAddD(LMultiplyAddD* instr) { | 1443 void LCodeGen::DoMultiplyAddD(LMultiplyAddD* instr) { |
1444 DwVfpRegister addend = ToDoubleRegister(instr->addend()); | 1444 DwVfpRegister addend = ToDoubleRegister(instr->addend()); |
1445 DwVfpRegister multiplier = ToDoubleRegister(instr->multiplier()); | 1445 DwVfpRegister multiplier = ToDoubleRegister(instr->multiplier()); |
1446 DwVfpRegister multiplicand = ToDoubleRegister(instr->multiplicand()); | 1446 DwVfpRegister multiplicand = ToDoubleRegister(instr->multiplicand()); |
1447 | 1447 |
1448 // This is computed in-place. | 1448 // This is computed in-place. |
(...skipping 30 matching lines...) Expand all Loading... |
1479 // can simply do an arithmetic right shift. | 1479 // can simply do an arithmetic right shift. |
1480 int32_t shift = WhichPowerOf2Abs(divisor); | 1480 int32_t shift = WhichPowerOf2Abs(divisor); |
1481 if (divisor > 1) { | 1481 if (divisor > 1) { |
1482 __ mov(result, Operand(dividend, ASR, shift)); | 1482 __ mov(result, Operand(dividend, ASR, shift)); |
1483 return; | 1483 return; |
1484 } | 1484 } |
1485 | 1485 |
1486 // If the divisor is negative, we have to negate and handle edge cases. | 1486 // If the divisor is negative, we have to negate and handle edge cases. |
1487 __ rsb(result, dividend, Operand::Zero(), SetCC); | 1487 __ rsb(result, dividend, Operand::Zero(), SetCC); |
1488 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1488 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1489 DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero); | 1489 DeoptimizeIf(eq, instr, "minus zero"); |
1490 } | 1490 } |
1491 | 1491 |
1492 // Dividing by -1 is basically negation, unless we overflow. | 1492 // Dividing by -1 is basically negation, unless we overflow. |
1493 if (divisor == -1) { | 1493 if (divisor == -1) { |
1494 if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { | 1494 if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { |
1495 DeoptimizeIf(vs, instr, Deoptimizer::kOverflow); | 1495 DeoptimizeIf(vs, instr, "overflow"); |
1496 } | 1496 } |
1497 return; | 1497 return; |
1498 } | 1498 } |
1499 | 1499 |
1500 // If the negation could not overflow, simply shifting is OK. | 1500 // If the negation could not overflow, simply shifting is OK. |
1501 if (!instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { | 1501 if (!instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { |
1502 __ mov(result, Operand(result, ASR, shift)); | 1502 __ mov(result, Operand(result, ASR, shift)); |
1503 return; | 1503 return; |
1504 } | 1504 } |
1505 | 1505 |
1506 __ mov(result, Operand(kMinInt / divisor), LeaveCC, vs); | 1506 __ mov(result, Operand(kMinInt / divisor), LeaveCC, vs); |
1507 __ mov(result, Operand(result, ASR, shift), LeaveCC, vc); | 1507 __ mov(result, Operand(result, ASR, shift), LeaveCC, vc); |
1508 } | 1508 } |
1509 | 1509 |
1510 | 1510 |
1511 void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) { | 1511 void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) { |
1512 Register dividend = ToRegister(instr->dividend()); | 1512 Register dividend = ToRegister(instr->dividend()); |
1513 int32_t divisor = instr->divisor(); | 1513 int32_t divisor = instr->divisor(); |
1514 Register result = ToRegister(instr->result()); | 1514 Register result = ToRegister(instr->result()); |
1515 DCHECK(!dividend.is(result)); | 1515 DCHECK(!dividend.is(result)); |
1516 | 1516 |
1517 if (divisor == 0) { | 1517 if (divisor == 0) { |
1518 DeoptimizeIf(al, instr, Deoptimizer::kDivisionByZero); | 1518 DeoptimizeIf(al, instr, "division by zero"); |
1519 return; | 1519 return; |
1520 } | 1520 } |
1521 | 1521 |
1522 // Check for (0 / -x) that will produce negative zero. | 1522 // Check for (0 / -x) that will produce negative zero. |
1523 HMathFloorOfDiv* hdiv = instr->hydrogen(); | 1523 HMathFloorOfDiv* hdiv = instr->hydrogen(); |
1524 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { | 1524 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { |
1525 __ cmp(dividend, Operand::Zero()); | 1525 __ cmp(dividend, Operand::Zero()); |
1526 DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero); | 1526 DeoptimizeIf(eq, instr, "minus zero"); |
1527 } | 1527 } |
1528 | 1528 |
1529 // Easy case: We need no dynamic check for the dividend and the flooring | 1529 // Easy case: We need no dynamic check for the dividend and the flooring |
1530 // division is the same as the truncating division. | 1530 // division is the same as the truncating division. |
1531 if ((divisor > 0 && !hdiv->CheckFlag(HValue::kLeftCanBeNegative)) || | 1531 if ((divisor > 0 && !hdiv->CheckFlag(HValue::kLeftCanBeNegative)) || |
1532 (divisor < 0 && !hdiv->CheckFlag(HValue::kLeftCanBePositive))) { | 1532 (divisor < 0 && !hdiv->CheckFlag(HValue::kLeftCanBePositive))) { |
1533 __ TruncatingDiv(result, dividend, Abs(divisor)); | 1533 __ TruncatingDiv(result, dividend, Abs(divisor)); |
1534 if (divisor < 0) __ rsb(result, result, Operand::Zero()); | 1534 if (divisor < 0) __ rsb(result, result, Operand::Zero()); |
1535 return; | 1535 return; |
1536 } | 1536 } |
(...skipping 20 matching lines...) Expand all Loading... |
1557 // TODO(svenpanne) Refactor this to avoid code duplication with DoDivI. | 1557 // TODO(svenpanne) Refactor this to avoid code duplication with DoDivI. |
1558 void LCodeGen::DoFlooringDivI(LFlooringDivI* instr) { | 1558 void LCodeGen::DoFlooringDivI(LFlooringDivI* instr) { |
1559 HBinaryOperation* hdiv = instr->hydrogen(); | 1559 HBinaryOperation* hdiv = instr->hydrogen(); |
1560 Register left = ToRegister(instr->dividend()); | 1560 Register left = ToRegister(instr->dividend()); |
1561 Register right = ToRegister(instr->divisor()); | 1561 Register right = ToRegister(instr->divisor()); |
1562 Register result = ToRegister(instr->result()); | 1562 Register result = ToRegister(instr->result()); |
1563 | 1563 |
1564 // Check for x / 0. | 1564 // Check for x / 0. |
1565 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { | 1565 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { |
1566 __ cmp(right, Operand::Zero()); | 1566 __ cmp(right, Operand::Zero()); |
1567 DeoptimizeIf(eq, instr, Deoptimizer::kDivisionByZero); | 1567 DeoptimizeIf(eq, instr, "division by zero"); |
1568 } | 1568 } |
1569 | 1569 |
1570 // Check for (0 / -x) that will produce negative zero. | 1570 // Check for (0 / -x) that will produce negative zero. |
1571 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1571 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1572 Label positive; | 1572 Label positive; |
1573 if (!instr->hydrogen_value()->CheckFlag(HValue::kCanBeDivByZero)) { | 1573 if (!instr->hydrogen_value()->CheckFlag(HValue::kCanBeDivByZero)) { |
1574 // Do the test only if it hadn't be done above. | 1574 // Do the test only if it hadn't be done above. |
1575 __ cmp(right, Operand::Zero()); | 1575 __ cmp(right, Operand::Zero()); |
1576 } | 1576 } |
1577 __ b(pl, &positive); | 1577 __ b(pl, &positive); |
1578 __ cmp(left, Operand::Zero()); | 1578 __ cmp(left, Operand::Zero()); |
1579 DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero); | 1579 DeoptimizeIf(eq, instr, "minus zero"); |
1580 __ bind(&positive); | 1580 __ bind(&positive); |
1581 } | 1581 } |
1582 | 1582 |
1583 // Check for (kMinInt / -1). | 1583 // Check for (kMinInt / -1). |
1584 if (hdiv->CheckFlag(HValue::kCanOverflow) && | 1584 if (hdiv->CheckFlag(HValue::kCanOverflow) && |
1585 (!CpuFeatures::IsSupported(SUDIV) || | 1585 (!CpuFeatures::IsSupported(SUDIV) || |
1586 !hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32))) { | 1586 !hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32))) { |
1587 // We don't need to check for overflow when truncating with sdiv | 1587 // We don't need to check for overflow when truncating with sdiv |
1588 // support because, on ARM, sdiv kMinInt, -1 -> kMinInt. | 1588 // support because, on ARM, sdiv kMinInt, -1 -> kMinInt. |
1589 __ cmp(left, Operand(kMinInt)); | 1589 __ cmp(left, Operand(kMinInt)); |
1590 __ cmp(right, Operand(-1), eq); | 1590 __ cmp(right, Operand(-1), eq); |
1591 DeoptimizeIf(eq, instr, Deoptimizer::kOverflow); | 1591 DeoptimizeIf(eq, instr, "overflow"); |
1592 } | 1592 } |
1593 | 1593 |
1594 if (CpuFeatures::IsSupported(SUDIV)) { | 1594 if (CpuFeatures::IsSupported(SUDIV)) { |
1595 CpuFeatureScope scope(masm(), SUDIV); | 1595 CpuFeatureScope scope(masm(), SUDIV); |
1596 __ sdiv(result, left, right); | 1596 __ sdiv(result, left, right); |
1597 } else { | 1597 } else { |
1598 DoubleRegister vleft = ToDoubleRegister(instr->temp()); | 1598 DoubleRegister vleft = ToDoubleRegister(instr->temp()); |
1599 DoubleRegister vright = double_scratch0(); | 1599 DoubleRegister vright = double_scratch0(); |
1600 __ vmov(double_scratch0().low(), left); | 1600 __ vmov(double_scratch0().low(), left); |
1601 __ vcvt_f64_s32(vleft, double_scratch0().low()); | 1601 __ vcvt_f64_s32(vleft, double_scratch0().low()); |
(...skipping 25 matching lines...) Expand all Loading... |
1627 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero); | 1627 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero); |
1628 bool overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); | 1628 bool overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); |
1629 | 1629 |
1630 if (right_op->IsConstantOperand()) { | 1630 if (right_op->IsConstantOperand()) { |
1631 int32_t constant = ToInteger32(LConstantOperand::cast(right_op)); | 1631 int32_t constant = ToInteger32(LConstantOperand::cast(right_op)); |
1632 | 1632 |
1633 if (bailout_on_minus_zero && (constant < 0)) { | 1633 if (bailout_on_minus_zero && (constant < 0)) { |
1634 // The case of a null constant will be handled separately. | 1634 // The case of a null constant will be handled separately. |
1635 // If constant is negative and left is null, the result should be -0. | 1635 // If constant is negative and left is null, the result should be -0. |
1636 __ cmp(left, Operand::Zero()); | 1636 __ cmp(left, Operand::Zero()); |
1637 DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero); | 1637 DeoptimizeIf(eq, instr, "minus zero"); |
1638 } | 1638 } |
1639 | 1639 |
1640 switch (constant) { | 1640 switch (constant) { |
1641 case -1: | 1641 case -1: |
1642 if (overflow) { | 1642 if (overflow) { |
1643 __ rsb(result, left, Operand::Zero(), SetCC); | 1643 __ rsb(result, left, Operand::Zero(), SetCC); |
1644 DeoptimizeIf(vs, instr, Deoptimizer::kOverflow); | 1644 DeoptimizeIf(vs, instr, "overflow"); |
1645 } else { | 1645 } else { |
1646 __ rsb(result, left, Operand::Zero()); | 1646 __ rsb(result, left, Operand::Zero()); |
1647 } | 1647 } |
1648 break; | 1648 break; |
1649 case 0: | 1649 case 0: |
1650 if (bailout_on_minus_zero) { | 1650 if (bailout_on_minus_zero) { |
1651 // If left is strictly negative and the constant is null, the | 1651 // If left is strictly negative and the constant is null, the |
1652 // result is -0. Deoptimize if required, otherwise return 0. | 1652 // result is -0. Deoptimize if required, otherwise return 0. |
1653 __ cmp(left, Operand::Zero()); | 1653 __ cmp(left, Operand::Zero()); |
1654 DeoptimizeIf(mi, instr, Deoptimizer::kMinusZero); | 1654 DeoptimizeIf(mi, instr, "minus zero"); |
1655 } | 1655 } |
1656 __ mov(result, Operand::Zero()); | 1656 __ mov(result, Operand::Zero()); |
1657 break; | 1657 break; |
1658 case 1: | 1658 case 1: |
1659 __ Move(result, left); | 1659 __ Move(result, left); |
1660 break; | 1660 break; |
1661 default: | 1661 default: |
1662 // Multiplying by powers of two and powers of two plus or minus | 1662 // Multiplying by powers of two and powers of two plus or minus |
1663 // one can be done faster with shifted operands. | 1663 // one can be done faster with shifted operands. |
1664 // For other constants we emit standard code. | 1664 // For other constants we emit standard code. |
(...skipping 29 matching lines...) Expand all Loading... |
1694 if (overflow) { | 1694 if (overflow) { |
1695 Register scratch = scratch0(); | 1695 Register scratch = scratch0(); |
1696 // scratch:result = left * right. | 1696 // scratch:result = left * right. |
1697 if (instr->hydrogen()->representation().IsSmi()) { | 1697 if (instr->hydrogen()->representation().IsSmi()) { |
1698 __ SmiUntag(result, left); | 1698 __ SmiUntag(result, left); |
1699 __ smull(result, scratch, result, right); | 1699 __ smull(result, scratch, result, right); |
1700 } else { | 1700 } else { |
1701 __ smull(result, scratch, left, right); | 1701 __ smull(result, scratch, left, right); |
1702 } | 1702 } |
1703 __ cmp(scratch, Operand(result, ASR, 31)); | 1703 __ cmp(scratch, Operand(result, ASR, 31)); |
1704 DeoptimizeIf(ne, instr, Deoptimizer::kOverflow); | 1704 DeoptimizeIf(ne, instr, "overflow"); |
1705 } else { | 1705 } else { |
1706 if (instr->hydrogen()->representation().IsSmi()) { | 1706 if (instr->hydrogen()->representation().IsSmi()) { |
1707 __ SmiUntag(result, left); | 1707 __ SmiUntag(result, left); |
1708 __ mul(result, result, right); | 1708 __ mul(result, result, right); |
1709 } else { | 1709 } else { |
1710 __ mul(result, left, right); | 1710 __ mul(result, left, right); |
1711 } | 1711 } |
1712 } | 1712 } |
1713 | 1713 |
1714 if (bailout_on_minus_zero) { | 1714 if (bailout_on_minus_zero) { |
1715 Label done; | 1715 Label done; |
1716 __ teq(left, Operand(right)); | 1716 __ teq(left, Operand(right)); |
1717 __ b(pl, &done); | 1717 __ b(pl, &done); |
1718 // Bail out if the result is minus zero. | 1718 // Bail out if the result is minus zero. |
1719 __ cmp(result, Operand::Zero()); | 1719 __ cmp(result, Operand::Zero()); |
1720 DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero); | 1720 DeoptimizeIf(eq, instr, "minus zero"); |
1721 __ bind(&done); | 1721 __ bind(&done); |
1722 } | 1722 } |
1723 } | 1723 } |
1724 } | 1724 } |
1725 | 1725 |
1726 | 1726 |
1727 void LCodeGen::DoBitI(LBitI* instr) { | 1727 void LCodeGen::DoBitI(LBitI* instr) { |
1728 LOperand* left_op = instr->left(); | 1728 LOperand* left_op = instr->left(); |
1729 LOperand* right_op = instr->right(); | 1729 LOperand* right_op = instr->right(); |
1730 DCHECK(left_op->IsRegister()); | 1730 DCHECK(left_op->IsRegister()); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1773 switch (instr->op()) { | 1773 switch (instr->op()) { |
1774 case Token::ROR: | 1774 case Token::ROR: |
1775 __ mov(result, Operand(left, ROR, scratch)); | 1775 __ mov(result, Operand(left, ROR, scratch)); |
1776 break; | 1776 break; |
1777 case Token::SAR: | 1777 case Token::SAR: |
1778 __ mov(result, Operand(left, ASR, scratch)); | 1778 __ mov(result, Operand(left, ASR, scratch)); |
1779 break; | 1779 break; |
1780 case Token::SHR: | 1780 case Token::SHR: |
1781 if (instr->can_deopt()) { | 1781 if (instr->can_deopt()) { |
1782 __ mov(result, Operand(left, LSR, scratch), SetCC); | 1782 __ mov(result, Operand(left, LSR, scratch), SetCC); |
1783 DeoptimizeIf(mi, instr, Deoptimizer::kNegativeValue); | 1783 DeoptimizeIf(mi, instr, "negative value"); |
1784 } else { | 1784 } else { |
1785 __ mov(result, Operand(left, LSR, scratch)); | 1785 __ mov(result, Operand(left, LSR, scratch)); |
1786 } | 1786 } |
1787 break; | 1787 break; |
1788 case Token::SHL: | 1788 case Token::SHL: |
1789 __ mov(result, Operand(left, LSL, scratch)); | 1789 __ mov(result, Operand(left, LSL, scratch)); |
1790 break; | 1790 break; |
1791 default: | 1791 default: |
1792 UNREACHABLE(); | 1792 UNREACHABLE(); |
1793 break; | 1793 break; |
(...skipping 16 matching lines...) Expand all Loading... |
1810 } else { | 1810 } else { |
1811 __ Move(result, left); | 1811 __ Move(result, left); |
1812 } | 1812 } |
1813 break; | 1813 break; |
1814 case Token::SHR: | 1814 case Token::SHR: |
1815 if (shift_count != 0) { | 1815 if (shift_count != 0) { |
1816 __ mov(result, Operand(left, LSR, shift_count)); | 1816 __ mov(result, Operand(left, LSR, shift_count)); |
1817 } else { | 1817 } else { |
1818 if (instr->can_deopt()) { | 1818 if (instr->can_deopt()) { |
1819 __ tst(left, Operand(0x80000000)); | 1819 __ tst(left, Operand(0x80000000)); |
1820 DeoptimizeIf(ne, instr, Deoptimizer::kNegativeValue); | 1820 DeoptimizeIf(ne, instr, "negative value"); |
1821 } | 1821 } |
1822 __ Move(result, left); | 1822 __ Move(result, left); |
1823 } | 1823 } |
1824 break; | 1824 break; |
1825 case Token::SHL: | 1825 case Token::SHL: |
1826 if (shift_count != 0) { | 1826 if (shift_count != 0) { |
1827 if (instr->hydrogen_value()->representation().IsSmi() && | 1827 if (instr->hydrogen_value()->representation().IsSmi() && |
1828 instr->can_deopt()) { | 1828 instr->can_deopt()) { |
1829 if (shift_count != 1) { | 1829 if (shift_count != 1) { |
1830 __ mov(result, Operand(left, LSL, shift_count - 1)); | 1830 __ mov(result, Operand(left, LSL, shift_count - 1)); |
1831 __ SmiTag(result, result, SetCC); | 1831 __ SmiTag(result, result, SetCC); |
1832 } else { | 1832 } else { |
1833 __ SmiTag(result, left, SetCC); | 1833 __ SmiTag(result, left, SetCC); |
1834 } | 1834 } |
1835 DeoptimizeIf(vs, instr, Deoptimizer::kOverflow); | 1835 DeoptimizeIf(vs, instr, "overflow"); |
1836 } else { | 1836 } else { |
1837 __ mov(result, Operand(left, LSL, shift_count)); | 1837 __ mov(result, Operand(left, LSL, shift_count)); |
1838 } | 1838 } |
1839 } else { | 1839 } else { |
1840 __ Move(result, left); | 1840 __ Move(result, left); |
1841 } | 1841 } |
1842 break; | 1842 break; |
1843 default: | 1843 default: |
1844 UNREACHABLE(); | 1844 UNREACHABLE(); |
1845 break; | 1845 break; |
(...skipping 11 matching lines...) Expand all Loading... |
1857 | 1857 |
1858 if (right->IsStackSlot()) { | 1858 if (right->IsStackSlot()) { |
1859 Register right_reg = EmitLoadRegister(right, ip); | 1859 Register right_reg = EmitLoadRegister(right, ip); |
1860 __ sub(ToRegister(result), ToRegister(left), Operand(right_reg), set_cond); | 1860 __ sub(ToRegister(result), ToRegister(left), Operand(right_reg), set_cond); |
1861 } else { | 1861 } else { |
1862 DCHECK(right->IsRegister() || right->IsConstantOperand()); | 1862 DCHECK(right->IsRegister() || right->IsConstantOperand()); |
1863 __ sub(ToRegister(result), ToRegister(left), ToOperand(right), set_cond); | 1863 __ sub(ToRegister(result), ToRegister(left), ToOperand(right), set_cond); |
1864 } | 1864 } |
1865 | 1865 |
1866 if (can_overflow) { | 1866 if (can_overflow) { |
1867 DeoptimizeIf(vs, instr, Deoptimizer::kOverflow); | 1867 DeoptimizeIf(vs, instr, "overflow"); |
1868 } | 1868 } |
1869 } | 1869 } |
1870 | 1870 |
1871 | 1871 |
1872 void LCodeGen::DoRSubI(LRSubI* instr) { | 1872 void LCodeGen::DoRSubI(LRSubI* instr) { |
1873 LOperand* left = instr->left(); | 1873 LOperand* left = instr->left(); |
1874 LOperand* right = instr->right(); | 1874 LOperand* right = instr->right(); |
1875 LOperand* result = instr->result(); | 1875 LOperand* result = instr->result(); |
1876 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); | 1876 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); |
1877 SBit set_cond = can_overflow ? SetCC : LeaveCC; | 1877 SBit set_cond = can_overflow ? SetCC : LeaveCC; |
1878 | 1878 |
1879 if (right->IsStackSlot()) { | 1879 if (right->IsStackSlot()) { |
1880 Register right_reg = EmitLoadRegister(right, ip); | 1880 Register right_reg = EmitLoadRegister(right, ip); |
1881 __ rsb(ToRegister(result), ToRegister(left), Operand(right_reg), set_cond); | 1881 __ rsb(ToRegister(result), ToRegister(left), Operand(right_reg), set_cond); |
1882 } else { | 1882 } else { |
1883 DCHECK(right->IsRegister() || right->IsConstantOperand()); | 1883 DCHECK(right->IsRegister() || right->IsConstantOperand()); |
1884 __ rsb(ToRegister(result), ToRegister(left), ToOperand(right), set_cond); | 1884 __ rsb(ToRegister(result), ToRegister(left), ToOperand(right), set_cond); |
1885 } | 1885 } |
1886 | 1886 |
1887 if (can_overflow) { | 1887 if (can_overflow) { |
1888 DeoptimizeIf(vs, instr, Deoptimizer::kOverflow); | 1888 DeoptimizeIf(vs, instr, "overflow"); |
1889 } | 1889 } |
1890 } | 1890 } |
1891 | 1891 |
1892 | 1892 |
1893 void LCodeGen::DoConstantI(LConstantI* instr) { | 1893 void LCodeGen::DoConstantI(LConstantI* instr) { |
1894 __ mov(ToRegister(instr->result()), Operand(instr->value())); | 1894 __ mov(ToRegister(instr->result()), Operand(instr->value())); |
1895 } | 1895 } |
1896 | 1896 |
1897 | 1897 |
1898 void LCodeGen::DoConstantS(LConstantS* instr) { | 1898 void LCodeGen::DoConstantS(LConstantS* instr) { |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1946 Register result = ToRegister(instr->result()); | 1946 Register result = ToRegister(instr->result()); |
1947 Register scratch = ToRegister(instr->temp()); | 1947 Register scratch = ToRegister(instr->temp()); |
1948 Smi* index = instr->index(); | 1948 Smi* index = instr->index(); |
1949 Label runtime, done; | 1949 Label runtime, done; |
1950 DCHECK(object.is(result)); | 1950 DCHECK(object.is(result)); |
1951 DCHECK(object.is(r0)); | 1951 DCHECK(object.is(r0)); |
1952 DCHECK(!scratch.is(scratch0())); | 1952 DCHECK(!scratch.is(scratch0())); |
1953 DCHECK(!scratch.is(object)); | 1953 DCHECK(!scratch.is(object)); |
1954 | 1954 |
1955 __ SmiTst(object); | 1955 __ SmiTst(object); |
1956 DeoptimizeIf(eq, instr, Deoptimizer::kSmi); | 1956 DeoptimizeIf(eq, instr, "Smi"); |
1957 __ CompareObjectType(object, scratch, scratch, JS_DATE_TYPE); | 1957 __ CompareObjectType(object, scratch, scratch, JS_DATE_TYPE); |
1958 DeoptimizeIf(ne, instr, Deoptimizer::kNotADateObject); | 1958 DeoptimizeIf(ne, instr, "not a date object"); |
1959 | 1959 |
1960 if (index->value() == 0) { | 1960 if (index->value() == 0) { |
1961 __ ldr(result, FieldMemOperand(object, JSDate::kValueOffset)); | 1961 __ ldr(result, FieldMemOperand(object, JSDate::kValueOffset)); |
1962 } else { | 1962 } else { |
1963 if (index->value() < JSDate::kFirstUncachedField) { | 1963 if (index->value() < JSDate::kFirstUncachedField) { |
1964 ExternalReference stamp = ExternalReference::date_cache_stamp(isolate()); | 1964 ExternalReference stamp = ExternalReference::date_cache_stamp(isolate()); |
1965 __ mov(scratch, Operand(stamp)); | 1965 __ mov(scratch, Operand(stamp)); |
1966 __ ldr(scratch, MemOperand(scratch)); | 1966 __ ldr(scratch, MemOperand(scratch)); |
1967 __ ldr(scratch0(), FieldMemOperand(object, JSDate::kCacheStampOffset)); | 1967 __ ldr(scratch0(), FieldMemOperand(object, JSDate::kCacheStampOffset)); |
1968 __ cmp(scratch, scratch0()); | 1968 __ cmp(scratch, scratch0()); |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2065 | 2065 |
2066 if (right->IsStackSlot()) { | 2066 if (right->IsStackSlot()) { |
2067 Register right_reg = EmitLoadRegister(right, ip); | 2067 Register right_reg = EmitLoadRegister(right, ip); |
2068 __ add(ToRegister(result), ToRegister(left), Operand(right_reg), set_cond); | 2068 __ add(ToRegister(result), ToRegister(left), Operand(right_reg), set_cond); |
2069 } else { | 2069 } else { |
2070 DCHECK(right->IsRegister() || right->IsConstantOperand()); | 2070 DCHECK(right->IsRegister() || right->IsConstantOperand()); |
2071 __ add(ToRegister(result), ToRegister(left), ToOperand(right), set_cond); | 2071 __ add(ToRegister(result), ToRegister(left), ToOperand(right), set_cond); |
2072 } | 2072 } |
2073 | 2073 |
2074 if (can_overflow) { | 2074 if (can_overflow) { |
2075 DeoptimizeIf(vs, instr, Deoptimizer::kOverflow); | 2075 DeoptimizeIf(vs, instr, "overflow"); |
2076 } | 2076 } |
2077 } | 2077 } |
2078 | 2078 |
2079 | 2079 |
2080 void LCodeGen::DoMathMinMax(LMathMinMax* instr) { | 2080 void LCodeGen::DoMathMinMax(LMathMinMax* instr) { |
2081 LOperand* left = instr->left(); | 2081 LOperand* left = instr->left(); |
2082 LOperand* right = instr->right(); | 2082 LOperand* right = instr->right(); |
2083 HMathMinMax::Operation operation = instr->hydrogen()->operation(); | 2083 HMathMinMax::Operation operation = instr->hydrogen()->operation(); |
2084 if (instr->hydrogen()->representation().IsSmiOrInteger32()) { | 2084 if (instr->hydrogen()->representation().IsSmiOrInteger32()) { |
2085 Condition condition = (operation == HMathMinMax::kMathMin) ? le : ge; | 2085 Condition condition = (operation == HMathMinMax::kMathMin) ? le : ge; |
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2291 } | 2291 } |
2292 | 2292 |
2293 if (expected.Contains(ToBooleanStub::SMI)) { | 2293 if (expected.Contains(ToBooleanStub::SMI)) { |
2294 // Smis: 0 -> false, all other -> true. | 2294 // Smis: 0 -> false, all other -> true. |
2295 __ cmp(reg, Operand::Zero()); | 2295 __ cmp(reg, Operand::Zero()); |
2296 __ b(eq, instr->FalseLabel(chunk_)); | 2296 __ b(eq, instr->FalseLabel(chunk_)); |
2297 __ JumpIfSmi(reg, instr->TrueLabel(chunk_)); | 2297 __ JumpIfSmi(reg, instr->TrueLabel(chunk_)); |
2298 } else if (expected.NeedsMap()) { | 2298 } else if (expected.NeedsMap()) { |
2299 // If we need a map later and have a Smi -> deopt. | 2299 // If we need a map later and have a Smi -> deopt. |
2300 __ SmiTst(reg); | 2300 __ SmiTst(reg); |
2301 DeoptimizeIf(eq, instr, Deoptimizer::kSmi); | 2301 DeoptimizeIf(eq, instr, "Smi"); |
2302 } | 2302 } |
2303 | 2303 |
2304 const Register map = scratch0(); | 2304 const Register map = scratch0(); |
2305 if (expected.NeedsMap()) { | 2305 if (expected.NeedsMap()) { |
2306 __ ldr(map, FieldMemOperand(reg, HeapObject::kMapOffset)); | 2306 __ ldr(map, FieldMemOperand(reg, HeapObject::kMapOffset)); |
2307 | 2307 |
2308 if (expected.CanBeUndetectable()) { | 2308 if (expected.CanBeUndetectable()) { |
2309 // Undetectable -> false. | 2309 // Undetectable -> false. |
2310 __ ldrb(ip, FieldMemOperand(map, Map::kBitFieldOffset)); | 2310 __ ldrb(ip, FieldMemOperand(map, Map::kBitFieldOffset)); |
2311 __ tst(ip, Operand(1 << Map::kIsUndetectable)); | 2311 __ tst(ip, Operand(1 << Map::kIsUndetectable)); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2347 __ VFPCompareAndSetFlags(dbl_scratch, 0.0); | 2347 __ VFPCompareAndSetFlags(dbl_scratch, 0.0); |
2348 __ cmp(r0, r0, vs); // NaN -> false. | 2348 __ cmp(r0, r0, vs); // NaN -> false. |
2349 __ b(eq, instr->FalseLabel(chunk_)); // +0, -0 -> false. | 2349 __ b(eq, instr->FalseLabel(chunk_)); // +0, -0 -> false. |
2350 __ b(instr->TrueLabel(chunk_)); | 2350 __ b(instr->TrueLabel(chunk_)); |
2351 __ bind(¬_heap_number); | 2351 __ bind(¬_heap_number); |
2352 } | 2352 } |
2353 | 2353 |
2354 if (!expected.IsGeneric()) { | 2354 if (!expected.IsGeneric()) { |
2355 // We've seen something for the first time -> deopt. | 2355 // We've seen something for the first time -> deopt. |
2356 // This can only happen if we are not generic already. | 2356 // This can only happen if we are not generic already. |
2357 DeoptimizeIf(al, instr, Deoptimizer::kUnexpectedObject); | 2357 DeoptimizeIf(al, instr, "unexpected object"); |
2358 } | 2358 } |
2359 } | 2359 } |
2360 } | 2360 } |
2361 } | 2361 } |
2362 | 2362 |
2363 | 2363 |
2364 void LCodeGen::EmitGoto(int block) { | 2364 void LCodeGen::EmitGoto(int block) { |
2365 if (!IsNextEmittedBlock(block)) { | 2365 if (!IsNextEmittedBlock(block)) { |
2366 __ jmp(chunk_->GetAssemblyLabel(LookupDestination(block))); | 2366 __ jmp(chunk_->GetAssemblyLabel(LookupDestination(block))); |
2367 } | 2367 } |
(...skipping 625 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2993 } | 2993 } |
2994 | 2994 |
2995 | 2995 |
2996 void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) { | 2996 void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) { |
2997 Register result = ToRegister(instr->result()); | 2997 Register result = ToRegister(instr->result()); |
2998 __ mov(ip, Operand(Handle<Object>(instr->hydrogen()->cell().handle()))); | 2998 __ mov(ip, Operand(Handle<Object>(instr->hydrogen()->cell().handle()))); |
2999 __ ldr(result, FieldMemOperand(ip, Cell::kValueOffset)); | 2999 __ ldr(result, FieldMemOperand(ip, Cell::kValueOffset)); |
3000 if (instr->hydrogen()->RequiresHoleCheck()) { | 3000 if (instr->hydrogen()->RequiresHoleCheck()) { |
3001 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | 3001 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
3002 __ cmp(result, ip); | 3002 __ cmp(result, ip); |
3003 DeoptimizeIf(eq, instr, Deoptimizer::kHole); | 3003 DeoptimizeIf(eq, instr, "hole"); |
3004 } | 3004 } |
3005 } | 3005 } |
3006 | 3006 |
3007 | 3007 |
3008 template <class T> | 3008 template <class T> |
3009 void LCodeGen::EmitVectorLoadICRegisters(T* instr) { | 3009 void LCodeGen::EmitVectorLoadICRegisters(T* instr) { |
3010 DCHECK(FLAG_vector_ics); | 3010 DCHECK(FLAG_vector_ics); |
3011 Register vector_register = ToRegister(instr->temp_vector()); | 3011 Register vector_register = ToRegister(instr->temp_vector()); |
3012 Register slot_register = VectorLoadICDescriptor::SlotRegister(); | 3012 Register slot_register = VectorLoadICDescriptor::SlotRegister(); |
3013 DCHECK(vector_register.is(VectorLoadICDescriptor::VectorRegister())); | 3013 DCHECK(vector_register.is(VectorLoadICDescriptor::VectorRegister())); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3048 | 3048 |
3049 // If the cell we are storing to contains the hole it could have | 3049 // If the cell we are storing to contains the hole it could have |
3050 // been deleted from the property dictionary. In that case, we need | 3050 // been deleted from the property dictionary. In that case, we need |
3051 // to update the property details in the property dictionary to mark | 3051 // to update the property details in the property dictionary to mark |
3052 // it as no longer deleted. | 3052 // it as no longer deleted. |
3053 if (instr->hydrogen()->RequiresHoleCheck()) { | 3053 if (instr->hydrogen()->RequiresHoleCheck()) { |
3054 // We use a temp to check the payload (CompareRoot might clobber ip). | 3054 // We use a temp to check the payload (CompareRoot might clobber ip). |
3055 Register payload = ToRegister(instr->temp()); | 3055 Register payload = ToRegister(instr->temp()); |
3056 __ ldr(payload, FieldMemOperand(cell, Cell::kValueOffset)); | 3056 __ ldr(payload, FieldMemOperand(cell, Cell::kValueOffset)); |
3057 __ CompareRoot(payload, Heap::kTheHoleValueRootIndex); | 3057 __ CompareRoot(payload, Heap::kTheHoleValueRootIndex); |
3058 DeoptimizeIf(eq, instr, Deoptimizer::kHole); | 3058 DeoptimizeIf(eq, instr, "hole"); |
3059 } | 3059 } |
3060 | 3060 |
3061 // Store the value. | 3061 // Store the value. |
3062 __ str(value, FieldMemOperand(cell, Cell::kValueOffset)); | 3062 __ str(value, FieldMemOperand(cell, Cell::kValueOffset)); |
3063 // Cells are always rescanned, so no write barrier here. | 3063 // Cells are always rescanned, so no write barrier here. |
3064 } | 3064 } |
3065 | 3065 |
3066 | 3066 |
3067 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { | 3067 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { |
3068 Register context = ToRegister(instr->context()); | 3068 Register context = ToRegister(instr->context()); |
3069 Register result = ToRegister(instr->result()); | 3069 Register result = ToRegister(instr->result()); |
3070 __ ldr(result, ContextOperand(context, instr->slot_index())); | 3070 __ ldr(result, ContextOperand(context, instr->slot_index())); |
3071 if (instr->hydrogen()->RequiresHoleCheck()) { | 3071 if (instr->hydrogen()->RequiresHoleCheck()) { |
3072 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | 3072 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
3073 __ cmp(result, ip); | 3073 __ cmp(result, ip); |
3074 if (instr->hydrogen()->DeoptimizesOnHole()) { | 3074 if (instr->hydrogen()->DeoptimizesOnHole()) { |
3075 DeoptimizeIf(eq, instr, Deoptimizer::kHole); | 3075 DeoptimizeIf(eq, instr, "hole"); |
3076 } else { | 3076 } else { |
3077 __ mov(result, Operand(factory()->undefined_value()), LeaveCC, eq); | 3077 __ mov(result, Operand(factory()->undefined_value()), LeaveCC, eq); |
3078 } | 3078 } |
3079 } | 3079 } |
3080 } | 3080 } |
3081 | 3081 |
3082 | 3082 |
3083 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { | 3083 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { |
3084 Register context = ToRegister(instr->context()); | 3084 Register context = ToRegister(instr->context()); |
3085 Register value = ToRegister(instr->value()); | 3085 Register value = ToRegister(instr->value()); |
3086 Register scratch = scratch0(); | 3086 Register scratch = scratch0(); |
3087 MemOperand target = ContextOperand(context, instr->slot_index()); | 3087 MemOperand target = ContextOperand(context, instr->slot_index()); |
3088 | 3088 |
3089 Label skip_assignment; | 3089 Label skip_assignment; |
3090 | 3090 |
3091 if (instr->hydrogen()->RequiresHoleCheck()) { | 3091 if (instr->hydrogen()->RequiresHoleCheck()) { |
3092 __ ldr(scratch, target); | 3092 __ ldr(scratch, target); |
3093 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | 3093 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
3094 __ cmp(scratch, ip); | 3094 __ cmp(scratch, ip); |
3095 if (instr->hydrogen()->DeoptimizesOnHole()) { | 3095 if (instr->hydrogen()->DeoptimizesOnHole()) { |
3096 DeoptimizeIf(eq, instr, Deoptimizer::kHole); | 3096 DeoptimizeIf(eq, instr, "hole"); |
3097 } else { | 3097 } else { |
3098 __ b(ne, &skip_assignment); | 3098 __ b(ne, &skip_assignment); |
3099 } | 3099 } |
3100 } | 3100 } |
3101 | 3101 |
3102 __ str(value, target); | 3102 __ str(value, target); |
3103 if (instr->hydrogen()->NeedsWriteBarrier()) { | 3103 if (instr->hydrogen()->NeedsWriteBarrier()) { |
3104 SmiCheck check_needed = | 3104 SmiCheck check_needed = |
3105 instr->hydrogen()->value()->type().IsHeapObject() | 3105 instr->hydrogen()->value()->type().IsHeapObject() |
3106 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; | 3106 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3167 Register function = ToRegister(instr->function()); | 3167 Register function = ToRegister(instr->function()); |
3168 Register result = ToRegister(instr->result()); | 3168 Register result = ToRegister(instr->result()); |
3169 | 3169 |
3170 // Get the prototype or initial map from the function. | 3170 // Get the prototype or initial map from the function. |
3171 __ ldr(result, | 3171 __ ldr(result, |
3172 FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); | 3172 FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); |
3173 | 3173 |
3174 // Check that the function has a prototype or an initial map. | 3174 // Check that the function has a prototype or an initial map. |
3175 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | 3175 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
3176 __ cmp(result, ip); | 3176 __ cmp(result, ip); |
3177 DeoptimizeIf(eq, instr, Deoptimizer::kHole); | 3177 DeoptimizeIf(eq, instr, "hole"); |
3178 | 3178 |
3179 // If the function does not have an initial map, we're done. | 3179 // If the function does not have an initial map, we're done. |
3180 Label done; | 3180 Label done; |
3181 __ CompareObjectType(result, scratch, scratch, MAP_TYPE); | 3181 __ CompareObjectType(result, scratch, scratch, MAP_TYPE); |
3182 __ b(ne, &done); | 3182 __ b(ne, &done); |
3183 | 3183 |
3184 // Get the prototype from the initial map. | 3184 // Get the prototype from the initial map. |
3185 __ ldr(result, FieldMemOperand(result, Map::kPrototypeOffset)); | 3185 __ ldr(result, FieldMemOperand(result, Map::kPrototypeOffset)); |
3186 | 3186 |
3187 // All done. | 3187 // All done. |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3293 break; | 3293 break; |
3294 case EXTERNAL_INT32_ELEMENTS: | 3294 case EXTERNAL_INT32_ELEMENTS: |
3295 case INT32_ELEMENTS: | 3295 case INT32_ELEMENTS: |
3296 __ ldr(result, mem_operand); | 3296 __ ldr(result, mem_operand); |
3297 break; | 3297 break; |
3298 case EXTERNAL_UINT32_ELEMENTS: | 3298 case EXTERNAL_UINT32_ELEMENTS: |
3299 case UINT32_ELEMENTS: | 3299 case UINT32_ELEMENTS: |
3300 __ ldr(result, mem_operand); | 3300 __ ldr(result, mem_operand); |
3301 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) { | 3301 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) { |
3302 __ cmp(result, Operand(0x80000000)); | 3302 __ cmp(result, Operand(0x80000000)); |
3303 DeoptimizeIf(cs, instr, Deoptimizer::kNegativeValue); | 3303 DeoptimizeIf(cs, instr, "negative value"); |
3304 } | 3304 } |
3305 break; | 3305 break; |
3306 case FLOAT32_ELEMENTS: | 3306 case FLOAT32_ELEMENTS: |
3307 case FLOAT64_ELEMENTS: | 3307 case FLOAT64_ELEMENTS: |
3308 case EXTERNAL_FLOAT32_ELEMENTS: | 3308 case EXTERNAL_FLOAT32_ELEMENTS: |
3309 case EXTERNAL_FLOAT64_ELEMENTS: | 3309 case EXTERNAL_FLOAT64_ELEMENTS: |
3310 case FAST_HOLEY_DOUBLE_ELEMENTS: | 3310 case FAST_HOLEY_DOUBLE_ELEMENTS: |
3311 case FAST_HOLEY_ELEMENTS: | 3311 case FAST_HOLEY_ELEMENTS: |
3312 case FAST_HOLEY_SMI_ELEMENTS: | 3312 case FAST_HOLEY_SMI_ELEMENTS: |
3313 case FAST_DOUBLE_ELEMENTS: | 3313 case FAST_DOUBLE_ELEMENTS: |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3346 int shift_size = (instr->hydrogen()->key()->representation().IsSmi()) | 3346 int shift_size = (instr->hydrogen()->key()->representation().IsSmi()) |
3347 ? (element_size_shift - kSmiTagSize) : element_size_shift; | 3347 ? (element_size_shift - kSmiTagSize) : element_size_shift; |
3348 __ add(scratch, scratch, Operand(key, LSL, shift_size)); | 3348 __ add(scratch, scratch, Operand(key, LSL, shift_size)); |
3349 } | 3349 } |
3350 | 3350 |
3351 __ vldr(result, scratch, 0); | 3351 __ vldr(result, scratch, 0); |
3352 | 3352 |
3353 if (instr->hydrogen()->RequiresHoleCheck()) { | 3353 if (instr->hydrogen()->RequiresHoleCheck()) { |
3354 __ ldr(scratch, MemOperand(scratch, sizeof(kHoleNanLower32))); | 3354 __ ldr(scratch, MemOperand(scratch, sizeof(kHoleNanLower32))); |
3355 __ cmp(scratch, Operand(kHoleNanUpper32)); | 3355 __ cmp(scratch, Operand(kHoleNanUpper32)); |
3356 DeoptimizeIf(eq, instr, Deoptimizer::kHole); | 3356 DeoptimizeIf(eq, instr, "hole"); |
3357 } | 3357 } |
3358 } | 3358 } |
3359 | 3359 |
3360 | 3360 |
3361 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { | 3361 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { |
3362 Register elements = ToRegister(instr->elements()); | 3362 Register elements = ToRegister(instr->elements()); |
3363 Register result = ToRegister(instr->result()); | 3363 Register result = ToRegister(instr->result()); |
3364 Register scratch = scratch0(); | 3364 Register scratch = scratch0(); |
3365 Register store_base = scratch; | 3365 Register store_base = scratch; |
3366 int offset = instr->base_offset(); | 3366 int offset = instr->base_offset(); |
(...skipping 13 matching lines...) Expand all Loading... |
3380 } else { | 3380 } else { |
3381 __ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2)); | 3381 __ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2)); |
3382 } | 3382 } |
3383 } | 3383 } |
3384 __ ldr(result, MemOperand(store_base, offset)); | 3384 __ ldr(result, MemOperand(store_base, offset)); |
3385 | 3385 |
3386 // Check for the hole value. | 3386 // Check for the hole value. |
3387 if (instr->hydrogen()->RequiresHoleCheck()) { | 3387 if (instr->hydrogen()->RequiresHoleCheck()) { |
3388 if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) { | 3388 if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) { |
3389 __ SmiTst(result); | 3389 __ SmiTst(result); |
3390 DeoptimizeIf(ne, instr, Deoptimizer::kNotASmi); | 3390 DeoptimizeIf(ne, instr, "not a Smi"); |
3391 } else { | 3391 } else { |
3392 __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex); | 3392 __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex); |
3393 __ cmp(result, scratch); | 3393 __ cmp(result, scratch); |
3394 DeoptimizeIf(eq, instr, Deoptimizer::kHole); | 3394 DeoptimizeIf(eq, instr, "hole"); |
3395 } | 3395 } |
3396 } | 3396 } |
3397 } | 3397 } |
3398 | 3398 |
3399 | 3399 |
3400 void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) { | 3400 void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) { |
3401 if (instr->is_typed_elements()) { | 3401 if (instr->is_typed_elements()) { |
3402 DoLoadKeyedExternalArray(instr); | 3402 DoLoadKeyedExternalArray(instr); |
3403 } else if (instr->hydrogen()->representation().IsDouble()) { | 3403 } else if (instr->hydrogen()->representation().IsDouble()) { |
3404 DoLoadKeyedFixedDoubleArray(instr); | 3404 DoLoadKeyedFixedDoubleArray(instr); |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3526 // Normal function. Replace undefined or null with global receiver. | 3526 // Normal function. Replace undefined or null with global receiver. |
3527 __ LoadRoot(scratch, Heap::kNullValueRootIndex); | 3527 __ LoadRoot(scratch, Heap::kNullValueRootIndex); |
3528 __ cmp(receiver, scratch); | 3528 __ cmp(receiver, scratch); |
3529 __ b(eq, &global_object); | 3529 __ b(eq, &global_object); |
3530 __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex); | 3530 __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex); |
3531 __ cmp(receiver, scratch); | 3531 __ cmp(receiver, scratch); |
3532 __ b(eq, &global_object); | 3532 __ b(eq, &global_object); |
3533 | 3533 |
3534 // Deoptimize if the receiver is not a JS object. | 3534 // Deoptimize if the receiver is not a JS object. |
3535 __ SmiTst(receiver); | 3535 __ SmiTst(receiver); |
3536 DeoptimizeIf(eq, instr, Deoptimizer::kSmi); | 3536 DeoptimizeIf(eq, instr, "Smi"); |
3537 __ CompareObjectType(receiver, scratch, scratch, FIRST_SPEC_OBJECT_TYPE); | 3537 __ CompareObjectType(receiver, scratch, scratch, FIRST_SPEC_OBJECT_TYPE); |
3538 DeoptimizeIf(lt, instr, Deoptimizer::kNotAJavaScriptObject); | 3538 DeoptimizeIf(lt, instr, "not a JavaScript object"); |
3539 | 3539 |
3540 __ b(&result_in_receiver); | 3540 __ b(&result_in_receiver); |
3541 __ bind(&global_object); | 3541 __ bind(&global_object); |
3542 __ ldr(result, FieldMemOperand(function, JSFunction::kContextOffset)); | 3542 __ ldr(result, FieldMemOperand(function, JSFunction::kContextOffset)); |
3543 __ ldr(result, | 3543 __ ldr(result, |
3544 ContextOperand(result, Context::GLOBAL_OBJECT_INDEX)); | 3544 ContextOperand(result, Context::GLOBAL_OBJECT_INDEX)); |
3545 __ ldr(result, FieldMemOperand(result, GlobalObject::kGlobalProxyOffset)); | 3545 __ ldr(result, FieldMemOperand(result, GlobalObject::kGlobalProxyOffset)); |
3546 | 3546 |
3547 if (result.is(receiver)) { | 3547 if (result.is(receiver)) { |
3548 __ bind(&result_in_receiver); | 3548 __ bind(&result_in_receiver); |
(...skipping 14 matching lines...) Expand all Loading... |
3563 Register elements = ToRegister(instr->elements()); | 3563 Register elements = ToRegister(instr->elements()); |
3564 Register scratch = scratch0(); | 3564 Register scratch = scratch0(); |
3565 DCHECK(receiver.is(r0)); // Used for parameter count. | 3565 DCHECK(receiver.is(r0)); // Used for parameter count. |
3566 DCHECK(function.is(r1)); // Required by InvokeFunction. | 3566 DCHECK(function.is(r1)); // Required by InvokeFunction. |
3567 DCHECK(ToRegister(instr->result()).is(r0)); | 3567 DCHECK(ToRegister(instr->result()).is(r0)); |
3568 | 3568 |
3569 // Copy the arguments to this function possibly from the | 3569 // Copy the arguments to this function possibly from the |
3570 // adaptor frame below it. | 3570 // adaptor frame below it. |
3571 const uint32_t kArgumentsLimit = 1 * KB; | 3571 const uint32_t kArgumentsLimit = 1 * KB; |
3572 __ cmp(length, Operand(kArgumentsLimit)); | 3572 __ cmp(length, Operand(kArgumentsLimit)); |
3573 DeoptimizeIf(hi, instr, Deoptimizer::kTooManyArguments); | 3573 DeoptimizeIf(hi, instr, "too many arguments"); |
3574 | 3574 |
3575 // Push the receiver and use the register to keep the original | 3575 // Push the receiver and use the register to keep the original |
3576 // number of arguments. | 3576 // number of arguments. |
3577 __ push(receiver); | 3577 __ push(receiver); |
3578 __ mov(receiver, length); | 3578 __ mov(receiver, length); |
3579 // The arguments are at a one pointer size offset from elements. | 3579 // The arguments are at a one pointer size offset from elements. |
3580 __ add(elements, elements, Operand(1 * kPointerSize)); | 3580 __ add(elements, elements, Operand(1 * kPointerSize)); |
3581 | 3581 |
3582 // Loop through the arguments pushing them onto the execution | 3582 // Loop through the arguments pushing them onto the execution |
3583 // stack. | 3583 // stack. |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3689 DCHECK(instr->context() != NULL); | 3689 DCHECK(instr->context() != NULL); |
3690 DCHECK(ToRegister(instr->context()).is(cp)); | 3690 DCHECK(ToRegister(instr->context()).is(cp)); |
3691 Register input = ToRegister(instr->value()); | 3691 Register input = ToRegister(instr->value()); |
3692 Register result = ToRegister(instr->result()); | 3692 Register result = ToRegister(instr->result()); |
3693 Register scratch = scratch0(); | 3693 Register scratch = scratch0(); |
3694 | 3694 |
3695 // Deoptimize if not a heap number. | 3695 // Deoptimize if not a heap number. |
3696 __ ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); | 3696 __ ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); |
3697 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); | 3697 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); |
3698 __ cmp(scratch, Operand(ip)); | 3698 __ cmp(scratch, Operand(ip)); |
3699 DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumber); | 3699 DeoptimizeIf(ne, instr, "not a heap number"); |
3700 | 3700 |
3701 Label done; | 3701 Label done; |
3702 Register exponent = scratch0(); | 3702 Register exponent = scratch0(); |
3703 scratch = no_reg; | 3703 scratch = no_reg; |
3704 __ ldr(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset)); | 3704 __ ldr(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset)); |
3705 // Check the sign of the argument. If the argument is positive, just | 3705 // Check the sign of the argument. If the argument is positive, just |
3706 // return it. | 3706 // return it. |
3707 __ tst(exponent, Operand(HeapNumber::kSignMask)); | 3707 __ tst(exponent, Operand(HeapNumber::kSignMask)); |
3708 // Move the input to the result if necessary. | 3708 // Move the input to the result if necessary. |
3709 __ Move(result, input); | 3709 __ Move(result, input); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3757 void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) { | 3757 void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) { |
3758 Register input = ToRegister(instr->value()); | 3758 Register input = ToRegister(instr->value()); |
3759 Register result = ToRegister(instr->result()); | 3759 Register result = ToRegister(instr->result()); |
3760 __ cmp(input, Operand::Zero()); | 3760 __ cmp(input, Operand::Zero()); |
3761 __ Move(result, input, pl); | 3761 __ Move(result, input, pl); |
3762 // We can make rsb conditional because the previous cmp instruction | 3762 // We can make rsb conditional because the previous cmp instruction |
3763 // will clear the V (overflow) flag and rsb won't set this flag | 3763 // will clear the V (overflow) flag and rsb won't set this flag |
3764 // if input is positive. | 3764 // if input is positive. |
3765 __ rsb(result, input, Operand::Zero(), SetCC, mi); | 3765 __ rsb(result, input, Operand::Zero(), SetCC, mi); |
3766 // Deoptimize on overflow. | 3766 // Deoptimize on overflow. |
3767 DeoptimizeIf(vs, instr, Deoptimizer::kOverflow); | 3767 DeoptimizeIf(vs, instr, "overflow"); |
3768 } | 3768 } |
3769 | 3769 |
3770 | 3770 |
3771 void LCodeGen::DoMathAbs(LMathAbs* instr) { | 3771 void LCodeGen::DoMathAbs(LMathAbs* instr) { |
3772 // Class for deferred case. | 3772 // Class for deferred case. |
3773 class DeferredMathAbsTaggedHeapNumber FINAL : public LDeferredCode { | 3773 class DeferredMathAbsTaggedHeapNumber FINAL : public LDeferredCode { |
3774 public: | 3774 public: |
3775 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, LMathAbs* instr) | 3775 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, LMathAbs* instr) |
3776 : LDeferredCode(codegen), instr_(instr) { } | 3776 : LDeferredCode(codegen), instr_(instr) { } |
3777 void Generate() OVERRIDE { | 3777 void Generate() OVERRIDE { |
(...skipping 26 matching lines...) Expand all Loading... |
3804 } | 3804 } |
3805 | 3805 |
3806 | 3806 |
3807 void LCodeGen::DoMathFloor(LMathFloor* instr) { | 3807 void LCodeGen::DoMathFloor(LMathFloor* instr) { |
3808 DwVfpRegister input = ToDoubleRegister(instr->value()); | 3808 DwVfpRegister input = ToDoubleRegister(instr->value()); |
3809 Register result = ToRegister(instr->result()); | 3809 Register result = ToRegister(instr->result()); |
3810 Register input_high = scratch0(); | 3810 Register input_high = scratch0(); |
3811 Label done, exact; | 3811 Label done, exact; |
3812 | 3812 |
3813 __ TryInt32Floor(result, input, input_high, double_scratch0(), &done, &exact); | 3813 __ TryInt32Floor(result, input, input_high, double_scratch0(), &done, &exact); |
3814 DeoptimizeIf(al, instr, Deoptimizer::kLostPrecisionOrNaN); | 3814 DeoptimizeIf(al, instr, "lost precision or NaN"); |
3815 | 3815 |
3816 __ bind(&exact); | 3816 __ bind(&exact); |
3817 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3817 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
3818 // Test for -0. | 3818 // Test for -0. |
3819 __ cmp(result, Operand::Zero()); | 3819 __ cmp(result, Operand::Zero()); |
3820 __ b(ne, &done); | 3820 __ b(ne, &done); |
3821 __ cmp(input_high, Operand::Zero()); | 3821 __ cmp(input_high, Operand::Zero()); |
3822 DeoptimizeIf(mi, instr, Deoptimizer::kMinusZero); | 3822 DeoptimizeIf(mi, instr, "minus zero"); |
3823 } | 3823 } |
3824 __ bind(&done); | 3824 __ bind(&done); |
3825 } | 3825 } |
3826 | 3826 |
3827 | 3827 |
3828 void LCodeGen::DoMathRound(LMathRound* instr) { | 3828 void LCodeGen::DoMathRound(LMathRound* instr) { |
3829 DwVfpRegister input = ToDoubleRegister(instr->value()); | 3829 DwVfpRegister input = ToDoubleRegister(instr->value()); |
3830 Register result = ToRegister(instr->result()); | 3830 Register result = ToRegister(instr->result()); |
3831 DwVfpRegister double_scratch1 = ToDoubleRegister(instr->temp()); | 3831 DwVfpRegister double_scratch1 = ToDoubleRegister(instr->temp()); |
3832 DwVfpRegister input_plus_dot_five = double_scratch1; | 3832 DwVfpRegister input_plus_dot_five = double_scratch1; |
3833 Register input_high = scratch0(); | 3833 Register input_high = scratch0(); |
3834 DwVfpRegister dot_five = double_scratch0(); | 3834 DwVfpRegister dot_five = double_scratch0(); |
3835 Label convert, done; | 3835 Label convert, done; |
3836 | 3836 |
3837 __ Vmov(dot_five, 0.5, scratch0()); | 3837 __ Vmov(dot_five, 0.5, scratch0()); |
3838 __ vabs(double_scratch1, input); | 3838 __ vabs(double_scratch1, input); |
3839 __ VFPCompareAndSetFlags(double_scratch1, dot_five); | 3839 __ VFPCompareAndSetFlags(double_scratch1, dot_five); |
3840 // If input is in [-0.5, -0], the result is -0. | 3840 // If input is in [-0.5, -0], the result is -0. |
3841 // If input is in [+0, +0.5[, the result is +0. | 3841 // If input is in [+0, +0.5[, the result is +0. |
3842 // If the input is +0.5, the result is 1. | 3842 // If the input is +0.5, the result is 1. |
3843 __ b(hi, &convert); // Out of [-0.5, +0.5]. | 3843 __ b(hi, &convert); // Out of [-0.5, +0.5]. |
3844 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3844 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
3845 __ VmovHigh(input_high, input); | 3845 __ VmovHigh(input_high, input); |
3846 __ cmp(input_high, Operand::Zero()); | 3846 __ cmp(input_high, Operand::Zero()); |
3847 // [-0.5, -0]. | 3847 // [-0.5, -0]. |
3848 DeoptimizeIf(mi, instr, Deoptimizer::kMinusZero); | 3848 DeoptimizeIf(mi, instr, "minus zero"); |
3849 } | 3849 } |
3850 __ VFPCompareAndSetFlags(input, dot_five); | 3850 __ VFPCompareAndSetFlags(input, dot_five); |
3851 __ mov(result, Operand(1), LeaveCC, eq); // +0.5. | 3851 __ mov(result, Operand(1), LeaveCC, eq); // +0.5. |
3852 // Remaining cases: [+0, +0.5[ or [-0.5, +0.5[, depending on | 3852 // Remaining cases: [+0, +0.5[ or [-0.5, +0.5[, depending on |
3853 // flag kBailoutOnMinusZero. | 3853 // flag kBailoutOnMinusZero. |
3854 __ mov(result, Operand::Zero(), LeaveCC, ne); | 3854 __ mov(result, Operand::Zero(), LeaveCC, ne); |
3855 __ b(&done); | 3855 __ b(&done); |
3856 | 3856 |
3857 __ bind(&convert); | 3857 __ bind(&convert); |
3858 __ vadd(input_plus_dot_five, input, dot_five); | 3858 __ vadd(input_plus_dot_five, input, dot_five); |
3859 // Reuse dot_five (double_scratch0) as we no longer need this value. | 3859 // Reuse dot_five (double_scratch0) as we no longer need this value. |
3860 __ TryInt32Floor(result, input_plus_dot_five, input_high, double_scratch0(), | 3860 __ TryInt32Floor(result, input_plus_dot_five, input_high, double_scratch0(), |
3861 &done, &done); | 3861 &done, &done); |
3862 DeoptimizeIf(al, instr, Deoptimizer::kLostPrecisionOrNaN); | 3862 DeoptimizeIf(al, instr, "lost precision or NaN"); |
3863 __ bind(&done); | 3863 __ bind(&done); |
3864 } | 3864 } |
3865 | 3865 |
3866 | 3866 |
3867 void LCodeGen::DoMathFround(LMathFround* instr) { | 3867 void LCodeGen::DoMathFround(LMathFround* instr) { |
3868 DwVfpRegister input_reg = ToDoubleRegister(instr->value()); | 3868 DwVfpRegister input_reg = ToDoubleRegister(instr->value()); |
3869 DwVfpRegister output_reg = ToDoubleRegister(instr->result()); | 3869 DwVfpRegister output_reg = ToDoubleRegister(instr->result()); |
3870 LowDwVfpRegister scratch = double_scratch0(); | 3870 LowDwVfpRegister scratch = double_scratch0(); |
3871 __ vcvt_f32_f64(scratch.low(), input_reg); | 3871 __ vcvt_f32_f64(scratch.low(), input_reg); |
3872 __ vcvt_f64_f32(output_reg, scratch.low()); | 3872 __ vcvt_f64_f32(output_reg, scratch.low()); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3916 if (exponent_type.IsSmi()) { | 3916 if (exponent_type.IsSmi()) { |
3917 MathPowStub stub(isolate(), MathPowStub::TAGGED); | 3917 MathPowStub stub(isolate(), MathPowStub::TAGGED); |
3918 __ CallStub(&stub); | 3918 __ CallStub(&stub); |
3919 } else if (exponent_type.IsTagged()) { | 3919 } else if (exponent_type.IsTagged()) { |
3920 Label no_deopt; | 3920 Label no_deopt; |
3921 __ JumpIfSmi(tagged_exponent, &no_deopt); | 3921 __ JumpIfSmi(tagged_exponent, &no_deopt); |
3922 DCHECK(!r6.is(tagged_exponent)); | 3922 DCHECK(!r6.is(tagged_exponent)); |
3923 __ ldr(r6, FieldMemOperand(tagged_exponent, HeapObject::kMapOffset)); | 3923 __ ldr(r6, FieldMemOperand(tagged_exponent, HeapObject::kMapOffset)); |
3924 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); | 3924 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); |
3925 __ cmp(r6, Operand(ip)); | 3925 __ cmp(r6, Operand(ip)); |
3926 DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumber); | 3926 DeoptimizeIf(ne, instr, "not a heap number"); |
3927 __ bind(&no_deopt); | 3927 __ bind(&no_deopt); |
3928 MathPowStub stub(isolate(), MathPowStub::TAGGED); | 3928 MathPowStub stub(isolate(), MathPowStub::TAGGED); |
3929 __ CallStub(&stub); | 3929 __ CallStub(&stub); |
3930 } else if (exponent_type.IsInteger32()) { | 3930 } else if (exponent_type.IsInteger32()) { |
3931 MathPowStub stub(isolate(), MathPowStub::INTEGER); | 3931 MathPowStub stub(isolate(), MathPowStub::INTEGER); |
3932 __ CallStub(&stub); | 3932 __ CallStub(&stub); |
3933 } else { | 3933 } else { |
3934 DCHECK(exponent_type.IsDouble()); | 3934 DCHECK(exponent_type.IsDouble()); |
3935 MathPowStub stub(isolate(), MathPowStub::DOUBLE); | 3935 MathPowStub stub(isolate(), MathPowStub::DOUBLE); |
3936 __ CallStub(&stub); | 3936 __ CallStub(&stub); |
(...skipping 388 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4325 Register index = ToRegister(instr->index()); | 4325 Register index = ToRegister(instr->index()); |
4326 Operand length = ToOperand(instr->length()); | 4326 Operand length = ToOperand(instr->length()); |
4327 __ cmp(index, length); | 4327 __ cmp(index, length); |
4328 } | 4328 } |
4329 if (FLAG_debug_code && instr->hydrogen()->skip_check()) { | 4329 if (FLAG_debug_code && instr->hydrogen()->skip_check()) { |
4330 Label done; | 4330 Label done; |
4331 __ b(NegateCondition(cc), &done); | 4331 __ b(NegateCondition(cc), &done); |
4332 __ stop("eliminated bounds check failed"); | 4332 __ stop("eliminated bounds check failed"); |
4333 __ bind(&done); | 4333 __ bind(&done); |
4334 } else { | 4334 } else { |
4335 DeoptimizeIf(cc, instr, Deoptimizer::kOutOfBounds); | 4335 DeoptimizeIf(cc, instr, "out of bounds"); |
4336 } | 4336 } |
4337 } | 4337 } |
4338 | 4338 |
4339 | 4339 |
4340 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) { | 4340 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) { |
4341 Register external_pointer = ToRegister(instr->elements()); | 4341 Register external_pointer = ToRegister(instr->elements()); |
4342 Register key = no_reg; | 4342 Register key = no_reg; |
4343 ElementsKind elements_kind = instr->elements_kind(); | 4343 ElementsKind elements_kind = instr->elements_kind(); |
4344 bool key_is_constant = instr->key()->IsConstantOperand(); | 4344 bool key_is_constant = instr->key()->IsConstantOperand(); |
4345 int constant_key = 0; | 4345 int constant_key = 0; |
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4573 } | 4573 } |
4574 __ bind(¬_applicable); | 4574 __ bind(¬_applicable); |
4575 } | 4575 } |
4576 | 4576 |
4577 | 4577 |
4578 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) { | 4578 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) { |
4579 Register object = ToRegister(instr->object()); | 4579 Register object = ToRegister(instr->object()); |
4580 Register temp = ToRegister(instr->temp()); | 4580 Register temp = ToRegister(instr->temp()); |
4581 Label no_memento_found; | 4581 Label no_memento_found; |
4582 __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found); | 4582 __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found); |
4583 DeoptimizeIf(eq, instr, Deoptimizer::kMementoFound); | 4583 DeoptimizeIf(eq, instr, "memento found"); |
4584 __ bind(&no_memento_found); | 4584 __ bind(&no_memento_found); |
4585 } | 4585 } |
4586 | 4586 |
4587 | 4587 |
4588 void LCodeGen::DoStringAdd(LStringAdd* instr) { | 4588 void LCodeGen::DoStringAdd(LStringAdd* instr) { |
4589 DCHECK(ToRegister(instr->context()).is(cp)); | 4589 DCHECK(ToRegister(instr->context()).is(cp)); |
4590 DCHECK(ToRegister(instr->left()).is(r1)); | 4590 DCHECK(ToRegister(instr->left()).is(r1)); |
4591 DCHECK(ToRegister(instr->right()).is(r0)); | 4591 DCHECK(ToRegister(instr->right()).is(r0)); |
4592 StringAddStub stub(isolate(), | 4592 StringAddStub stub(isolate(), |
4593 instr->hydrogen()->flags(), | 4593 instr->hydrogen()->flags(), |
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4908 } | 4908 } |
4909 | 4909 |
4910 | 4910 |
4911 void LCodeGen::DoSmiTag(LSmiTag* instr) { | 4911 void LCodeGen::DoSmiTag(LSmiTag* instr) { |
4912 HChange* hchange = instr->hydrogen(); | 4912 HChange* hchange = instr->hydrogen(); |
4913 Register input = ToRegister(instr->value()); | 4913 Register input = ToRegister(instr->value()); |
4914 Register output = ToRegister(instr->result()); | 4914 Register output = ToRegister(instr->result()); |
4915 if (hchange->CheckFlag(HValue::kCanOverflow) && | 4915 if (hchange->CheckFlag(HValue::kCanOverflow) && |
4916 hchange->value()->CheckFlag(HValue::kUint32)) { | 4916 hchange->value()->CheckFlag(HValue::kUint32)) { |
4917 __ tst(input, Operand(0xc0000000)); | 4917 __ tst(input, Operand(0xc0000000)); |
4918 DeoptimizeIf(ne, instr, Deoptimizer::kOverflow); | 4918 DeoptimizeIf(ne, instr, "overflow"); |
4919 } | 4919 } |
4920 if (hchange->CheckFlag(HValue::kCanOverflow) && | 4920 if (hchange->CheckFlag(HValue::kCanOverflow) && |
4921 !hchange->value()->CheckFlag(HValue::kUint32)) { | 4921 !hchange->value()->CheckFlag(HValue::kUint32)) { |
4922 __ SmiTag(output, input, SetCC); | 4922 __ SmiTag(output, input, SetCC); |
4923 DeoptimizeIf(vs, instr, Deoptimizer::kOverflow); | 4923 DeoptimizeIf(vs, instr, "overflow"); |
4924 } else { | 4924 } else { |
4925 __ SmiTag(output, input); | 4925 __ SmiTag(output, input); |
4926 } | 4926 } |
4927 } | 4927 } |
4928 | 4928 |
4929 | 4929 |
4930 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { | 4930 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { |
4931 Register input = ToRegister(instr->value()); | 4931 Register input = ToRegister(instr->value()); |
4932 Register result = ToRegister(instr->result()); | 4932 Register result = ToRegister(instr->result()); |
4933 if (instr->needs_check()) { | 4933 if (instr->needs_check()) { |
4934 STATIC_ASSERT(kHeapObjectTag == 1); | 4934 STATIC_ASSERT(kHeapObjectTag == 1); |
4935 // If the input is a HeapObject, SmiUntag will set the carry flag. | 4935 // If the input is a HeapObject, SmiUntag will set the carry flag. |
4936 __ SmiUntag(result, input, SetCC); | 4936 __ SmiUntag(result, input, SetCC); |
4937 DeoptimizeIf(cs, instr, Deoptimizer::kNotASmi); | 4937 DeoptimizeIf(cs, instr, "not a Smi"); |
4938 } else { | 4938 } else { |
4939 __ SmiUntag(result, input); | 4939 __ SmiUntag(result, input); |
4940 } | 4940 } |
4941 } | 4941 } |
4942 | 4942 |
4943 | 4943 |
4944 void LCodeGen::EmitNumberUntagD(LNumberUntagD* instr, Register input_reg, | 4944 void LCodeGen::EmitNumberUntagD(LNumberUntagD* instr, Register input_reg, |
4945 DwVfpRegister result_reg, | 4945 DwVfpRegister result_reg, |
4946 NumberUntagDMode mode) { | 4946 NumberUntagDMode mode) { |
4947 bool can_convert_undefined_to_nan = | 4947 bool can_convert_undefined_to_nan = |
4948 instr->hydrogen()->can_convert_undefined_to_nan(); | 4948 instr->hydrogen()->can_convert_undefined_to_nan(); |
4949 bool deoptimize_on_minus_zero = instr->hydrogen()->deoptimize_on_minus_zero(); | 4949 bool deoptimize_on_minus_zero = instr->hydrogen()->deoptimize_on_minus_zero(); |
4950 | 4950 |
4951 Register scratch = scratch0(); | 4951 Register scratch = scratch0(); |
4952 SwVfpRegister flt_scratch = double_scratch0().low(); | 4952 SwVfpRegister flt_scratch = double_scratch0().low(); |
4953 DCHECK(!result_reg.is(double_scratch0())); | 4953 DCHECK(!result_reg.is(double_scratch0())); |
4954 Label convert, load_smi, done; | 4954 Label convert, load_smi, done; |
4955 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) { | 4955 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) { |
4956 // Smi check. | 4956 // Smi check. |
4957 __ UntagAndJumpIfSmi(scratch, input_reg, &load_smi); | 4957 __ UntagAndJumpIfSmi(scratch, input_reg, &load_smi); |
4958 // Heap number map check. | 4958 // Heap number map check. |
4959 __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); | 4959 __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); |
4960 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); | 4960 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); |
4961 __ cmp(scratch, Operand(ip)); | 4961 __ cmp(scratch, Operand(ip)); |
4962 if (can_convert_undefined_to_nan) { | 4962 if (can_convert_undefined_to_nan) { |
4963 __ b(ne, &convert); | 4963 __ b(ne, &convert); |
4964 } else { | 4964 } else { |
4965 DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumber); | 4965 DeoptimizeIf(ne, instr, "not a heap number"); |
4966 } | 4966 } |
4967 // load heap number | 4967 // load heap number |
4968 __ vldr(result_reg, input_reg, HeapNumber::kValueOffset - kHeapObjectTag); | 4968 __ vldr(result_reg, input_reg, HeapNumber::kValueOffset - kHeapObjectTag); |
4969 if (deoptimize_on_minus_zero) { | 4969 if (deoptimize_on_minus_zero) { |
4970 __ VmovLow(scratch, result_reg); | 4970 __ VmovLow(scratch, result_reg); |
4971 __ cmp(scratch, Operand::Zero()); | 4971 __ cmp(scratch, Operand::Zero()); |
4972 __ b(ne, &done); | 4972 __ b(ne, &done); |
4973 __ VmovHigh(scratch, result_reg); | 4973 __ VmovHigh(scratch, result_reg); |
4974 __ cmp(scratch, Operand(HeapNumber::kSignMask)); | 4974 __ cmp(scratch, Operand(HeapNumber::kSignMask)); |
4975 DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero); | 4975 DeoptimizeIf(eq, instr, "minus zero"); |
4976 } | 4976 } |
4977 __ jmp(&done); | 4977 __ jmp(&done); |
4978 if (can_convert_undefined_to_nan) { | 4978 if (can_convert_undefined_to_nan) { |
4979 __ bind(&convert); | 4979 __ bind(&convert); |
4980 // Convert undefined (and hole) to NaN. | 4980 // Convert undefined (and hole) to NaN. |
4981 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 4981 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
4982 __ cmp(input_reg, Operand(ip)); | 4982 __ cmp(input_reg, Operand(ip)); |
4983 DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumberUndefined); | 4983 DeoptimizeIf(ne, instr, "not a heap number/undefined"); |
4984 __ LoadRoot(scratch, Heap::kNanValueRootIndex); | 4984 __ LoadRoot(scratch, Heap::kNanValueRootIndex); |
4985 __ vldr(result_reg, scratch, HeapNumber::kValueOffset - kHeapObjectTag); | 4985 __ vldr(result_reg, scratch, HeapNumber::kValueOffset - kHeapObjectTag); |
4986 __ jmp(&done); | 4986 __ jmp(&done); |
4987 } | 4987 } |
4988 } else { | 4988 } else { |
4989 __ SmiUntag(scratch, input_reg); | 4989 __ SmiUntag(scratch, input_reg); |
4990 DCHECK(mode == NUMBER_CANDIDATE_IS_SMI); | 4990 DCHECK(mode == NUMBER_CANDIDATE_IS_SMI); |
4991 } | 4991 } |
4992 // Smi to double register conversion | 4992 // Smi to double register conversion |
4993 __ bind(&load_smi); | 4993 __ bind(&load_smi); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5041 __ bind(&check_bools); | 5041 __ bind(&check_bools); |
5042 __ LoadRoot(ip, Heap::kTrueValueRootIndex); | 5042 __ LoadRoot(ip, Heap::kTrueValueRootIndex); |
5043 __ cmp(scratch2, Operand(ip)); | 5043 __ cmp(scratch2, Operand(ip)); |
5044 __ b(ne, &check_false); | 5044 __ b(ne, &check_false); |
5045 __ mov(input_reg, Operand(1)); | 5045 __ mov(input_reg, Operand(1)); |
5046 __ b(&done); | 5046 __ b(&done); |
5047 | 5047 |
5048 __ bind(&check_false); | 5048 __ bind(&check_false); |
5049 __ LoadRoot(ip, Heap::kFalseValueRootIndex); | 5049 __ LoadRoot(ip, Heap::kFalseValueRootIndex); |
5050 __ cmp(scratch2, Operand(ip)); | 5050 __ cmp(scratch2, Operand(ip)); |
5051 DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumberUndefinedBoolean); | 5051 DeoptimizeIf(ne, instr, "not a heap number/undefined/true/false"); |
5052 __ mov(input_reg, Operand::Zero()); | 5052 __ mov(input_reg, Operand::Zero()); |
5053 } else { | 5053 } else { |
5054 DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumber); | 5054 DeoptimizeIf(ne, instr, "not a heap number"); |
5055 | 5055 |
5056 __ sub(ip, scratch2, Operand(kHeapObjectTag)); | 5056 __ sub(ip, scratch2, Operand(kHeapObjectTag)); |
5057 __ vldr(double_scratch2, ip, HeapNumber::kValueOffset); | 5057 __ vldr(double_scratch2, ip, HeapNumber::kValueOffset); |
5058 __ TryDoubleToInt32Exact(input_reg, double_scratch2, double_scratch); | 5058 __ TryDoubleToInt32Exact(input_reg, double_scratch2, double_scratch); |
5059 DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecisionOrNaN); | 5059 DeoptimizeIf(ne, instr, "lost precision or NaN"); |
5060 | 5060 |
5061 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 5061 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
5062 __ cmp(input_reg, Operand::Zero()); | 5062 __ cmp(input_reg, Operand::Zero()); |
5063 __ b(ne, &done); | 5063 __ b(ne, &done); |
5064 __ VmovHigh(scratch1, double_scratch2); | 5064 __ VmovHigh(scratch1, double_scratch2); |
5065 __ tst(scratch1, Operand(HeapNumber::kSignMask)); | 5065 __ tst(scratch1, Operand(HeapNumber::kSignMask)); |
5066 DeoptimizeIf(ne, instr, Deoptimizer::kMinusZero); | 5066 DeoptimizeIf(ne, instr, "minus zero"); |
5067 } | 5067 } |
5068 } | 5068 } |
5069 __ bind(&done); | 5069 __ bind(&done); |
5070 } | 5070 } |
5071 | 5071 |
5072 | 5072 |
5073 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { | 5073 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { |
5074 class DeferredTaggedToI FINAL : public LDeferredCode { | 5074 class DeferredTaggedToI FINAL : public LDeferredCode { |
5075 public: | 5075 public: |
5076 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) | 5076 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5125 Register result_reg = ToRegister(instr->result()); | 5125 Register result_reg = ToRegister(instr->result()); |
5126 Register scratch1 = scratch0(); | 5126 Register scratch1 = scratch0(); |
5127 DwVfpRegister double_input = ToDoubleRegister(instr->value()); | 5127 DwVfpRegister double_input = ToDoubleRegister(instr->value()); |
5128 LowDwVfpRegister double_scratch = double_scratch0(); | 5128 LowDwVfpRegister double_scratch = double_scratch0(); |
5129 | 5129 |
5130 if (instr->truncating()) { | 5130 if (instr->truncating()) { |
5131 __ TruncateDoubleToI(result_reg, double_input); | 5131 __ TruncateDoubleToI(result_reg, double_input); |
5132 } else { | 5132 } else { |
5133 __ TryDoubleToInt32Exact(result_reg, double_input, double_scratch); | 5133 __ TryDoubleToInt32Exact(result_reg, double_input, double_scratch); |
5134 // Deoptimize if the input wasn't a int32 (inside a double). | 5134 // Deoptimize if the input wasn't a int32 (inside a double). |
5135 DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecisionOrNaN); | 5135 DeoptimizeIf(ne, instr, "lost precision or NaN"); |
5136 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 5136 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
5137 Label done; | 5137 Label done; |
5138 __ cmp(result_reg, Operand::Zero()); | 5138 __ cmp(result_reg, Operand::Zero()); |
5139 __ b(ne, &done); | 5139 __ b(ne, &done); |
5140 __ VmovHigh(scratch1, double_input); | 5140 __ VmovHigh(scratch1, double_input); |
5141 __ tst(scratch1, Operand(HeapNumber::kSignMask)); | 5141 __ tst(scratch1, Operand(HeapNumber::kSignMask)); |
5142 DeoptimizeIf(ne, instr, Deoptimizer::kMinusZero); | 5142 DeoptimizeIf(ne, instr, "minus zero"); |
5143 __ bind(&done); | 5143 __ bind(&done); |
5144 } | 5144 } |
5145 } | 5145 } |
5146 } | 5146 } |
5147 | 5147 |
5148 | 5148 |
5149 void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) { | 5149 void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) { |
5150 Register result_reg = ToRegister(instr->result()); | 5150 Register result_reg = ToRegister(instr->result()); |
5151 Register scratch1 = scratch0(); | 5151 Register scratch1 = scratch0(); |
5152 DwVfpRegister double_input = ToDoubleRegister(instr->value()); | 5152 DwVfpRegister double_input = ToDoubleRegister(instr->value()); |
5153 LowDwVfpRegister double_scratch = double_scratch0(); | 5153 LowDwVfpRegister double_scratch = double_scratch0(); |
5154 | 5154 |
5155 if (instr->truncating()) { | 5155 if (instr->truncating()) { |
5156 __ TruncateDoubleToI(result_reg, double_input); | 5156 __ TruncateDoubleToI(result_reg, double_input); |
5157 } else { | 5157 } else { |
5158 __ TryDoubleToInt32Exact(result_reg, double_input, double_scratch); | 5158 __ TryDoubleToInt32Exact(result_reg, double_input, double_scratch); |
5159 // Deoptimize if the input wasn't a int32 (inside a double). | 5159 // Deoptimize if the input wasn't a int32 (inside a double). |
5160 DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecisionOrNaN); | 5160 DeoptimizeIf(ne, instr, "lost precision or NaN"); |
5161 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 5161 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
5162 Label done; | 5162 Label done; |
5163 __ cmp(result_reg, Operand::Zero()); | 5163 __ cmp(result_reg, Operand::Zero()); |
5164 __ b(ne, &done); | 5164 __ b(ne, &done); |
5165 __ VmovHigh(scratch1, double_input); | 5165 __ VmovHigh(scratch1, double_input); |
5166 __ tst(scratch1, Operand(HeapNumber::kSignMask)); | 5166 __ tst(scratch1, Operand(HeapNumber::kSignMask)); |
5167 DeoptimizeIf(ne, instr, Deoptimizer::kMinusZero); | 5167 DeoptimizeIf(ne, instr, "minus zero"); |
5168 __ bind(&done); | 5168 __ bind(&done); |
5169 } | 5169 } |
5170 } | 5170 } |
5171 __ SmiTag(result_reg, SetCC); | 5171 __ SmiTag(result_reg, SetCC); |
5172 DeoptimizeIf(vs, instr, Deoptimizer::kOverflow); | 5172 DeoptimizeIf(vs, instr, "overflow"); |
5173 } | 5173 } |
5174 | 5174 |
5175 | 5175 |
5176 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { | 5176 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { |
5177 LOperand* input = instr->value(); | 5177 LOperand* input = instr->value(); |
5178 __ SmiTst(ToRegister(input)); | 5178 __ SmiTst(ToRegister(input)); |
5179 DeoptimizeIf(ne, instr, Deoptimizer::kNotASmi); | 5179 DeoptimizeIf(ne, instr, "not a Smi"); |
5180 } | 5180 } |
5181 | 5181 |
5182 | 5182 |
5183 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { | 5183 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { |
5184 if (!instr->hydrogen()->value()->type().IsHeapObject()) { | 5184 if (!instr->hydrogen()->value()->type().IsHeapObject()) { |
5185 LOperand* input = instr->value(); | 5185 LOperand* input = instr->value(); |
5186 __ SmiTst(ToRegister(input)); | 5186 __ SmiTst(ToRegister(input)); |
5187 DeoptimizeIf(eq, instr, Deoptimizer::kSmi); | 5187 DeoptimizeIf(eq, instr, "Smi"); |
5188 } | 5188 } |
5189 } | 5189 } |
5190 | 5190 |
5191 | 5191 |
5192 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { | 5192 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { |
5193 Register input = ToRegister(instr->value()); | 5193 Register input = ToRegister(instr->value()); |
5194 Register scratch = scratch0(); | 5194 Register scratch = scratch0(); |
5195 | 5195 |
5196 __ ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); | 5196 __ ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); |
5197 __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); | 5197 __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); |
5198 | 5198 |
5199 if (instr->hydrogen()->is_interval_check()) { | 5199 if (instr->hydrogen()->is_interval_check()) { |
5200 InstanceType first; | 5200 InstanceType first; |
5201 InstanceType last; | 5201 InstanceType last; |
5202 instr->hydrogen()->GetCheckInterval(&first, &last); | 5202 instr->hydrogen()->GetCheckInterval(&first, &last); |
5203 | 5203 |
5204 __ cmp(scratch, Operand(first)); | 5204 __ cmp(scratch, Operand(first)); |
5205 | 5205 |
5206 // If there is only one type in the interval check for equality. | 5206 // If there is only one type in the interval check for equality. |
5207 if (first == last) { | 5207 if (first == last) { |
5208 DeoptimizeIf(ne, instr, Deoptimizer::kWrongInstanceType); | 5208 DeoptimizeIf(ne, instr, "wrong instance type"); |
5209 } else { | 5209 } else { |
5210 DeoptimizeIf(lo, instr, Deoptimizer::kWrongInstanceType); | 5210 DeoptimizeIf(lo, instr, "wrong instance type"); |
5211 // Omit check for the last type. | 5211 // Omit check for the last type. |
5212 if (last != LAST_TYPE) { | 5212 if (last != LAST_TYPE) { |
5213 __ cmp(scratch, Operand(last)); | 5213 __ cmp(scratch, Operand(last)); |
5214 DeoptimizeIf(hi, instr, Deoptimizer::kWrongInstanceType); | 5214 DeoptimizeIf(hi, instr, "wrong instance type"); |
5215 } | 5215 } |
5216 } | 5216 } |
5217 } else { | 5217 } else { |
5218 uint8_t mask; | 5218 uint8_t mask; |
5219 uint8_t tag; | 5219 uint8_t tag; |
5220 instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag); | 5220 instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag); |
5221 | 5221 |
5222 if (base::bits::IsPowerOfTwo32(mask)) { | 5222 if (base::bits::IsPowerOfTwo32(mask)) { |
5223 DCHECK(tag == 0 || base::bits::IsPowerOfTwo32(tag)); | 5223 DCHECK(tag == 0 || base::bits::IsPowerOfTwo32(tag)); |
5224 __ tst(scratch, Operand(mask)); | 5224 __ tst(scratch, Operand(mask)); |
5225 DeoptimizeIf(tag == 0 ? ne : eq, instr, Deoptimizer::kWrongInstanceType); | 5225 DeoptimizeIf(tag == 0 ? ne : eq, instr, "wrong instance type"); |
5226 } else { | 5226 } else { |
5227 __ and_(scratch, scratch, Operand(mask)); | 5227 __ and_(scratch, scratch, Operand(mask)); |
5228 __ cmp(scratch, Operand(tag)); | 5228 __ cmp(scratch, Operand(tag)); |
5229 DeoptimizeIf(ne, instr, Deoptimizer::kWrongInstanceType); | 5229 DeoptimizeIf(ne, instr, "wrong instance type"); |
5230 } | 5230 } |
5231 } | 5231 } |
5232 } | 5232 } |
5233 | 5233 |
5234 | 5234 |
5235 void LCodeGen::DoCheckValue(LCheckValue* instr) { | 5235 void LCodeGen::DoCheckValue(LCheckValue* instr) { |
5236 Register reg = ToRegister(instr->value()); | 5236 Register reg = ToRegister(instr->value()); |
5237 Handle<HeapObject> object = instr->hydrogen()->object().handle(); | 5237 Handle<HeapObject> object = instr->hydrogen()->object().handle(); |
5238 AllowDeferredHandleDereference smi_check; | 5238 AllowDeferredHandleDereference smi_check; |
5239 if (isolate()->heap()->InNewSpace(*object)) { | 5239 if (isolate()->heap()->InNewSpace(*object)) { |
5240 Register reg = ToRegister(instr->value()); | 5240 Register reg = ToRegister(instr->value()); |
5241 Handle<Cell> cell = isolate()->factory()->NewCell(object); | 5241 Handle<Cell> cell = isolate()->factory()->NewCell(object); |
5242 __ mov(ip, Operand(Handle<Object>(cell))); | 5242 __ mov(ip, Operand(Handle<Object>(cell))); |
5243 __ ldr(ip, FieldMemOperand(ip, Cell::kValueOffset)); | 5243 __ ldr(ip, FieldMemOperand(ip, Cell::kValueOffset)); |
5244 __ cmp(reg, ip); | 5244 __ cmp(reg, ip); |
5245 } else { | 5245 } else { |
5246 __ cmp(reg, Operand(object)); | 5246 __ cmp(reg, Operand(object)); |
5247 } | 5247 } |
5248 DeoptimizeIf(ne, instr, Deoptimizer::kValueMismatch); | 5248 DeoptimizeIf(ne, instr, "value mismatch"); |
5249 } | 5249 } |
5250 | 5250 |
5251 | 5251 |
5252 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) { | 5252 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) { |
5253 { | 5253 { |
5254 PushSafepointRegistersScope scope(this); | 5254 PushSafepointRegistersScope scope(this); |
5255 __ push(object); | 5255 __ push(object); |
5256 __ mov(cp, Operand::Zero()); | 5256 __ mov(cp, Operand::Zero()); |
5257 __ CallRuntimeSaveDoubles(Runtime::kTryMigrateInstance); | 5257 __ CallRuntimeSaveDoubles(Runtime::kTryMigrateInstance); |
5258 RecordSafepointWithRegisters( | 5258 RecordSafepointWithRegisters( |
5259 instr->pointer_map(), 1, Safepoint::kNoLazyDeopt); | 5259 instr->pointer_map(), 1, Safepoint::kNoLazyDeopt); |
5260 __ StoreToSafepointRegisterSlot(r0, scratch0()); | 5260 __ StoreToSafepointRegisterSlot(r0, scratch0()); |
5261 } | 5261 } |
5262 __ tst(scratch0(), Operand(kSmiTagMask)); | 5262 __ tst(scratch0(), Operand(kSmiTagMask)); |
5263 DeoptimizeIf(eq, instr, Deoptimizer::kInstanceMigrationFailed); | 5263 DeoptimizeIf(eq, instr, "instance migration failed"); |
5264 } | 5264 } |
5265 | 5265 |
5266 | 5266 |
5267 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { | 5267 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { |
5268 class DeferredCheckMaps FINAL : public LDeferredCode { | 5268 class DeferredCheckMaps FINAL : public LDeferredCode { |
5269 public: | 5269 public: |
5270 DeferredCheckMaps(LCodeGen* codegen, LCheckMaps* instr, Register object) | 5270 DeferredCheckMaps(LCodeGen* codegen, LCheckMaps* instr, Register object) |
5271 : LDeferredCode(codegen), instr_(instr), object_(object) { | 5271 : LDeferredCode(codegen), instr_(instr), object_(object) { |
5272 SetExit(check_maps()); | 5272 SetExit(check_maps()); |
5273 } | 5273 } |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5311 Handle<Map> map = maps->at(i).handle(); | 5311 Handle<Map> map = maps->at(i).handle(); |
5312 __ CompareMap(map_reg, map, &success); | 5312 __ CompareMap(map_reg, map, &success); |
5313 __ b(eq, &success); | 5313 __ b(eq, &success); |
5314 } | 5314 } |
5315 | 5315 |
5316 Handle<Map> map = maps->at(maps->size() - 1).handle(); | 5316 Handle<Map> map = maps->at(maps->size() - 1).handle(); |
5317 __ CompareMap(map_reg, map, &success); | 5317 __ CompareMap(map_reg, map, &success); |
5318 if (instr->hydrogen()->HasMigrationTarget()) { | 5318 if (instr->hydrogen()->HasMigrationTarget()) { |
5319 __ b(ne, deferred->entry()); | 5319 __ b(ne, deferred->entry()); |
5320 } else { | 5320 } else { |
5321 DeoptimizeIf(ne, instr, Deoptimizer::kWrongMap); | 5321 DeoptimizeIf(ne, instr, "wrong map"); |
5322 } | 5322 } |
5323 | 5323 |
5324 __ bind(&success); | 5324 __ bind(&success); |
5325 } | 5325 } |
5326 | 5326 |
5327 | 5327 |
5328 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { | 5328 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { |
5329 DwVfpRegister value_reg = ToDoubleRegister(instr->unclamped()); | 5329 DwVfpRegister value_reg = ToDoubleRegister(instr->unclamped()); |
5330 Register result_reg = ToRegister(instr->result()); | 5330 Register result_reg = ToRegister(instr->result()); |
5331 __ ClampDoubleToUint8(result_reg, value_reg, double_scratch0()); | 5331 __ ClampDoubleToUint8(result_reg, value_reg, double_scratch0()); |
(...skipping 18 matching lines...) Expand all Loading... |
5350 __ UntagAndJumpIfSmi(result_reg, input_reg, &is_smi); | 5350 __ UntagAndJumpIfSmi(result_reg, input_reg, &is_smi); |
5351 | 5351 |
5352 // Check for heap number | 5352 // Check for heap number |
5353 __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); | 5353 __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); |
5354 __ cmp(scratch, Operand(factory()->heap_number_map())); | 5354 __ cmp(scratch, Operand(factory()->heap_number_map())); |
5355 __ b(eq, &heap_number); | 5355 __ b(eq, &heap_number); |
5356 | 5356 |
5357 // Check for undefined. Undefined is converted to zero for clamping | 5357 // Check for undefined. Undefined is converted to zero for clamping |
5358 // conversions. | 5358 // conversions. |
5359 __ cmp(input_reg, Operand(factory()->undefined_value())); | 5359 __ cmp(input_reg, Operand(factory()->undefined_value())); |
5360 DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumberUndefined); | 5360 DeoptimizeIf(ne, instr, "not a heap number/undefined"); |
5361 __ mov(result_reg, Operand::Zero()); | 5361 __ mov(result_reg, Operand::Zero()); |
5362 __ jmp(&done); | 5362 __ jmp(&done); |
5363 | 5363 |
5364 // Heap number | 5364 // Heap number |
5365 __ bind(&heap_number); | 5365 __ bind(&heap_number); |
5366 __ vldr(temp_reg, FieldMemOperand(input_reg, HeapNumber::kValueOffset)); | 5366 __ vldr(temp_reg, FieldMemOperand(input_reg, HeapNumber::kValueOffset)); |
5367 __ ClampDoubleToUint8(result_reg, temp_reg, double_scratch0()); | 5367 __ ClampDoubleToUint8(result_reg, temp_reg, double_scratch0()); |
5368 __ jmp(&done); | 5368 __ jmp(&done); |
5369 | 5369 |
5370 // smi | 5370 // smi |
(...skipping 447 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5818 DCHECK(!environment->HasBeenRegistered()); | 5818 DCHECK(!environment->HasBeenRegistered()); |
5819 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); | 5819 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); |
5820 | 5820 |
5821 GenerateOsrPrologue(); | 5821 GenerateOsrPrologue(); |
5822 } | 5822 } |
5823 | 5823 |
5824 | 5824 |
5825 void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) { | 5825 void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) { |
5826 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 5826 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
5827 __ cmp(r0, ip); | 5827 __ cmp(r0, ip); |
5828 DeoptimizeIf(eq, instr, Deoptimizer::kUndefined); | 5828 DeoptimizeIf(eq, instr, "undefined"); |
5829 | 5829 |
5830 Register null_value = r5; | 5830 Register null_value = r5; |
5831 __ LoadRoot(null_value, Heap::kNullValueRootIndex); | 5831 __ LoadRoot(null_value, Heap::kNullValueRootIndex); |
5832 __ cmp(r0, null_value); | 5832 __ cmp(r0, null_value); |
5833 DeoptimizeIf(eq, instr, Deoptimizer::kNull); | 5833 DeoptimizeIf(eq, instr, "null"); |
5834 | 5834 |
5835 __ SmiTst(r0); | 5835 __ SmiTst(r0); |
5836 DeoptimizeIf(eq, instr, Deoptimizer::kSmi); | 5836 DeoptimizeIf(eq, instr, "Smi"); |
5837 | 5837 |
5838 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); | 5838 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); |
5839 __ CompareObjectType(r0, r1, r1, LAST_JS_PROXY_TYPE); | 5839 __ CompareObjectType(r0, r1, r1, LAST_JS_PROXY_TYPE); |
5840 DeoptimizeIf(le, instr, Deoptimizer::kWrongInstanceType); | 5840 DeoptimizeIf(le, instr, "wrong instance type"); |
5841 | 5841 |
5842 Label use_cache, call_runtime; | 5842 Label use_cache, call_runtime; |
5843 __ CheckEnumCache(null_value, &call_runtime); | 5843 __ CheckEnumCache(null_value, &call_runtime); |
5844 | 5844 |
5845 __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset)); | 5845 __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset)); |
5846 __ b(&use_cache); | 5846 __ b(&use_cache); |
5847 | 5847 |
5848 // Get the set of properties to enumerate. | 5848 // Get the set of properties to enumerate. |
5849 __ bind(&call_runtime); | 5849 __ bind(&call_runtime); |
5850 __ push(r0); | 5850 __ push(r0); |
5851 CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr); | 5851 CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr); |
5852 | 5852 |
5853 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); | 5853 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); |
5854 __ LoadRoot(ip, Heap::kMetaMapRootIndex); | 5854 __ LoadRoot(ip, Heap::kMetaMapRootIndex); |
5855 __ cmp(r1, ip); | 5855 __ cmp(r1, ip); |
5856 DeoptimizeIf(ne, instr, Deoptimizer::kWrongMap); | 5856 DeoptimizeIf(ne, instr, "wrong map"); |
5857 __ bind(&use_cache); | 5857 __ bind(&use_cache); |
5858 } | 5858 } |
5859 | 5859 |
5860 | 5860 |
5861 void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) { | 5861 void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) { |
5862 Register map = ToRegister(instr->map()); | 5862 Register map = ToRegister(instr->map()); |
5863 Register result = ToRegister(instr->result()); | 5863 Register result = ToRegister(instr->result()); |
5864 Label load_cache, done; | 5864 Label load_cache, done; |
5865 __ EnumLength(result, map); | 5865 __ EnumLength(result, map); |
5866 __ cmp(result, Operand(Smi::FromInt(0))); | 5866 __ cmp(result, Operand(Smi::FromInt(0))); |
5867 __ b(ne, &load_cache); | 5867 __ b(ne, &load_cache); |
5868 __ mov(result, Operand(isolate()->factory()->empty_fixed_array())); | 5868 __ mov(result, Operand(isolate()->factory()->empty_fixed_array())); |
5869 __ jmp(&done); | 5869 __ jmp(&done); |
5870 | 5870 |
5871 __ bind(&load_cache); | 5871 __ bind(&load_cache); |
5872 __ LoadInstanceDescriptors(map, result); | 5872 __ LoadInstanceDescriptors(map, result); |
5873 __ ldr(result, | 5873 __ ldr(result, |
5874 FieldMemOperand(result, DescriptorArray::kEnumCacheOffset)); | 5874 FieldMemOperand(result, DescriptorArray::kEnumCacheOffset)); |
5875 __ ldr(result, | 5875 __ ldr(result, |
5876 FieldMemOperand(result, FixedArray::SizeFor(instr->idx()))); | 5876 FieldMemOperand(result, FixedArray::SizeFor(instr->idx()))); |
5877 __ cmp(result, Operand::Zero()); | 5877 __ cmp(result, Operand::Zero()); |
5878 DeoptimizeIf(eq, instr, Deoptimizer::kNoCache); | 5878 DeoptimizeIf(eq, instr, "no cache"); |
5879 | 5879 |
5880 __ bind(&done); | 5880 __ bind(&done); |
5881 } | 5881 } |
5882 | 5882 |
5883 | 5883 |
5884 void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) { | 5884 void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) { |
5885 Register object = ToRegister(instr->value()); | 5885 Register object = ToRegister(instr->value()); |
5886 Register map = ToRegister(instr->map()); | 5886 Register map = ToRegister(instr->map()); |
5887 __ ldr(scratch0(), FieldMemOperand(object, HeapObject::kMapOffset)); | 5887 __ ldr(scratch0(), FieldMemOperand(object, HeapObject::kMapOffset)); |
5888 __ cmp(map, scratch0()); | 5888 __ cmp(map, scratch0()); |
5889 DeoptimizeIf(ne, instr, Deoptimizer::kWrongMap); | 5889 DeoptimizeIf(ne, instr, "wrong map"); |
5890 } | 5890 } |
5891 | 5891 |
5892 | 5892 |
5893 void LCodeGen::DoDeferredLoadMutableDouble(LLoadFieldByIndex* instr, | 5893 void LCodeGen::DoDeferredLoadMutableDouble(LLoadFieldByIndex* instr, |
5894 Register result, | 5894 Register result, |
5895 Register object, | 5895 Register object, |
5896 Register index) { | 5896 Register index) { |
5897 PushSafepointRegistersScope scope(this); | 5897 PushSafepointRegistersScope scope(this); |
5898 __ Push(object); | 5898 __ Push(object); |
5899 __ Push(index); | 5899 __ Push(index); |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5977 __ Push(scope_info); | 5977 __ Push(scope_info); |
5978 __ push(ToRegister(instr->function())); | 5978 __ push(ToRegister(instr->function())); |
5979 CallRuntime(Runtime::kPushBlockContext, 2, instr); | 5979 CallRuntime(Runtime::kPushBlockContext, 2, instr); |
5980 RecordSafepoint(Safepoint::kNoLazyDeopt); | 5980 RecordSafepoint(Safepoint::kNoLazyDeopt); |
5981 } | 5981 } |
5982 | 5982 |
5983 | 5983 |
5984 #undef __ | 5984 #undef __ |
5985 | 5985 |
5986 } } // namespace v8::internal | 5986 } } // namespace v8::internal |
OLD | NEW |