Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(835)

Side by Side Diff: src/arm/lithium-codegen-arm.cc

Issue 559143003: Thread the Lithium instruction down to DeoptimizeIf and friends. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Rebased Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/arm/lithium-codegen-arm.h ('k') | src/arm64/lithium-codegen-arm64.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 828 matching lines...) Expand 10 before | Expand all | Expand 10 after
839 int deoptimization_index = deoptimizations_.length(); 839 int deoptimization_index = deoptimizations_.length();
840 int pc_offset = masm()->pc_offset(); 840 int pc_offset = masm()->pc_offset();
841 environment->Register(deoptimization_index, 841 environment->Register(deoptimization_index,
842 translation.index(), 842 translation.index(),
843 (mode == Safepoint::kLazyDeopt) ? pc_offset : -1); 843 (mode == Safepoint::kLazyDeopt) ? pc_offset : -1);
844 deoptimizations_.Add(environment, zone()); 844 deoptimizations_.Add(environment, zone());
845 } 845 }
846 } 846 }
847 847
848 848
849 void LCodeGen::DeoptimizeIf(Condition condition, 849 void LCodeGen::DeoptimizeIf(Condition condition, LInstruction* instr,
850 LEnvironment* environment,
851 Deoptimizer::BailoutType bailout_type) { 850 Deoptimizer::BailoutType bailout_type) {
851 LEnvironment* environment = instr->environment();
852 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); 852 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
853 DCHECK(environment->HasBeenRegistered()); 853 DCHECK(environment->HasBeenRegistered());
854 int id = environment->deoptimization_index(); 854 int id = environment->deoptimization_index();
855 DCHECK(info()->IsOptimizing() || info()->IsStub()); 855 DCHECK(info()->IsOptimizing() || info()->IsStub());
856 Address entry = 856 Address entry =
857 Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type); 857 Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type);
858 if (entry == NULL) { 858 if (entry == NULL) {
859 Abort(kBailoutWasNotPrepared); 859 Abort(kBailoutWasNotPrepared);
860 return; 860 return;
861 } 861 }
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
915 Deoptimizer::JumpTableEntry table_entry(entry, 915 Deoptimizer::JumpTableEntry table_entry(entry,
916 bailout_type, 916 bailout_type,
917 !frame_is_built_); 917 !frame_is_built_);
918 deopt_jump_table_.Add(table_entry, zone()); 918 deopt_jump_table_.Add(table_entry, zone());
919 } 919 }
920 __ b(condition, &deopt_jump_table_.last().label); 920 __ b(condition, &deopt_jump_table_.last().label);
921 } 921 }
922 } 922 }
923 923
924 924
925 void LCodeGen::DeoptimizeIf(Condition condition, 925 void LCodeGen::DeoptimizeIf(Condition condition, LInstruction* instr) {
926 LEnvironment* environment) {
927 Deoptimizer::BailoutType bailout_type = info()->IsStub() 926 Deoptimizer::BailoutType bailout_type = info()->IsStub()
928 ? Deoptimizer::LAZY 927 ? Deoptimizer::LAZY
929 : Deoptimizer::EAGER; 928 : Deoptimizer::EAGER;
930 DeoptimizeIf(condition, environment, bailout_type); 929 DeoptimizeIf(condition, instr, bailout_type);
931 } 930 }
932 931
933 932
934 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { 933 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) {
935 int length = deoptimizations_.length(); 934 int length = deoptimizations_.length();
936 if (length == 0) return; 935 if (length == 0) return;
937 Handle<DeoptimizationInputData> data = 936 Handle<DeoptimizationInputData> data =
938 DeoptimizationInputData::New(isolate(), length, TENURED); 937 DeoptimizationInputData::New(isolate(), length, TENURED);
939 938
940 Handle<ByteArray> translations = 939 Handle<ByteArray> translations =
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after
1155 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); 1154 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1);
1156 Label dividend_is_not_negative, done; 1155 Label dividend_is_not_negative, done;
1157 if (hmod->CheckFlag(HValue::kLeftCanBeNegative)) { 1156 if (hmod->CheckFlag(HValue::kLeftCanBeNegative)) {
1158 __ cmp(dividend, Operand::Zero()); 1157 __ cmp(dividend, Operand::Zero());
1159 __ b(pl, &dividend_is_not_negative); 1158 __ b(pl, &dividend_is_not_negative);
1160 // Note that this is correct even for kMinInt operands. 1159 // Note that this is correct even for kMinInt operands.
1161 __ rsb(dividend, dividend, Operand::Zero()); 1160 __ rsb(dividend, dividend, Operand::Zero());
1162 __ and_(dividend, dividend, Operand(mask)); 1161 __ and_(dividend, dividend, Operand(mask));
1163 __ rsb(dividend, dividend, Operand::Zero(), SetCC); 1162 __ rsb(dividend, dividend, Operand::Zero(), SetCC);
1164 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { 1163 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1165 DeoptimizeIf(eq, instr->environment()); 1164 DeoptimizeIf(eq, instr);
1166 } 1165 }
1167 __ b(&done); 1166 __ b(&done);
1168 } 1167 }
1169 1168
1170 __ bind(&dividend_is_not_negative); 1169 __ bind(&dividend_is_not_negative);
1171 __ and_(dividend, dividend, Operand(mask)); 1170 __ and_(dividend, dividend, Operand(mask));
1172 __ bind(&done); 1171 __ bind(&done);
1173 } 1172 }
1174 1173
1175 1174
1176 void LCodeGen::DoModByConstI(LModByConstI* instr) { 1175 void LCodeGen::DoModByConstI(LModByConstI* instr) {
1177 Register dividend = ToRegister(instr->dividend()); 1176 Register dividend = ToRegister(instr->dividend());
1178 int32_t divisor = instr->divisor(); 1177 int32_t divisor = instr->divisor();
1179 Register result = ToRegister(instr->result()); 1178 Register result = ToRegister(instr->result());
1180 DCHECK(!dividend.is(result)); 1179 DCHECK(!dividend.is(result));
1181 1180
1182 if (divisor == 0) { 1181 if (divisor == 0) {
1183 DeoptimizeIf(al, instr->environment()); 1182 DeoptimizeIf(al, instr);
1184 return; 1183 return;
1185 } 1184 }
1186 1185
1187 __ TruncatingDiv(result, dividend, Abs(divisor)); 1186 __ TruncatingDiv(result, dividend, Abs(divisor));
1188 __ mov(ip, Operand(Abs(divisor))); 1187 __ mov(ip, Operand(Abs(divisor)));
1189 __ smull(result, ip, result, ip); 1188 __ smull(result, ip, result, ip);
1190 __ sub(result, dividend, result, SetCC); 1189 __ sub(result, dividend, result, SetCC);
1191 1190
1192 // Check for negative zero. 1191 // Check for negative zero.
1193 HMod* hmod = instr->hydrogen(); 1192 HMod* hmod = instr->hydrogen();
1194 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { 1193 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1195 Label remainder_not_zero; 1194 Label remainder_not_zero;
1196 __ b(ne, &remainder_not_zero); 1195 __ b(ne, &remainder_not_zero);
1197 __ cmp(dividend, Operand::Zero()); 1196 __ cmp(dividend, Operand::Zero());
1198 DeoptimizeIf(lt, instr->environment()); 1197 DeoptimizeIf(lt, instr);
1199 __ bind(&remainder_not_zero); 1198 __ bind(&remainder_not_zero);
1200 } 1199 }
1201 } 1200 }
1202 1201
1203 1202
1204 void LCodeGen::DoModI(LModI* instr) { 1203 void LCodeGen::DoModI(LModI* instr) {
1205 HMod* hmod = instr->hydrogen(); 1204 HMod* hmod = instr->hydrogen();
1206 if (CpuFeatures::IsSupported(SUDIV)) { 1205 if (CpuFeatures::IsSupported(SUDIV)) {
1207 CpuFeatureScope scope(masm(), SUDIV); 1206 CpuFeatureScope scope(masm(), SUDIV);
1208 1207
1209 Register left_reg = ToRegister(instr->left()); 1208 Register left_reg = ToRegister(instr->left());
1210 Register right_reg = ToRegister(instr->right()); 1209 Register right_reg = ToRegister(instr->right());
1211 Register result_reg = ToRegister(instr->result()); 1210 Register result_reg = ToRegister(instr->result());
1212 1211
1213 Label done; 1212 Label done;
1214 // Check for x % 0, sdiv might signal an exception. We have to deopt in this 1213 // Check for x % 0, sdiv might signal an exception. We have to deopt in this
1215 // case because we can't return a NaN. 1214 // case because we can't return a NaN.
1216 if (hmod->CheckFlag(HValue::kCanBeDivByZero)) { 1215 if (hmod->CheckFlag(HValue::kCanBeDivByZero)) {
1217 __ cmp(right_reg, Operand::Zero()); 1216 __ cmp(right_reg, Operand::Zero());
1218 DeoptimizeIf(eq, instr->environment()); 1217 DeoptimizeIf(eq, instr);
1219 } 1218 }
1220 1219
1221 // Check for kMinInt % -1, sdiv will return kMinInt, which is not what we 1220 // Check for kMinInt % -1, sdiv will return kMinInt, which is not what we
1222 // want. We have to deopt if we care about -0, because we can't return that. 1221 // want. We have to deopt if we care about -0, because we can't return that.
1223 if (hmod->CheckFlag(HValue::kCanOverflow)) { 1222 if (hmod->CheckFlag(HValue::kCanOverflow)) {
1224 Label no_overflow_possible; 1223 Label no_overflow_possible;
1225 __ cmp(left_reg, Operand(kMinInt)); 1224 __ cmp(left_reg, Operand(kMinInt));
1226 __ b(ne, &no_overflow_possible); 1225 __ b(ne, &no_overflow_possible);
1227 __ cmp(right_reg, Operand(-1)); 1226 __ cmp(right_reg, Operand(-1));
1228 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { 1227 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1229 DeoptimizeIf(eq, instr->environment()); 1228 DeoptimizeIf(eq, instr);
1230 } else { 1229 } else {
1231 __ b(ne, &no_overflow_possible); 1230 __ b(ne, &no_overflow_possible);
1232 __ mov(result_reg, Operand::Zero()); 1231 __ mov(result_reg, Operand::Zero());
1233 __ jmp(&done); 1232 __ jmp(&done);
1234 } 1233 }
1235 __ bind(&no_overflow_possible); 1234 __ bind(&no_overflow_possible);
1236 } 1235 }
1237 1236
1238 // For 'r3 = r1 % r2' we can have the following ARM code: 1237 // For 'r3 = r1 % r2' we can have the following ARM code:
1239 // sdiv r3, r1, r2 1238 // sdiv r3, r1, r2
1240 // mls r3, r3, r2, r1 1239 // mls r3, r3, r2, r1
1241 1240
1242 __ sdiv(result_reg, left_reg, right_reg); 1241 __ sdiv(result_reg, left_reg, right_reg);
1243 __ Mls(result_reg, result_reg, right_reg, left_reg); 1242 __ Mls(result_reg, result_reg, right_reg, left_reg);
1244 1243
1245 // If we care about -0, test if the dividend is <0 and the result is 0. 1244 // If we care about -0, test if the dividend is <0 and the result is 0.
1246 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { 1245 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1247 __ cmp(result_reg, Operand::Zero()); 1246 __ cmp(result_reg, Operand::Zero());
1248 __ b(ne, &done); 1247 __ b(ne, &done);
1249 __ cmp(left_reg, Operand::Zero()); 1248 __ cmp(left_reg, Operand::Zero());
1250 DeoptimizeIf(lt, instr->environment()); 1249 DeoptimizeIf(lt, instr);
1251 } 1250 }
1252 __ bind(&done); 1251 __ bind(&done);
1253 1252
1254 } else { 1253 } else {
1255 // General case, without any SDIV support. 1254 // General case, without any SDIV support.
1256 Register left_reg = ToRegister(instr->left()); 1255 Register left_reg = ToRegister(instr->left());
1257 Register right_reg = ToRegister(instr->right()); 1256 Register right_reg = ToRegister(instr->right());
1258 Register result_reg = ToRegister(instr->result()); 1257 Register result_reg = ToRegister(instr->result());
1259 Register scratch = scratch0(); 1258 Register scratch = scratch0();
1260 DCHECK(!scratch.is(left_reg)); 1259 DCHECK(!scratch.is(left_reg));
1261 DCHECK(!scratch.is(right_reg)); 1260 DCHECK(!scratch.is(right_reg));
1262 DCHECK(!scratch.is(result_reg)); 1261 DCHECK(!scratch.is(result_reg));
1263 DwVfpRegister dividend = ToDoubleRegister(instr->temp()); 1262 DwVfpRegister dividend = ToDoubleRegister(instr->temp());
1264 DwVfpRegister divisor = ToDoubleRegister(instr->temp2()); 1263 DwVfpRegister divisor = ToDoubleRegister(instr->temp2());
1265 DCHECK(!divisor.is(dividend)); 1264 DCHECK(!divisor.is(dividend));
1266 LowDwVfpRegister quotient = double_scratch0(); 1265 LowDwVfpRegister quotient = double_scratch0();
1267 DCHECK(!quotient.is(dividend)); 1266 DCHECK(!quotient.is(dividend));
1268 DCHECK(!quotient.is(divisor)); 1267 DCHECK(!quotient.is(divisor));
1269 1268
1270 Label done; 1269 Label done;
1271 // Check for x % 0, we have to deopt in this case because we can't return a 1270 // Check for x % 0, we have to deopt in this case because we can't return a
1272 // NaN. 1271 // NaN.
1273 if (hmod->CheckFlag(HValue::kCanBeDivByZero)) { 1272 if (hmod->CheckFlag(HValue::kCanBeDivByZero)) {
1274 __ cmp(right_reg, Operand::Zero()); 1273 __ cmp(right_reg, Operand::Zero());
1275 DeoptimizeIf(eq, instr->environment()); 1274 DeoptimizeIf(eq, instr);
1276 } 1275 }
1277 1276
1278 __ Move(result_reg, left_reg); 1277 __ Move(result_reg, left_reg);
1279 // Load the arguments in VFP registers. The divisor value is preloaded 1278 // Load the arguments in VFP registers. The divisor value is preloaded
1280 // before. Be careful that 'right_reg' is only live on entry. 1279 // before. Be careful that 'right_reg' is only live on entry.
1281 // TODO(svenpanne) The last comments seems to be wrong nowadays. 1280 // TODO(svenpanne) The last comments seems to be wrong nowadays.
1282 __ vmov(double_scratch0().low(), left_reg); 1281 __ vmov(double_scratch0().low(), left_reg);
1283 __ vcvt_f64_s32(dividend, double_scratch0().low()); 1282 __ vcvt_f64_s32(dividend, double_scratch0().low());
1284 __ vmov(double_scratch0().low(), right_reg); 1283 __ vmov(double_scratch0().low(), right_reg);
1285 __ vcvt_f64_s32(divisor, double_scratch0().low()); 1284 __ vcvt_f64_s32(divisor, double_scratch0().low());
1286 1285
1287 // We do not care about the sign of the divisor. Note that we still handle 1286 // We do not care about the sign of the divisor. Note that we still handle
1288 // the kMinInt % -1 case correctly, though. 1287 // the kMinInt % -1 case correctly, though.
1289 __ vabs(divisor, divisor); 1288 __ vabs(divisor, divisor);
1290 // Compute the quotient and round it to a 32bit integer. 1289 // Compute the quotient and round it to a 32bit integer.
1291 __ vdiv(quotient, dividend, divisor); 1290 __ vdiv(quotient, dividend, divisor);
1292 __ vcvt_s32_f64(quotient.low(), quotient); 1291 __ vcvt_s32_f64(quotient.low(), quotient);
1293 __ vcvt_f64_s32(quotient, quotient.low()); 1292 __ vcvt_f64_s32(quotient, quotient.low());
1294 1293
1295 // Compute the remainder in result. 1294 // Compute the remainder in result.
1296 __ vmul(double_scratch0(), divisor, quotient); 1295 __ vmul(double_scratch0(), divisor, quotient);
1297 __ vcvt_s32_f64(double_scratch0().low(), double_scratch0()); 1296 __ vcvt_s32_f64(double_scratch0().low(), double_scratch0());
1298 __ vmov(scratch, double_scratch0().low()); 1297 __ vmov(scratch, double_scratch0().low());
1299 __ sub(result_reg, left_reg, scratch, SetCC); 1298 __ sub(result_reg, left_reg, scratch, SetCC);
1300 1299
1301 // If we care about -0, test if the dividend is <0 and the result is 0. 1300 // If we care about -0, test if the dividend is <0 and the result is 0.
1302 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { 1301 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1303 __ b(ne, &done); 1302 __ b(ne, &done);
1304 __ cmp(left_reg, Operand::Zero()); 1303 __ cmp(left_reg, Operand::Zero());
1305 DeoptimizeIf(mi, instr->environment()); 1304 DeoptimizeIf(mi, instr);
1306 } 1305 }
1307 __ bind(&done); 1306 __ bind(&done);
1308 } 1307 }
1309 } 1308 }
1310 1309
1311 1310
1312 void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) { 1311 void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) {
1313 Register dividend = ToRegister(instr->dividend()); 1312 Register dividend = ToRegister(instr->dividend());
1314 int32_t divisor = instr->divisor(); 1313 int32_t divisor = instr->divisor();
1315 Register result = ToRegister(instr->result()); 1314 Register result = ToRegister(instr->result());
1316 DCHECK(divisor == kMinInt || base::bits::IsPowerOfTwo32(Abs(divisor))); 1315 DCHECK(divisor == kMinInt || base::bits::IsPowerOfTwo32(Abs(divisor)));
1317 DCHECK(!result.is(dividend)); 1316 DCHECK(!result.is(dividend));
1318 1317
1319 // Check for (0 / -x) that will produce negative zero. 1318 // Check for (0 / -x) that will produce negative zero.
1320 HDiv* hdiv = instr->hydrogen(); 1319 HDiv* hdiv = instr->hydrogen();
1321 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { 1320 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
1322 __ cmp(dividend, Operand::Zero()); 1321 __ cmp(dividend, Operand::Zero());
1323 DeoptimizeIf(eq, instr->environment()); 1322 DeoptimizeIf(eq, instr);
1324 } 1323 }
1325 // Check for (kMinInt / -1). 1324 // Check for (kMinInt / -1).
1326 if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) { 1325 if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) {
1327 __ cmp(dividend, Operand(kMinInt)); 1326 __ cmp(dividend, Operand(kMinInt));
1328 DeoptimizeIf(eq, instr->environment()); 1327 DeoptimizeIf(eq, instr);
1329 } 1328 }
1330 // Deoptimize if remainder will not be 0. 1329 // Deoptimize if remainder will not be 0.
1331 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) && 1330 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) &&
1332 divisor != 1 && divisor != -1) { 1331 divisor != 1 && divisor != -1) {
1333 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); 1332 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1);
1334 __ tst(dividend, Operand(mask)); 1333 __ tst(dividend, Operand(mask));
1335 DeoptimizeIf(ne, instr->environment()); 1334 DeoptimizeIf(ne, instr);
1336 } 1335 }
1337 1336
1338 if (divisor == -1) { // Nice shortcut, not needed for correctness. 1337 if (divisor == -1) { // Nice shortcut, not needed for correctness.
1339 __ rsb(result, dividend, Operand(0)); 1338 __ rsb(result, dividend, Operand(0));
1340 return; 1339 return;
1341 } 1340 }
1342 int32_t shift = WhichPowerOf2Abs(divisor); 1341 int32_t shift = WhichPowerOf2Abs(divisor);
1343 if (shift == 0) { 1342 if (shift == 0) {
1344 __ mov(result, dividend); 1343 __ mov(result, dividend);
1345 } else if (shift == 1) { 1344 } else if (shift == 1) {
1346 __ add(result, dividend, Operand(dividend, LSR, 31)); 1345 __ add(result, dividend, Operand(dividend, LSR, 31));
1347 } else { 1346 } else {
1348 __ mov(result, Operand(dividend, ASR, 31)); 1347 __ mov(result, Operand(dividend, ASR, 31));
1349 __ add(result, dividend, Operand(result, LSR, 32 - shift)); 1348 __ add(result, dividend, Operand(result, LSR, 32 - shift));
1350 } 1349 }
1351 if (shift > 0) __ mov(result, Operand(result, ASR, shift)); 1350 if (shift > 0) __ mov(result, Operand(result, ASR, shift));
1352 if (divisor < 0) __ rsb(result, result, Operand(0)); 1351 if (divisor < 0) __ rsb(result, result, Operand(0));
1353 } 1352 }
1354 1353
1355 1354
1356 void LCodeGen::DoDivByConstI(LDivByConstI* instr) { 1355 void LCodeGen::DoDivByConstI(LDivByConstI* instr) {
1357 Register dividend = ToRegister(instr->dividend()); 1356 Register dividend = ToRegister(instr->dividend());
1358 int32_t divisor = instr->divisor(); 1357 int32_t divisor = instr->divisor();
1359 Register result = ToRegister(instr->result()); 1358 Register result = ToRegister(instr->result());
1360 DCHECK(!dividend.is(result)); 1359 DCHECK(!dividend.is(result));
1361 1360
1362 if (divisor == 0) { 1361 if (divisor == 0) {
1363 DeoptimizeIf(al, instr->environment()); 1362 DeoptimizeIf(al, instr);
1364 return; 1363 return;
1365 } 1364 }
1366 1365
1367 // Check for (0 / -x) that will produce negative zero. 1366 // Check for (0 / -x) that will produce negative zero.
1368 HDiv* hdiv = instr->hydrogen(); 1367 HDiv* hdiv = instr->hydrogen();
1369 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { 1368 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
1370 __ cmp(dividend, Operand::Zero()); 1369 __ cmp(dividend, Operand::Zero());
1371 DeoptimizeIf(eq, instr->environment()); 1370 DeoptimizeIf(eq, instr);
1372 } 1371 }
1373 1372
1374 __ TruncatingDiv(result, dividend, Abs(divisor)); 1373 __ TruncatingDiv(result, dividend, Abs(divisor));
1375 if (divisor < 0) __ rsb(result, result, Operand::Zero()); 1374 if (divisor < 0) __ rsb(result, result, Operand::Zero());
1376 1375
1377 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) { 1376 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) {
1378 __ mov(ip, Operand(divisor)); 1377 __ mov(ip, Operand(divisor));
1379 __ smull(scratch0(), ip, result, ip); 1378 __ smull(scratch0(), ip, result, ip);
1380 __ sub(scratch0(), scratch0(), dividend, SetCC); 1379 __ sub(scratch0(), scratch0(), dividend, SetCC);
1381 DeoptimizeIf(ne, instr->environment()); 1380 DeoptimizeIf(ne, instr);
1382 } 1381 }
1383 } 1382 }
1384 1383
1385 1384
1386 // TODO(svenpanne) Refactor this to avoid code duplication with DoFlooringDivI. 1385 // TODO(svenpanne) Refactor this to avoid code duplication with DoFlooringDivI.
1387 void LCodeGen::DoDivI(LDivI* instr) { 1386 void LCodeGen::DoDivI(LDivI* instr) {
1388 HBinaryOperation* hdiv = instr->hydrogen(); 1387 HBinaryOperation* hdiv = instr->hydrogen();
1389 Register dividend = ToRegister(instr->dividend()); 1388 Register dividend = ToRegister(instr->dividend());
1390 Register divisor = ToRegister(instr->divisor()); 1389 Register divisor = ToRegister(instr->divisor());
1391 Register result = ToRegister(instr->result()); 1390 Register result = ToRegister(instr->result());
1392 1391
1393 // Check for x / 0. 1392 // Check for x / 0.
1394 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { 1393 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
1395 __ cmp(divisor, Operand::Zero()); 1394 __ cmp(divisor, Operand::Zero());
1396 DeoptimizeIf(eq, instr->environment()); 1395 DeoptimizeIf(eq, instr);
1397 } 1396 }
1398 1397
1399 // Check for (0 / -x) that will produce negative zero. 1398 // Check for (0 / -x) that will produce negative zero.
1400 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { 1399 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) {
1401 Label positive; 1400 Label positive;
1402 if (!instr->hydrogen_value()->CheckFlag(HValue::kCanBeDivByZero)) { 1401 if (!instr->hydrogen_value()->CheckFlag(HValue::kCanBeDivByZero)) {
1403 // Do the test only if it hadn't be done above. 1402 // Do the test only if it hadn't be done above.
1404 __ cmp(divisor, Operand::Zero()); 1403 __ cmp(divisor, Operand::Zero());
1405 } 1404 }
1406 __ b(pl, &positive); 1405 __ b(pl, &positive);
1407 __ cmp(dividend, Operand::Zero()); 1406 __ cmp(dividend, Operand::Zero());
1408 DeoptimizeIf(eq, instr->environment()); 1407 DeoptimizeIf(eq, instr);
1409 __ bind(&positive); 1408 __ bind(&positive);
1410 } 1409 }
1411 1410
1412 // Check for (kMinInt / -1). 1411 // Check for (kMinInt / -1).
1413 if (hdiv->CheckFlag(HValue::kCanOverflow) && 1412 if (hdiv->CheckFlag(HValue::kCanOverflow) &&
1414 (!CpuFeatures::IsSupported(SUDIV) || 1413 (!CpuFeatures::IsSupported(SUDIV) ||
1415 !hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32))) { 1414 !hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32))) {
1416 // We don't need to check for overflow when truncating with sdiv 1415 // We don't need to check for overflow when truncating with sdiv
1417 // support because, on ARM, sdiv kMinInt, -1 -> kMinInt. 1416 // support because, on ARM, sdiv kMinInt, -1 -> kMinInt.
1418 __ cmp(dividend, Operand(kMinInt)); 1417 __ cmp(dividend, Operand(kMinInt));
1419 __ cmp(divisor, Operand(-1), eq); 1418 __ cmp(divisor, Operand(-1), eq);
1420 DeoptimizeIf(eq, instr->environment()); 1419 DeoptimizeIf(eq, instr);
1421 } 1420 }
1422 1421
1423 if (CpuFeatures::IsSupported(SUDIV)) { 1422 if (CpuFeatures::IsSupported(SUDIV)) {
1424 CpuFeatureScope scope(masm(), SUDIV); 1423 CpuFeatureScope scope(masm(), SUDIV);
1425 __ sdiv(result, dividend, divisor); 1424 __ sdiv(result, dividend, divisor);
1426 } else { 1425 } else {
1427 DoubleRegister vleft = ToDoubleRegister(instr->temp()); 1426 DoubleRegister vleft = ToDoubleRegister(instr->temp());
1428 DoubleRegister vright = double_scratch0(); 1427 DoubleRegister vright = double_scratch0();
1429 __ vmov(double_scratch0().low(), dividend); 1428 __ vmov(double_scratch0().low(), dividend);
1430 __ vcvt_f64_s32(vleft, double_scratch0().low()); 1429 __ vcvt_f64_s32(vleft, double_scratch0().low());
1431 __ vmov(double_scratch0().low(), divisor); 1430 __ vmov(double_scratch0().low(), divisor);
1432 __ vcvt_f64_s32(vright, double_scratch0().low()); 1431 __ vcvt_f64_s32(vright, double_scratch0().low());
1433 __ vdiv(vleft, vleft, vright); // vleft now contains the result. 1432 __ vdiv(vleft, vleft, vright); // vleft now contains the result.
1434 __ vcvt_s32_f64(double_scratch0().low(), vleft); 1433 __ vcvt_s32_f64(double_scratch0().low(), vleft);
1435 __ vmov(result, double_scratch0().low()); 1434 __ vmov(result, double_scratch0().low());
1436 } 1435 }
1437 1436
1438 if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { 1437 if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
1439 // Compute remainder and deopt if it's not zero. 1438 // Compute remainder and deopt if it's not zero.
1440 Register remainder = scratch0(); 1439 Register remainder = scratch0();
1441 __ Mls(remainder, result, divisor, dividend); 1440 __ Mls(remainder, result, divisor, dividend);
1442 __ cmp(remainder, Operand::Zero()); 1441 __ cmp(remainder, Operand::Zero());
1443 DeoptimizeIf(ne, instr->environment()); 1442 DeoptimizeIf(ne, instr);
1444 } 1443 }
1445 } 1444 }
1446 1445
1447 1446
1448 void LCodeGen::DoMultiplyAddD(LMultiplyAddD* instr) { 1447 void LCodeGen::DoMultiplyAddD(LMultiplyAddD* instr) {
1449 DwVfpRegister addend = ToDoubleRegister(instr->addend()); 1448 DwVfpRegister addend = ToDoubleRegister(instr->addend());
1450 DwVfpRegister multiplier = ToDoubleRegister(instr->multiplier()); 1449 DwVfpRegister multiplier = ToDoubleRegister(instr->multiplier());
1451 DwVfpRegister multiplicand = ToDoubleRegister(instr->multiplicand()); 1450 DwVfpRegister multiplicand = ToDoubleRegister(instr->multiplicand());
1452 1451
1453 // This is computed in-place. 1452 // This is computed in-place.
(...skipping 30 matching lines...) Expand all
1484 // can simply do an arithmetic right shift. 1483 // can simply do an arithmetic right shift.
1485 int32_t shift = WhichPowerOf2Abs(divisor); 1484 int32_t shift = WhichPowerOf2Abs(divisor);
1486 if (divisor > 1) { 1485 if (divisor > 1) {
1487 __ mov(result, Operand(dividend, ASR, shift)); 1486 __ mov(result, Operand(dividend, ASR, shift));
1488 return; 1487 return;
1489 } 1488 }
1490 1489
1491 // If the divisor is negative, we have to negate and handle edge cases. 1490 // If the divisor is negative, we have to negate and handle edge cases.
1492 __ rsb(result, dividend, Operand::Zero(), SetCC); 1491 __ rsb(result, dividend, Operand::Zero(), SetCC);
1493 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 1492 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
1494 DeoptimizeIf(eq, instr->environment()); 1493 DeoptimizeIf(eq, instr);
1495 } 1494 }
1496 1495
1497 // Dividing by -1 is basically negation, unless we overflow. 1496 // Dividing by -1 is basically negation, unless we overflow.
1498 if (divisor == -1) { 1497 if (divisor == -1) {
1499 if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { 1498 if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) {
1500 DeoptimizeIf(vs, instr->environment()); 1499 DeoptimizeIf(vs, instr);
1501 } 1500 }
1502 return; 1501 return;
1503 } 1502 }
1504 1503
1505 // If the negation could not overflow, simply shifting is OK. 1504 // If the negation could not overflow, simply shifting is OK.
1506 if (!instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { 1505 if (!instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) {
1507 __ mov(result, Operand(result, ASR, shift)); 1506 __ mov(result, Operand(result, ASR, shift));
1508 return; 1507 return;
1509 } 1508 }
1510 1509
1511 __ mov(result, Operand(kMinInt / divisor), LeaveCC, vs); 1510 __ mov(result, Operand(kMinInt / divisor), LeaveCC, vs);
1512 __ mov(result, Operand(result, ASR, shift), LeaveCC, vc); 1511 __ mov(result, Operand(result, ASR, shift), LeaveCC, vc);
1513 } 1512 }
1514 1513
1515 1514
1516 void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) { 1515 void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) {
1517 Register dividend = ToRegister(instr->dividend()); 1516 Register dividend = ToRegister(instr->dividend());
1518 int32_t divisor = instr->divisor(); 1517 int32_t divisor = instr->divisor();
1519 Register result = ToRegister(instr->result()); 1518 Register result = ToRegister(instr->result());
1520 DCHECK(!dividend.is(result)); 1519 DCHECK(!dividend.is(result));
1521 1520
1522 if (divisor == 0) { 1521 if (divisor == 0) {
1523 DeoptimizeIf(al, instr->environment()); 1522 DeoptimizeIf(al, instr);
1524 return; 1523 return;
1525 } 1524 }
1526 1525
1527 // Check for (0 / -x) that will produce negative zero. 1526 // Check for (0 / -x) that will produce negative zero.
1528 HMathFloorOfDiv* hdiv = instr->hydrogen(); 1527 HMathFloorOfDiv* hdiv = instr->hydrogen();
1529 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { 1528 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
1530 __ cmp(dividend, Operand::Zero()); 1529 __ cmp(dividend, Operand::Zero());
1531 DeoptimizeIf(eq, instr->environment()); 1530 DeoptimizeIf(eq, instr);
1532 } 1531 }
1533 1532
1534 // Easy case: We need no dynamic check for the dividend and the flooring 1533 // Easy case: We need no dynamic check for the dividend and the flooring
1535 // division is the same as the truncating division. 1534 // division is the same as the truncating division.
1536 if ((divisor > 0 && !hdiv->CheckFlag(HValue::kLeftCanBeNegative)) || 1535 if ((divisor > 0 && !hdiv->CheckFlag(HValue::kLeftCanBeNegative)) ||
1537 (divisor < 0 && !hdiv->CheckFlag(HValue::kLeftCanBePositive))) { 1536 (divisor < 0 && !hdiv->CheckFlag(HValue::kLeftCanBePositive))) {
1538 __ TruncatingDiv(result, dividend, Abs(divisor)); 1537 __ TruncatingDiv(result, dividend, Abs(divisor));
1539 if (divisor < 0) __ rsb(result, result, Operand::Zero()); 1538 if (divisor < 0) __ rsb(result, result, Operand::Zero());
1540 return; 1539 return;
1541 } 1540 }
(...skipping 20 matching lines...) Expand all
1562 // TODO(svenpanne) Refactor this to avoid code duplication with DoDivI. 1561 // TODO(svenpanne) Refactor this to avoid code duplication with DoDivI.
1563 void LCodeGen::DoFlooringDivI(LFlooringDivI* instr) { 1562 void LCodeGen::DoFlooringDivI(LFlooringDivI* instr) {
1564 HBinaryOperation* hdiv = instr->hydrogen(); 1563 HBinaryOperation* hdiv = instr->hydrogen();
1565 Register left = ToRegister(instr->dividend()); 1564 Register left = ToRegister(instr->dividend());
1566 Register right = ToRegister(instr->divisor()); 1565 Register right = ToRegister(instr->divisor());
1567 Register result = ToRegister(instr->result()); 1566 Register result = ToRegister(instr->result());
1568 1567
1569 // Check for x / 0. 1568 // Check for x / 0.
1570 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { 1569 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
1571 __ cmp(right, Operand::Zero()); 1570 __ cmp(right, Operand::Zero());
1572 DeoptimizeIf(eq, instr->environment()); 1571 DeoptimizeIf(eq, instr);
1573 } 1572 }
1574 1573
1575 // Check for (0 / -x) that will produce negative zero. 1574 // Check for (0 / -x) that will produce negative zero.
1576 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { 1575 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) {
1577 Label positive; 1576 Label positive;
1578 if (!instr->hydrogen_value()->CheckFlag(HValue::kCanBeDivByZero)) { 1577 if (!instr->hydrogen_value()->CheckFlag(HValue::kCanBeDivByZero)) {
1579 // Do the test only if it hadn't be done above. 1578 // Do the test only if it hadn't be done above.
1580 __ cmp(right, Operand::Zero()); 1579 __ cmp(right, Operand::Zero());
1581 } 1580 }
1582 __ b(pl, &positive); 1581 __ b(pl, &positive);
1583 __ cmp(left, Operand::Zero()); 1582 __ cmp(left, Operand::Zero());
1584 DeoptimizeIf(eq, instr->environment()); 1583 DeoptimizeIf(eq, instr);
1585 __ bind(&positive); 1584 __ bind(&positive);
1586 } 1585 }
1587 1586
1588 // Check for (kMinInt / -1). 1587 // Check for (kMinInt / -1).
1589 if (hdiv->CheckFlag(HValue::kCanOverflow) && 1588 if (hdiv->CheckFlag(HValue::kCanOverflow) &&
1590 (!CpuFeatures::IsSupported(SUDIV) || 1589 (!CpuFeatures::IsSupported(SUDIV) ||
1591 !hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32))) { 1590 !hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32))) {
1592 // We don't need to check for overflow when truncating with sdiv 1591 // We don't need to check for overflow when truncating with sdiv
1593 // support because, on ARM, sdiv kMinInt, -1 -> kMinInt. 1592 // support because, on ARM, sdiv kMinInt, -1 -> kMinInt.
1594 __ cmp(left, Operand(kMinInt)); 1593 __ cmp(left, Operand(kMinInt));
1595 __ cmp(right, Operand(-1), eq); 1594 __ cmp(right, Operand(-1), eq);
1596 DeoptimizeIf(eq, instr->environment()); 1595 DeoptimizeIf(eq, instr);
1597 } 1596 }
1598 1597
1599 if (CpuFeatures::IsSupported(SUDIV)) { 1598 if (CpuFeatures::IsSupported(SUDIV)) {
1600 CpuFeatureScope scope(masm(), SUDIV); 1599 CpuFeatureScope scope(masm(), SUDIV);
1601 __ sdiv(result, left, right); 1600 __ sdiv(result, left, right);
1602 } else { 1601 } else {
1603 DoubleRegister vleft = ToDoubleRegister(instr->temp()); 1602 DoubleRegister vleft = ToDoubleRegister(instr->temp());
1604 DoubleRegister vright = double_scratch0(); 1603 DoubleRegister vright = double_scratch0();
1605 __ vmov(double_scratch0().low(), left); 1604 __ vmov(double_scratch0().low(), left);
1606 __ vcvt_f64_s32(vleft, double_scratch0().low()); 1605 __ vcvt_f64_s32(vleft, double_scratch0().low());
(...skipping 25 matching lines...) Expand all
1632 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero); 1631 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero);
1633 bool overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); 1632 bool overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
1634 1633
1635 if (right_op->IsConstantOperand()) { 1634 if (right_op->IsConstantOperand()) {
1636 int32_t constant = ToInteger32(LConstantOperand::cast(right_op)); 1635 int32_t constant = ToInteger32(LConstantOperand::cast(right_op));
1637 1636
1638 if (bailout_on_minus_zero && (constant < 0)) { 1637 if (bailout_on_minus_zero && (constant < 0)) {
1639 // The case of a null constant will be handled separately. 1638 // The case of a null constant will be handled separately.
1640 // If constant is negative and left is null, the result should be -0. 1639 // If constant is negative and left is null, the result should be -0.
1641 __ cmp(left, Operand::Zero()); 1640 __ cmp(left, Operand::Zero());
1642 DeoptimizeIf(eq, instr->environment()); 1641 DeoptimizeIf(eq, instr);
1643 } 1642 }
1644 1643
1645 switch (constant) { 1644 switch (constant) {
1646 case -1: 1645 case -1:
1647 if (overflow) { 1646 if (overflow) {
1648 __ rsb(result, left, Operand::Zero(), SetCC); 1647 __ rsb(result, left, Operand::Zero(), SetCC);
1649 DeoptimizeIf(vs, instr->environment()); 1648 DeoptimizeIf(vs, instr);
1650 } else { 1649 } else {
1651 __ rsb(result, left, Operand::Zero()); 1650 __ rsb(result, left, Operand::Zero());
1652 } 1651 }
1653 break; 1652 break;
1654 case 0: 1653 case 0:
1655 if (bailout_on_minus_zero) { 1654 if (bailout_on_minus_zero) {
1656 // If left is strictly negative and the constant is null, the 1655 // If left is strictly negative and the constant is null, the
1657 // result is -0. Deoptimize if required, otherwise return 0. 1656 // result is -0. Deoptimize if required, otherwise return 0.
1658 __ cmp(left, Operand::Zero()); 1657 __ cmp(left, Operand::Zero());
1659 DeoptimizeIf(mi, instr->environment()); 1658 DeoptimizeIf(mi, instr);
1660 } 1659 }
1661 __ mov(result, Operand::Zero()); 1660 __ mov(result, Operand::Zero());
1662 break; 1661 break;
1663 case 1: 1662 case 1:
1664 __ Move(result, left); 1663 __ Move(result, left);
1665 break; 1664 break;
1666 default: 1665 default:
1667 // Multiplying by powers of two and powers of two plus or minus 1666 // Multiplying by powers of two and powers of two plus or minus
1668 // one can be done faster with shifted operands. 1667 // one can be done faster with shifted operands.
1669 // For other constants we emit standard code. 1668 // For other constants we emit standard code.
(...skipping 29 matching lines...) Expand all
1699 if (overflow) { 1698 if (overflow) {
1700 Register scratch = scratch0(); 1699 Register scratch = scratch0();
1701 // scratch:result = left * right. 1700 // scratch:result = left * right.
1702 if (instr->hydrogen()->representation().IsSmi()) { 1701 if (instr->hydrogen()->representation().IsSmi()) {
1703 __ SmiUntag(result, left); 1702 __ SmiUntag(result, left);
1704 __ smull(result, scratch, result, right); 1703 __ smull(result, scratch, result, right);
1705 } else { 1704 } else {
1706 __ smull(result, scratch, left, right); 1705 __ smull(result, scratch, left, right);
1707 } 1706 }
1708 __ cmp(scratch, Operand(result, ASR, 31)); 1707 __ cmp(scratch, Operand(result, ASR, 31));
1709 DeoptimizeIf(ne, instr->environment()); 1708 DeoptimizeIf(ne, instr);
1710 } else { 1709 } else {
1711 if (instr->hydrogen()->representation().IsSmi()) { 1710 if (instr->hydrogen()->representation().IsSmi()) {
1712 __ SmiUntag(result, left); 1711 __ SmiUntag(result, left);
1713 __ mul(result, result, right); 1712 __ mul(result, result, right);
1714 } else { 1713 } else {
1715 __ mul(result, left, right); 1714 __ mul(result, left, right);
1716 } 1715 }
1717 } 1716 }
1718 1717
1719 if (bailout_on_minus_zero) { 1718 if (bailout_on_minus_zero) {
1720 Label done; 1719 Label done;
1721 __ teq(left, Operand(right)); 1720 __ teq(left, Operand(right));
1722 __ b(pl, &done); 1721 __ b(pl, &done);
1723 // Bail out if the result is minus zero. 1722 // Bail out if the result is minus zero.
1724 __ cmp(result, Operand::Zero()); 1723 __ cmp(result, Operand::Zero());
1725 DeoptimizeIf(eq, instr->environment()); 1724 DeoptimizeIf(eq, instr);
1726 __ bind(&done); 1725 __ bind(&done);
1727 } 1726 }
1728 } 1727 }
1729 } 1728 }
1730 1729
1731 1730
1732 void LCodeGen::DoBitI(LBitI* instr) { 1731 void LCodeGen::DoBitI(LBitI* instr) {
1733 LOperand* left_op = instr->left(); 1732 LOperand* left_op = instr->left();
1734 LOperand* right_op = instr->right(); 1733 LOperand* right_op = instr->right();
1735 DCHECK(left_op->IsRegister()); 1734 DCHECK(left_op->IsRegister());
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
1778 switch (instr->op()) { 1777 switch (instr->op()) {
1779 case Token::ROR: 1778 case Token::ROR:
1780 __ mov(result, Operand(left, ROR, scratch)); 1779 __ mov(result, Operand(left, ROR, scratch));
1781 break; 1780 break;
1782 case Token::SAR: 1781 case Token::SAR:
1783 __ mov(result, Operand(left, ASR, scratch)); 1782 __ mov(result, Operand(left, ASR, scratch));
1784 break; 1783 break;
1785 case Token::SHR: 1784 case Token::SHR:
1786 if (instr->can_deopt()) { 1785 if (instr->can_deopt()) {
1787 __ mov(result, Operand(left, LSR, scratch), SetCC); 1786 __ mov(result, Operand(left, LSR, scratch), SetCC);
1788 DeoptimizeIf(mi, instr->environment()); 1787 DeoptimizeIf(mi, instr);
1789 } else { 1788 } else {
1790 __ mov(result, Operand(left, LSR, scratch)); 1789 __ mov(result, Operand(left, LSR, scratch));
1791 } 1790 }
1792 break; 1791 break;
1793 case Token::SHL: 1792 case Token::SHL:
1794 __ mov(result, Operand(left, LSL, scratch)); 1793 __ mov(result, Operand(left, LSL, scratch));
1795 break; 1794 break;
1796 default: 1795 default:
1797 UNREACHABLE(); 1796 UNREACHABLE();
1798 break; 1797 break;
(...skipping 16 matching lines...) Expand all
1815 } else { 1814 } else {
1816 __ Move(result, left); 1815 __ Move(result, left);
1817 } 1816 }
1818 break; 1817 break;
1819 case Token::SHR: 1818 case Token::SHR:
1820 if (shift_count != 0) { 1819 if (shift_count != 0) {
1821 __ mov(result, Operand(left, LSR, shift_count)); 1820 __ mov(result, Operand(left, LSR, shift_count));
1822 } else { 1821 } else {
1823 if (instr->can_deopt()) { 1822 if (instr->can_deopt()) {
1824 __ tst(left, Operand(0x80000000)); 1823 __ tst(left, Operand(0x80000000));
1825 DeoptimizeIf(ne, instr->environment()); 1824 DeoptimizeIf(ne, instr);
1826 } 1825 }
1827 __ Move(result, left); 1826 __ Move(result, left);
1828 } 1827 }
1829 break; 1828 break;
1830 case Token::SHL: 1829 case Token::SHL:
1831 if (shift_count != 0) { 1830 if (shift_count != 0) {
1832 if (instr->hydrogen_value()->representation().IsSmi() && 1831 if (instr->hydrogen_value()->representation().IsSmi() &&
1833 instr->can_deopt()) { 1832 instr->can_deopt()) {
1834 if (shift_count != 1) { 1833 if (shift_count != 1) {
1835 __ mov(result, Operand(left, LSL, shift_count - 1)); 1834 __ mov(result, Operand(left, LSL, shift_count - 1));
1836 __ SmiTag(result, result, SetCC); 1835 __ SmiTag(result, result, SetCC);
1837 } else { 1836 } else {
1838 __ SmiTag(result, left, SetCC); 1837 __ SmiTag(result, left, SetCC);
1839 } 1838 }
1840 DeoptimizeIf(vs, instr->environment()); 1839 DeoptimizeIf(vs, instr);
1841 } else { 1840 } else {
1842 __ mov(result, Operand(left, LSL, shift_count)); 1841 __ mov(result, Operand(left, LSL, shift_count));
1843 } 1842 }
1844 } else { 1843 } else {
1845 __ Move(result, left); 1844 __ Move(result, left);
1846 } 1845 }
1847 break; 1846 break;
1848 default: 1847 default:
1849 UNREACHABLE(); 1848 UNREACHABLE();
1850 break; 1849 break;
(...skipping 11 matching lines...) Expand all
1862 1861
1863 if (right->IsStackSlot()) { 1862 if (right->IsStackSlot()) {
1864 Register right_reg = EmitLoadRegister(right, ip); 1863 Register right_reg = EmitLoadRegister(right, ip);
1865 __ sub(ToRegister(result), ToRegister(left), Operand(right_reg), set_cond); 1864 __ sub(ToRegister(result), ToRegister(left), Operand(right_reg), set_cond);
1866 } else { 1865 } else {
1867 DCHECK(right->IsRegister() || right->IsConstantOperand()); 1866 DCHECK(right->IsRegister() || right->IsConstantOperand());
1868 __ sub(ToRegister(result), ToRegister(left), ToOperand(right), set_cond); 1867 __ sub(ToRegister(result), ToRegister(left), ToOperand(right), set_cond);
1869 } 1868 }
1870 1869
1871 if (can_overflow) { 1870 if (can_overflow) {
1872 DeoptimizeIf(vs, instr->environment()); 1871 DeoptimizeIf(vs, instr);
1873 } 1872 }
1874 } 1873 }
1875 1874
1876 1875
1877 void LCodeGen::DoRSubI(LRSubI* instr) { 1876 void LCodeGen::DoRSubI(LRSubI* instr) {
1878 LOperand* left = instr->left(); 1877 LOperand* left = instr->left();
1879 LOperand* right = instr->right(); 1878 LOperand* right = instr->right();
1880 LOperand* result = instr->result(); 1879 LOperand* result = instr->result();
1881 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); 1880 bool can_overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
1882 SBit set_cond = can_overflow ? SetCC : LeaveCC; 1881 SBit set_cond = can_overflow ? SetCC : LeaveCC;
1883 1882
1884 if (right->IsStackSlot()) { 1883 if (right->IsStackSlot()) {
1885 Register right_reg = EmitLoadRegister(right, ip); 1884 Register right_reg = EmitLoadRegister(right, ip);
1886 __ rsb(ToRegister(result), ToRegister(left), Operand(right_reg), set_cond); 1885 __ rsb(ToRegister(result), ToRegister(left), Operand(right_reg), set_cond);
1887 } else { 1886 } else {
1888 DCHECK(right->IsRegister() || right->IsConstantOperand()); 1887 DCHECK(right->IsRegister() || right->IsConstantOperand());
1889 __ rsb(ToRegister(result), ToRegister(left), ToOperand(right), set_cond); 1888 __ rsb(ToRegister(result), ToRegister(left), ToOperand(right), set_cond);
1890 } 1889 }
1891 1890
1892 if (can_overflow) { 1891 if (can_overflow) {
1893 DeoptimizeIf(vs, instr->environment()); 1892 DeoptimizeIf(vs, instr);
1894 } 1893 }
1895 } 1894 }
1896 1895
1897 1896
1898 void LCodeGen::DoConstantI(LConstantI* instr) { 1897 void LCodeGen::DoConstantI(LConstantI* instr) {
1899 __ mov(ToRegister(instr->result()), Operand(instr->value())); 1898 __ mov(ToRegister(instr->result()), Operand(instr->value()));
1900 } 1899 }
1901 1900
1902 1901
1903 void LCodeGen::DoConstantS(LConstantS* instr) { 1902 void LCodeGen::DoConstantS(LConstantS* instr) {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1937 Register result = ToRegister(instr->result()); 1936 Register result = ToRegister(instr->result());
1938 Register scratch = ToRegister(instr->temp()); 1937 Register scratch = ToRegister(instr->temp());
1939 Smi* index = instr->index(); 1938 Smi* index = instr->index();
1940 Label runtime, done; 1939 Label runtime, done;
1941 DCHECK(object.is(result)); 1940 DCHECK(object.is(result));
1942 DCHECK(object.is(r0)); 1941 DCHECK(object.is(r0));
1943 DCHECK(!scratch.is(scratch0())); 1942 DCHECK(!scratch.is(scratch0()));
1944 DCHECK(!scratch.is(object)); 1943 DCHECK(!scratch.is(object));
1945 1944
1946 __ SmiTst(object); 1945 __ SmiTst(object);
1947 DeoptimizeIf(eq, instr->environment()); 1946 DeoptimizeIf(eq, instr);
1948 __ CompareObjectType(object, scratch, scratch, JS_DATE_TYPE); 1947 __ CompareObjectType(object, scratch, scratch, JS_DATE_TYPE);
1949 DeoptimizeIf(ne, instr->environment()); 1948 DeoptimizeIf(ne, instr);
1950 1949
1951 if (index->value() == 0) { 1950 if (index->value() == 0) {
1952 __ ldr(result, FieldMemOperand(object, JSDate::kValueOffset)); 1951 __ ldr(result, FieldMemOperand(object, JSDate::kValueOffset));
1953 } else { 1952 } else {
1954 if (index->value() < JSDate::kFirstUncachedField) { 1953 if (index->value() < JSDate::kFirstUncachedField) {
1955 ExternalReference stamp = ExternalReference::date_cache_stamp(isolate()); 1954 ExternalReference stamp = ExternalReference::date_cache_stamp(isolate());
1956 __ mov(scratch, Operand(stamp)); 1955 __ mov(scratch, Operand(stamp));
1957 __ ldr(scratch, MemOperand(scratch)); 1956 __ ldr(scratch, MemOperand(scratch));
1958 __ ldr(scratch0(), FieldMemOperand(object, JSDate::kCacheStampOffset)); 1957 __ ldr(scratch0(), FieldMemOperand(object, JSDate::kCacheStampOffset));
1959 __ cmp(scratch, scratch0()); 1958 __ cmp(scratch, scratch0());
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
2056 2055
2057 if (right->IsStackSlot()) { 2056 if (right->IsStackSlot()) {
2058 Register right_reg = EmitLoadRegister(right, ip); 2057 Register right_reg = EmitLoadRegister(right, ip);
2059 __ add(ToRegister(result), ToRegister(left), Operand(right_reg), set_cond); 2058 __ add(ToRegister(result), ToRegister(left), Operand(right_reg), set_cond);
2060 } else { 2059 } else {
2061 DCHECK(right->IsRegister() || right->IsConstantOperand()); 2060 DCHECK(right->IsRegister() || right->IsConstantOperand());
2062 __ add(ToRegister(result), ToRegister(left), ToOperand(right), set_cond); 2061 __ add(ToRegister(result), ToRegister(left), ToOperand(right), set_cond);
2063 } 2062 }
2064 2063
2065 if (can_overflow) { 2064 if (can_overflow) {
2066 DeoptimizeIf(vs, instr->environment()); 2065 DeoptimizeIf(vs, instr);
2067 } 2066 }
2068 } 2067 }
2069 2068
2070 2069
2071 void LCodeGen::DoMathMinMax(LMathMinMax* instr) { 2070 void LCodeGen::DoMathMinMax(LMathMinMax* instr) {
2072 LOperand* left = instr->left(); 2071 LOperand* left = instr->left();
2073 LOperand* right = instr->right(); 2072 LOperand* right = instr->right();
2074 HMathMinMax::Operation operation = instr->hydrogen()->operation(); 2073 HMathMinMax::Operation operation = instr->hydrogen()->operation();
2075 if (instr->hydrogen()->representation().IsSmiOrInteger32()) { 2074 if (instr->hydrogen()->representation().IsSmiOrInteger32()) {
2076 Condition condition = (operation == HMathMinMax::kMathMin) ? le : ge; 2075 Condition condition = (operation == HMathMinMax::kMathMin) ? le : ge;
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after
2282 } 2281 }
2283 2282
2284 if (expected.Contains(ToBooleanStub::SMI)) { 2283 if (expected.Contains(ToBooleanStub::SMI)) {
2285 // Smis: 0 -> false, all other -> true. 2284 // Smis: 0 -> false, all other -> true.
2286 __ cmp(reg, Operand::Zero()); 2285 __ cmp(reg, Operand::Zero());
2287 __ b(eq, instr->FalseLabel(chunk_)); 2286 __ b(eq, instr->FalseLabel(chunk_));
2288 __ JumpIfSmi(reg, instr->TrueLabel(chunk_)); 2287 __ JumpIfSmi(reg, instr->TrueLabel(chunk_));
2289 } else if (expected.NeedsMap()) { 2288 } else if (expected.NeedsMap()) {
2290 // If we need a map later and have a Smi -> deopt. 2289 // If we need a map later and have a Smi -> deopt.
2291 __ SmiTst(reg); 2290 __ SmiTst(reg);
2292 DeoptimizeIf(eq, instr->environment()); 2291 DeoptimizeIf(eq, instr);
2293 } 2292 }
2294 2293
2295 const Register map = scratch0(); 2294 const Register map = scratch0();
2296 if (expected.NeedsMap()) { 2295 if (expected.NeedsMap()) {
2297 __ ldr(map, FieldMemOperand(reg, HeapObject::kMapOffset)); 2296 __ ldr(map, FieldMemOperand(reg, HeapObject::kMapOffset));
2298 2297
2299 if (expected.CanBeUndetectable()) { 2298 if (expected.CanBeUndetectable()) {
2300 // Undetectable -> false. 2299 // Undetectable -> false.
2301 __ ldrb(ip, FieldMemOperand(map, Map::kBitFieldOffset)); 2300 __ ldrb(ip, FieldMemOperand(map, Map::kBitFieldOffset));
2302 __ tst(ip, Operand(1 << Map::kIsUndetectable)); 2301 __ tst(ip, Operand(1 << Map::kIsUndetectable));
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
2338 __ VFPCompareAndSetFlags(dbl_scratch, 0.0); 2337 __ VFPCompareAndSetFlags(dbl_scratch, 0.0);
2339 __ cmp(r0, r0, vs); // NaN -> false. 2338 __ cmp(r0, r0, vs); // NaN -> false.
2340 __ b(eq, instr->FalseLabel(chunk_)); // +0, -0 -> false. 2339 __ b(eq, instr->FalseLabel(chunk_)); // +0, -0 -> false.
2341 __ b(instr->TrueLabel(chunk_)); 2340 __ b(instr->TrueLabel(chunk_));
2342 __ bind(&not_heap_number); 2341 __ bind(&not_heap_number);
2343 } 2342 }
2344 2343
2345 if (!expected.IsGeneric()) { 2344 if (!expected.IsGeneric()) {
2346 // We've seen something for the first time -> deopt. 2345 // We've seen something for the first time -> deopt.
2347 // This can only happen if we are not generic already. 2346 // This can only happen if we are not generic already.
2348 DeoptimizeIf(al, instr->environment()); 2347 DeoptimizeIf(al, instr);
2349 } 2348 }
2350 } 2349 }
2351 } 2350 }
2352 } 2351 }
2353 2352
2354 2353
2355 void LCodeGen::EmitGoto(int block) { 2354 void LCodeGen::EmitGoto(int block) {
2356 if (!IsNextEmittedBlock(block)) { 2355 if (!IsNextEmittedBlock(block)) {
2357 __ jmp(chunk_->GetAssemblyLabel(LookupDestination(block))); 2356 __ jmp(chunk_->GetAssemblyLabel(LookupDestination(block)));
2358 } 2357 }
(...skipping 624 matching lines...) Expand 10 before | Expand all | Expand 10 after
2983 } 2982 }
2984 2983
2985 2984
2986 void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) { 2985 void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) {
2987 Register result = ToRegister(instr->result()); 2986 Register result = ToRegister(instr->result());
2988 __ mov(ip, Operand(Handle<Object>(instr->hydrogen()->cell().handle()))); 2987 __ mov(ip, Operand(Handle<Object>(instr->hydrogen()->cell().handle())));
2989 __ ldr(result, FieldMemOperand(ip, Cell::kValueOffset)); 2988 __ ldr(result, FieldMemOperand(ip, Cell::kValueOffset));
2990 if (instr->hydrogen()->RequiresHoleCheck()) { 2989 if (instr->hydrogen()->RequiresHoleCheck()) {
2991 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 2990 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
2992 __ cmp(result, ip); 2991 __ cmp(result, ip);
2993 DeoptimizeIf(eq, instr->environment()); 2992 DeoptimizeIf(eq, instr);
2994 } 2993 }
2995 } 2994 }
2996 2995
2997 2996
2998 template <class T> 2997 template <class T>
2999 void LCodeGen::EmitVectorLoadICRegisters(T* instr) { 2998 void LCodeGen::EmitVectorLoadICRegisters(T* instr) {
3000 DCHECK(FLAG_vector_ics); 2999 DCHECK(FLAG_vector_ics);
3001 Register vector = ToRegister(instr->temp_vector()); 3000 Register vector = ToRegister(instr->temp_vector());
3002 DCHECK(vector.is(VectorLoadICDescriptor::VectorRegister())); 3001 DCHECK(vector.is(VectorLoadICDescriptor::VectorRegister()));
3003 __ Move(vector, instr->hydrogen()->feedback_vector()); 3002 __ Move(vector, instr->hydrogen()->feedback_vector());
(...skipping 29 matching lines...) Expand all
3033 3032
3034 // If the cell we are storing to contains the hole it could have 3033 // If the cell we are storing to contains the hole it could have
3035 // been deleted from the property dictionary. In that case, we need 3034 // been deleted from the property dictionary. In that case, we need
3036 // to update the property details in the property dictionary to mark 3035 // to update the property details in the property dictionary to mark
3037 // it as no longer deleted. 3036 // it as no longer deleted.
3038 if (instr->hydrogen()->RequiresHoleCheck()) { 3037 if (instr->hydrogen()->RequiresHoleCheck()) {
3039 // We use a temp to check the payload (CompareRoot might clobber ip). 3038 // We use a temp to check the payload (CompareRoot might clobber ip).
3040 Register payload = ToRegister(instr->temp()); 3039 Register payload = ToRegister(instr->temp());
3041 __ ldr(payload, FieldMemOperand(cell, Cell::kValueOffset)); 3040 __ ldr(payload, FieldMemOperand(cell, Cell::kValueOffset));
3042 __ CompareRoot(payload, Heap::kTheHoleValueRootIndex); 3041 __ CompareRoot(payload, Heap::kTheHoleValueRootIndex);
3043 DeoptimizeIf(eq, instr->environment()); 3042 DeoptimizeIf(eq, instr);
3044 } 3043 }
3045 3044
3046 // Store the value. 3045 // Store the value.
3047 __ str(value, FieldMemOperand(cell, Cell::kValueOffset)); 3046 __ str(value, FieldMemOperand(cell, Cell::kValueOffset));
3048 // Cells are always rescanned, so no write barrier here. 3047 // Cells are always rescanned, so no write barrier here.
3049 } 3048 }
3050 3049
3051 3050
3052 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { 3051 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
3053 Register context = ToRegister(instr->context()); 3052 Register context = ToRegister(instr->context());
3054 Register result = ToRegister(instr->result()); 3053 Register result = ToRegister(instr->result());
3055 __ ldr(result, ContextOperand(context, instr->slot_index())); 3054 __ ldr(result, ContextOperand(context, instr->slot_index()));
3056 if (instr->hydrogen()->RequiresHoleCheck()) { 3055 if (instr->hydrogen()->RequiresHoleCheck()) {
3057 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 3056 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
3058 __ cmp(result, ip); 3057 __ cmp(result, ip);
3059 if (instr->hydrogen()->DeoptimizesOnHole()) { 3058 if (instr->hydrogen()->DeoptimizesOnHole()) {
3060 DeoptimizeIf(eq, instr->environment()); 3059 DeoptimizeIf(eq, instr);
3061 } else { 3060 } else {
3062 __ mov(result, Operand(factory()->undefined_value()), LeaveCC, eq); 3061 __ mov(result, Operand(factory()->undefined_value()), LeaveCC, eq);
3063 } 3062 }
3064 } 3063 }
3065 } 3064 }
3066 3065
3067 3066
3068 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { 3067 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) {
3069 Register context = ToRegister(instr->context()); 3068 Register context = ToRegister(instr->context());
3070 Register value = ToRegister(instr->value()); 3069 Register value = ToRegister(instr->value());
3071 Register scratch = scratch0(); 3070 Register scratch = scratch0();
3072 MemOperand target = ContextOperand(context, instr->slot_index()); 3071 MemOperand target = ContextOperand(context, instr->slot_index());
3073 3072
3074 Label skip_assignment; 3073 Label skip_assignment;
3075 3074
3076 if (instr->hydrogen()->RequiresHoleCheck()) { 3075 if (instr->hydrogen()->RequiresHoleCheck()) {
3077 __ ldr(scratch, target); 3076 __ ldr(scratch, target);
3078 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 3077 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
3079 __ cmp(scratch, ip); 3078 __ cmp(scratch, ip);
3080 if (instr->hydrogen()->DeoptimizesOnHole()) { 3079 if (instr->hydrogen()->DeoptimizesOnHole()) {
3081 DeoptimizeIf(eq, instr->environment()); 3080 DeoptimizeIf(eq, instr);
3082 } else { 3081 } else {
3083 __ b(ne, &skip_assignment); 3082 __ b(ne, &skip_assignment);
3084 } 3083 }
3085 } 3084 }
3086 3085
3087 __ str(value, target); 3086 __ str(value, target);
3088 if (instr->hydrogen()->NeedsWriteBarrier()) { 3087 if (instr->hydrogen()->NeedsWriteBarrier()) {
3089 SmiCheck check_needed = 3088 SmiCheck check_needed =
3090 instr->hydrogen()->value()->type().IsHeapObject() 3089 instr->hydrogen()->value()->type().IsHeapObject()
3091 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; 3090 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
3151 Register function = ToRegister(instr->function()); 3150 Register function = ToRegister(instr->function());
3152 Register result = ToRegister(instr->result()); 3151 Register result = ToRegister(instr->result());
3153 3152
3154 // Get the prototype or initial map from the function. 3153 // Get the prototype or initial map from the function.
3155 __ ldr(result, 3154 __ ldr(result,
3156 FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); 3155 FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
3157 3156
3158 // Check that the function has a prototype or an initial map. 3157 // Check that the function has a prototype or an initial map.
3159 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); 3158 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
3160 __ cmp(result, ip); 3159 __ cmp(result, ip);
3161 DeoptimizeIf(eq, instr->environment()); 3160 DeoptimizeIf(eq, instr);
3162 3161
3163 // If the function does not have an initial map, we're done. 3162 // If the function does not have an initial map, we're done.
3164 Label done; 3163 Label done;
3165 __ CompareObjectType(result, scratch, scratch, MAP_TYPE); 3164 __ CompareObjectType(result, scratch, scratch, MAP_TYPE);
3166 __ b(ne, &done); 3165 __ b(ne, &done);
3167 3166
3168 // Get the prototype from the initial map. 3167 // Get the prototype from the initial map.
3169 __ ldr(result, FieldMemOperand(result, Map::kPrototypeOffset)); 3168 __ ldr(result, FieldMemOperand(result, Map::kPrototypeOffset));
3170 3169
3171 // All done. 3170 // All done.
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
3277 break; 3276 break;
3278 case EXTERNAL_INT32_ELEMENTS: 3277 case EXTERNAL_INT32_ELEMENTS:
3279 case INT32_ELEMENTS: 3278 case INT32_ELEMENTS:
3280 __ ldr(result, mem_operand); 3279 __ ldr(result, mem_operand);
3281 break; 3280 break;
3282 case EXTERNAL_UINT32_ELEMENTS: 3281 case EXTERNAL_UINT32_ELEMENTS:
3283 case UINT32_ELEMENTS: 3282 case UINT32_ELEMENTS:
3284 __ ldr(result, mem_operand); 3283 __ ldr(result, mem_operand);
3285 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) { 3284 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) {
3286 __ cmp(result, Operand(0x80000000)); 3285 __ cmp(result, Operand(0x80000000));
3287 DeoptimizeIf(cs, instr->environment()); 3286 DeoptimizeIf(cs, instr);
3288 } 3287 }
3289 break; 3288 break;
3290 case FLOAT32_ELEMENTS: 3289 case FLOAT32_ELEMENTS:
3291 case FLOAT64_ELEMENTS: 3290 case FLOAT64_ELEMENTS:
3292 case EXTERNAL_FLOAT32_ELEMENTS: 3291 case EXTERNAL_FLOAT32_ELEMENTS:
3293 case EXTERNAL_FLOAT64_ELEMENTS: 3292 case EXTERNAL_FLOAT64_ELEMENTS:
3294 case FAST_HOLEY_DOUBLE_ELEMENTS: 3293 case FAST_HOLEY_DOUBLE_ELEMENTS:
3295 case FAST_HOLEY_ELEMENTS: 3294 case FAST_HOLEY_ELEMENTS:
3296 case FAST_HOLEY_SMI_ELEMENTS: 3295 case FAST_HOLEY_SMI_ELEMENTS:
3297 case FAST_DOUBLE_ELEMENTS: 3296 case FAST_DOUBLE_ELEMENTS:
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
3330 int shift_size = (instr->hydrogen()->key()->representation().IsSmi()) 3329 int shift_size = (instr->hydrogen()->key()->representation().IsSmi())
3331 ? (element_size_shift - kSmiTagSize) : element_size_shift; 3330 ? (element_size_shift - kSmiTagSize) : element_size_shift;
3332 __ add(scratch, scratch, Operand(key, LSL, shift_size)); 3331 __ add(scratch, scratch, Operand(key, LSL, shift_size));
3333 } 3332 }
3334 3333
3335 __ vldr(result, scratch, 0); 3334 __ vldr(result, scratch, 0);
3336 3335
3337 if (instr->hydrogen()->RequiresHoleCheck()) { 3336 if (instr->hydrogen()->RequiresHoleCheck()) {
3338 __ ldr(scratch, MemOperand(scratch, sizeof(kHoleNanLower32))); 3337 __ ldr(scratch, MemOperand(scratch, sizeof(kHoleNanLower32)));
3339 __ cmp(scratch, Operand(kHoleNanUpper32)); 3338 __ cmp(scratch, Operand(kHoleNanUpper32));
3340 DeoptimizeIf(eq, instr->environment()); 3339 DeoptimizeIf(eq, instr);
3341 } 3340 }
3342 } 3341 }
3343 3342
3344 3343
3345 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { 3344 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) {
3346 Register elements = ToRegister(instr->elements()); 3345 Register elements = ToRegister(instr->elements());
3347 Register result = ToRegister(instr->result()); 3346 Register result = ToRegister(instr->result());
3348 Register scratch = scratch0(); 3347 Register scratch = scratch0();
3349 Register store_base = scratch; 3348 Register store_base = scratch;
3350 int offset = instr->base_offset(); 3349 int offset = instr->base_offset();
(...skipping 13 matching lines...) Expand all
3364 } else { 3363 } else {
3365 __ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2)); 3364 __ add(scratch, elements, Operand(key, LSL, kPointerSizeLog2));
3366 } 3365 }
3367 } 3366 }
3368 __ ldr(result, MemOperand(store_base, offset)); 3367 __ ldr(result, MemOperand(store_base, offset));
3369 3368
3370 // Check for the hole value. 3369 // Check for the hole value.
3371 if (instr->hydrogen()->RequiresHoleCheck()) { 3370 if (instr->hydrogen()->RequiresHoleCheck()) {
3372 if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) { 3371 if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) {
3373 __ SmiTst(result); 3372 __ SmiTst(result);
3374 DeoptimizeIf(ne, instr->environment()); 3373 DeoptimizeIf(ne, instr);
3375 } else { 3374 } else {
3376 __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex); 3375 __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex);
3377 __ cmp(result, scratch); 3376 __ cmp(result, scratch);
3378 DeoptimizeIf(eq, instr->environment()); 3377 DeoptimizeIf(eq, instr);
3379 } 3378 }
3380 } 3379 }
3381 } 3380 }
3382 3381
3383 3382
3384 void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) { 3383 void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) {
3385 if (instr->is_typed_elements()) { 3384 if (instr->is_typed_elements()) {
3386 DoLoadKeyedExternalArray(instr); 3385 DoLoadKeyedExternalArray(instr);
3387 } else if (instr->hydrogen()->representation().IsDouble()) { 3386 } else if (instr->hydrogen()->representation().IsDouble()) {
3388 DoLoadKeyedFixedDoubleArray(instr); 3387 DoLoadKeyedFixedDoubleArray(instr);
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
3510 // Normal function. Replace undefined or null with global receiver. 3509 // Normal function. Replace undefined or null with global receiver.
3511 __ LoadRoot(scratch, Heap::kNullValueRootIndex); 3510 __ LoadRoot(scratch, Heap::kNullValueRootIndex);
3512 __ cmp(receiver, scratch); 3511 __ cmp(receiver, scratch);
3513 __ b(eq, &global_object); 3512 __ b(eq, &global_object);
3514 __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex); 3513 __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex);
3515 __ cmp(receiver, scratch); 3514 __ cmp(receiver, scratch);
3516 __ b(eq, &global_object); 3515 __ b(eq, &global_object);
3517 3516
3518 // Deoptimize if the receiver is not a JS object. 3517 // Deoptimize if the receiver is not a JS object.
3519 __ SmiTst(receiver); 3518 __ SmiTst(receiver);
3520 DeoptimizeIf(eq, instr->environment()); 3519 DeoptimizeIf(eq, instr);
3521 __ CompareObjectType(receiver, scratch, scratch, FIRST_SPEC_OBJECT_TYPE); 3520 __ CompareObjectType(receiver, scratch, scratch, FIRST_SPEC_OBJECT_TYPE);
3522 DeoptimizeIf(lt, instr->environment()); 3521 DeoptimizeIf(lt, instr);
3523 3522
3524 __ b(&result_in_receiver); 3523 __ b(&result_in_receiver);
3525 __ bind(&global_object); 3524 __ bind(&global_object);
3526 __ ldr(result, FieldMemOperand(function, JSFunction::kContextOffset)); 3525 __ ldr(result, FieldMemOperand(function, JSFunction::kContextOffset));
3527 __ ldr(result, 3526 __ ldr(result,
3528 ContextOperand(result, Context::GLOBAL_OBJECT_INDEX)); 3527 ContextOperand(result, Context::GLOBAL_OBJECT_INDEX));
3529 __ ldr(result, FieldMemOperand(result, GlobalObject::kGlobalProxyOffset)); 3528 __ ldr(result, FieldMemOperand(result, GlobalObject::kGlobalProxyOffset));
3530 3529
3531 if (result.is(receiver)) { 3530 if (result.is(receiver)) {
3532 __ bind(&result_in_receiver); 3531 __ bind(&result_in_receiver);
(...skipping 14 matching lines...) Expand all
3547 Register elements = ToRegister(instr->elements()); 3546 Register elements = ToRegister(instr->elements());
3548 Register scratch = scratch0(); 3547 Register scratch = scratch0();
3549 DCHECK(receiver.is(r0)); // Used for parameter count. 3548 DCHECK(receiver.is(r0)); // Used for parameter count.
3550 DCHECK(function.is(r1)); // Required by InvokeFunction. 3549 DCHECK(function.is(r1)); // Required by InvokeFunction.
3551 DCHECK(ToRegister(instr->result()).is(r0)); 3550 DCHECK(ToRegister(instr->result()).is(r0));
3552 3551
3553 // Copy the arguments to this function possibly from the 3552 // Copy the arguments to this function possibly from the
3554 // adaptor frame below it. 3553 // adaptor frame below it.
3555 const uint32_t kArgumentsLimit = 1 * KB; 3554 const uint32_t kArgumentsLimit = 1 * KB;
3556 __ cmp(length, Operand(kArgumentsLimit)); 3555 __ cmp(length, Operand(kArgumentsLimit));
3557 DeoptimizeIf(hi, instr->environment()); 3556 DeoptimizeIf(hi, instr);
3558 3557
3559 // Push the receiver and use the register to keep the original 3558 // Push the receiver and use the register to keep the original
3560 // number of arguments. 3559 // number of arguments.
3561 __ push(receiver); 3560 __ push(receiver);
3562 __ mov(receiver, length); 3561 __ mov(receiver, length);
3563 // The arguments are at a one pointer size offset from elements. 3562 // The arguments are at a one pointer size offset from elements.
3564 __ add(elements, elements, Operand(1 * kPointerSize)); 3563 __ add(elements, elements, Operand(1 * kPointerSize));
3565 3564
3566 // Loop through the arguments pushing them onto the execution 3565 // Loop through the arguments pushing them onto the execution
3567 // stack. 3566 // stack.
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
3677 DCHECK(instr->context() != NULL); 3676 DCHECK(instr->context() != NULL);
3678 DCHECK(ToRegister(instr->context()).is(cp)); 3677 DCHECK(ToRegister(instr->context()).is(cp));
3679 Register input = ToRegister(instr->value()); 3678 Register input = ToRegister(instr->value());
3680 Register result = ToRegister(instr->result()); 3679 Register result = ToRegister(instr->result());
3681 Register scratch = scratch0(); 3680 Register scratch = scratch0();
3682 3681
3683 // Deoptimize if not a heap number. 3682 // Deoptimize if not a heap number.
3684 __ ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); 3683 __ ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset));
3685 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); 3684 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
3686 __ cmp(scratch, Operand(ip)); 3685 __ cmp(scratch, Operand(ip));
3687 DeoptimizeIf(ne, instr->environment()); 3686 DeoptimizeIf(ne, instr);
3688 3687
3689 Label done; 3688 Label done;
3690 Register exponent = scratch0(); 3689 Register exponent = scratch0();
3691 scratch = no_reg; 3690 scratch = no_reg;
3692 __ ldr(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset)); 3691 __ ldr(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset));
3693 // Check the sign of the argument. If the argument is positive, just 3692 // Check the sign of the argument. If the argument is positive, just
3694 // return it. 3693 // return it.
3695 __ tst(exponent, Operand(HeapNumber::kSignMask)); 3694 __ tst(exponent, Operand(HeapNumber::kSignMask));
3696 // Move the input to the result if necessary. 3695 // Move the input to the result if necessary.
3697 __ Move(result, input); 3696 __ Move(result, input);
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
3745 void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) { 3744 void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) {
3746 Register input = ToRegister(instr->value()); 3745 Register input = ToRegister(instr->value());
3747 Register result = ToRegister(instr->result()); 3746 Register result = ToRegister(instr->result());
3748 __ cmp(input, Operand::Zero()); 3747 __ cmp(input, Operand::Zero());
3749 __ Move(result, input, pl); 3748 __ Move(result, input, pl);
3750 // We can make rsb conditional because the previous cmp instruction 3749 // We can make rsb conditional because the previous cmp instruction
3751 // will clear the V (overflow) flag and rsb won't set this flag 3750 // will clear the V (overflow) flag and rsb won't set this flag
3752 // if input is positive. 3751 // if input is positive.
3753 __ rsb(result, input, Operand::Zero(), SetCC, mi); 3752 __ rsb(result, input, Operand::Zero(), SetCC, mi);
3754 // Deoptimize on overflow. 3753 // Deoptimize on overflow.
3755 DeoptimizeIf(vs, instr->environment()); 3754 DeoptimizeIf(vs, instr);
3756 } 3755 }
3757 3756
3758 3757
3759 void LCodeGen::DoMathAbs(LMathAbs* instr) { 3758 void LCodeGen::DoMathAbs(LMathAbs* instr) {
3760 // Class for deferred case. 3759 // Class for deferred case.
3761 class DeferredMathAbsTaggedHeapNumber FINAL : public LDeferredCode { 3760 class DeferredMathAbsTaggedHeapNumber FINAL : public LDeferredCode {
3762 public: 3761 public:
3763 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, LMathAbs* instr) 3762 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, LMathAbs* instr)
3764 : LDeferredCode(codegen), instr_(instr) { } 3763 : LDeferredCode(codegen), instr_(instr) { }
3765 virtual void Generate() OVERRIDE { 3764 virtual void Generate() OVERRIDE {
(...skipping 25 matching lines...) Expand all
3791 } 3790 }
3792 3791
3793 3792
3794 void LCodeGen::DoMathFloor(LMathFloor* instr) { 3793 void LCodeGen::DoMathFloor(LMathFloor* instr) {
3795 DwVfpRegister input = ToDoubleRegister(instr->value()); 3794 DwVfpRegister input = ToDoubleRegister(instr->value());
3796 Register result = ToRegister(instr->result()); 3795 Register result = ToRegister(instr->result());
3797 Register input_high = scratch0(); 3796 Register input_high = scratch0();
3798 Label done, exact; 3797 Label done, exact;
3799 3798
3800 __ TryInt32Floor(result, input, input_high, double_scratch0(), &done, &exact); 3799 __ TryInt32Floor(result, input, input_high, double_scratch0(), &done, &exact);
3801 DeoptimizeIf(al, instr->environment()); 3800 DeoptimizeIf(al, instr);
3802 3801
3803 __ bind(&exact); 3802 __ bind(&exact);
3804 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 3803 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
3805 // Test for -0. 3804 // Test for -0.
3806 __ cmp(result, Operand::Zero()); 3805 __ cmp(result, Operand::Zero());
3807 __ b(ne, &done); 3806 __ b(ne, &done);
3808 __ cmp(input_high, Operand::Zero()); 3807 __ cmp(input_high, Operand::Zero());
3809 DeoptimizeIf(mi, instr->environment()); 3808 DeoptimizeIf(mi, instr);
3810 } 3809 }
3811 __ bind(&done); 3810 __ bind(&done);
3812 } 3811 }
3813 3812
3814 3813
3815 void LCodeGen::DoMathRound(LMathRound* instr) { 3814 void LCodeGen::DoMathRound(LMathRound* instr) {
3816 DwVfpRegister input = ToDoubleRegister(instr->value()); 3815 DwVfpRegister input = ToDoubleRegister(instr->value());
3817 Register result = ToRegister(instr->result()); 3816 Register result = ToRegister(instr->result());
3818 DwVfpRegister double_scratch1 = ToDoubleRegister(instr->temp()); 3817 DwVfpRegister double_scratch1 = ToDoubleRegister(instr->temp());
3819 DwVfpRegister input_plus_dot_five = double_scratch1; 3818 DwVfpRegister input_plus_dot_five = double_scratch1;
3820 Register input_high = scratch0(); 3819 Register input_high = scratch0();
3821 DwVfpRegister dot_five = double_scratch0(); 3820 DwVfpRegister dot_five = double_scratch0();
3822 Label convert, done; 3821 Label convert, done;
3823 3822
3824 __ Vmov(dot_five, 0.5, scratch0()); 3823 __ Vmov(dot_five, 0.5, scratch0());
3825 __ vabs(double_scratch1, input); 3824 __ vabs(double_scratch1, input);
3826 __ VFPCompareAndSetFlags(double_scratch1, dot_five); 3825 __ VFPCompareAndSetFlags(double_scratch1, dot_five);
3827 // If input is in [-0.5, -0], the result is -0. 3826 // If input is in [-0.5, -0], the result is -0.
3828 // If input is in [+0, +0.5[, the result is +0. 3827 // If input is in [+0, +0.5[, the result is +0.
3829 // If the input is +0.5, the result is 1. 3828 // If the input is +0.5, the result is 1.
3830 __ b(hi, &convert); // Out of [-0.5, +0.5]. 3829 __ b(hi, &convert); // Out of [-0.5, +0.5].
3831 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 3830 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
3832 __ VmovHigh(input_high, input); 3831 __ VmovHigh(input_high, input);
3833 __ cmp(input_high, Operand::Zero()); 3832 __ cmp(input_high, Operand::Zero());
3834 DeoptimizeIf(mi, instr->environment()); // [-0.5, -0]. 3833 DeoptimizeIf(mi, instr); // [-0.5, -0].
3835 } 3834 }
3836 __ VFPCompareAndSetFlags(input, dot_five); 3835 __ VFPCompareAndSetFlags(input, dot_five);
3837 __ mov(result, Operand(1), LeaveCC, eq); // +0.5. 3836 __ mov(result, Operand(1), LeaveCC, eq); // +0.5.
3838 // Remaining cases: [+0, +0.5[ or [-0.5, +0.5[, depending on 3837 // Remaining cases: [+0, +0.5[ or [-0.5, +0.5[, depending on
3839 // flag kBailoutOnMinusZero. 3838 // flag kBailoutOnMinusZero.
3840 __ mov(result, Operand::Zero(), LeaveCC, ne); 3839 __ mov(result, Operand::Zero(), LeaveCC, ne);
3841 __ b(&done); 3840 __ b(&done);
3842 3841
3843 __ bind(&convert); 3842 __ bind(&convert);
3844 __ vadd(input_plus_dot_five, input, dot_five); 3843 __ vadd(input_plus_dot_five, input, dot_five);
3845 // Reuse dot_five (double_scratch0) as we no longer need this value. 3844 // Reuse dot_five (double_scratch0) as we no longer need this value.
3846 __ TryInt32Floor(result, input_plus_dot_five, input_high, double_scratch0(), 3845 __ TryInt32Floor(result, input_plus_dot_five, input_high, double_scratch0(),
3847 &done, &done); 3846 &done, &done);
3848 DeoptimizeIf(al, instr->environment()); 3847 DeoptimizeIf(al, instr);
3849 __ bind(&done); 3848 __ bind(&done);
3850 } 3849 }
3851 3850
3852 3851
3853 void LCodeGen::DoMathFround(LMathFround* instr) { 3852 void LCodeGen::DoMathFround(LMathFround* instr) {
3854 DwVfpRegister input_reg = ToDoubleRegister(instr->value()); 3853 DwVfpRegister input_reg = ToDoubleRegister(instr->value());
3855 DwVfpRegister output_reg = ToDoubleRegister(instr->result()); 3854 DwVfpRegister output_reg = ToDoubleRegister(instr->result());
3856 LowDwVfpRegister scratch = double_scratch0(); 3855 LowDwVfpRegister scratch = double_scratch0();
3857 __ vcvt_f32_f64(scratch.low(), input_reg); 3856 __ vcvt_f32_f64(scratch.low(), input_reg);
3858 __ vcvt_f64_f32(output_reg, scratch.low()); 3857 __ vcvt_f64_f32(output_reg, scratch.low());
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
3902 if (exponent_type.IsSmi()) { 3901 if (exponent_type.IsSmi()) {
3903 MathPowStub stub(isolate(), MathPowStub::TAGGED); 3902 MathPowStub stub(isolate(), MathPowStub::TAGGED);
3904 __ CallStub(&stub); 3903 __ CallStub(&stub);
3905 } else if (exponent_type.IsTagged()) { 3904 } else if (exponent_type.IsTagged()) {
3906 Label no_deopt; 3905 Label no_deopt;
3907 __ JumpIfSmi(tagged_exponent, &no_deopt); 3906 __ JumpIfSmi(tagged_exponent, &no_deopt);
3908 DCHECK(!r6.is(tagged_exponent)); 3907 DCHECK(!r6.is(tagged_exponent));
3909 __ ldr(r6, FieldMemOperand(tagged_exponent, HeapObject::kMapOffset)); 3908 __ ldr(r6, FieldMemOperand(tagged_exponent, HeapObject::kMapOffset));
3910 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); 3909 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
3911 __ cmp(r6, Operand(ip)); 3910 __ cmp(r6, Operand(ip));
3912 DeoptimizeIf(ne, instr->environment()); 3911 DeoptimizeIf(ne, instr);
3913 __ bind(&no_deopt); 3912 __ bind(&no_deopt);
3914 MathPowStub stub(isolate(), MathPowStub::TAGGED); 3913 MathPowStub stub(isolate(), MathPowStub::TAGGED);
3915 __ CallStub(&stub); 3914 __ CallStub(&stub);
3916 } else if (exponent_type.IsInteger32()) { 3915 } else if (exponent_type.IsInteger32()) {
3917 MathPowStub stub(isolate(), MathPowStub::INTEGER); 3916 MathPowStub stub(isolate(), MathPowStub::INTEGER);
3918 __ CallStub(&stub); 3917 __ CallStub(&stub);
3919 } else { 3918 } else {
3920 DCHECK(exponent_type.IsDouble()); 3919 DCHECK(exponent_type.IsDouble());
3921 MathPowStub stub(isolate(), MathPowStub::DOUBLE); 3920 MathPowStub stub(isolate(), MathPowStub::DOUBLE);
3922 __ CallStub(&stub); 3921 __ CallStub(&stub);
(...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after
4254 Register index = ToRegister(instr->index()); 4253 Register index = ToRegister(instr->index());
4255 Operand length = ToOperand(instr->length()); 4254 Operand length = ToOperand(instr->length());
4256 __ cmp(index, length); 4255 __ cmp(index, length);
4257 } 4256 }
4258 if (FLAG_debug_code && instr->hydrogen()->skip_check()) { 4257 if (FLAG_debug_code && instr->hydrogen()->skip_check()) {
4259 Label done; 4258 Label done;
4260 __ b(NegateCondition(cc), &done); 4259 __ b(NegateCondition(cc), &done);
4261 __ stop("eliminated bounds check failed"); 4260 __ stop("eliminated bounds check failed");
4262 __ bind(&done); 4261 __ bind(&done);
4263 } else { 4262 } else {
4264 DeoptimizeIf(cc, instr->environment()); 4263 DeoptimizeIf(cc, instr);
4265 } 4264 }
4266 } 4265 }
4267 4266
4268 4267
4269 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) { 4268 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
4270 Register external_pointer = ToRegister(instr->elements()); 4269 Register external_pointer = ToRegister(instr->elements());
4271 Register key = no_reg; 4270 Register key = no_reg;
4272 ElementsKind elements_kind = instr->elements_kind(); 4271 ElementsKind elements_kind = instr->elements_kind();
4273 bool key_is_constant = instr->key()->IsConstantOperand(); 4272 bool key_is_constant = instr->key()->IsConstantOperand();
4274 int constant_key = 0; 4273 int constant_key = 0;
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after
4502 } 4501 }
4503 __ bind(&not_applicable); 4502 __ bind(&not_applicable);
4504 } 4503 }
4505 4504
4506 4505
4507 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) { 4506 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) {
4508 Register object = ToRegister(instr->object()); 4507 Register object = ToRegister(instr->object());
4509 Register temp = ToRegister(instr->temp()); 4508 Register temp = ToRegister(instr->temp());
4510 Label no_memento_found; 4509 Label no_memento_found;
4511 __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found); 4510 __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found);
4512 DeoptimizeIf(eq, instr->environment()); 4511 DeoptimizeIf(eq, instr);
4513 __ bind(&no_memento_found); 4512 __ bind(&no_memento_found);
4514 } 4513 }
4515 4514
4516 4515
4517 void LCodeGen::DoStringAdd(LStringAdd* instr) { 4516 void LCodeGen::DoStringAdd(LStringAdd* instr) {
4518 DCHECK(ToRegister(instr->context()).is(cp)); 4517 DCHECK(ToRegister(instr->context()).is(cp));
4519 DCHECK(ToRegister(instr->left()).is(r1)); 4518 DCHECK(ToRegister(instr->left()).is(r1));
4520 DCHECK(ToRegister(instr->right()).is(r0)); 4519 DCHECK(ToRegister(instr->right()).is(r0));
4521 StringAddStub stub(isolate(), 4520 StringAddStub stub(isolate(),
4522 instr->hydrogen()->flags(), 4521 instr->hydrogen()->flags(),
(...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after
4836 } 4835 }
4837 4836
4838 4837
4839 void LCodeGen::DoSmiTag(LSmiTag* instr) { 4838 void LCodeGen::DoSmiTag(LSmiTag* instr) {
4840 HChange* hchange = instr->hydrogen(); 4839 HChange* hchange = instr->hydrogen();
4841 Register input = ToRegister(instr->value()); 4840 Register input = ToRegister(instr->value());
4842 Register output = ToRegister(instr->result()); 4841 Register output = ToRegister(instr->result());
4843 if (hchange->CheckFlag(HValue::kCanOverflow) && 4842 if (hchange->CheckFlag(HValue::kCanOverflow) &&
4844 hchange->value()->CheckFlag(HValue::kUint32)) { 4843 hchange->value()->CheckFlag(HValue::kUint32)) {
4845 __ tst(input, Operand(0xc0000000)); 4844 __ tst(input, Operand(0xc0000000));
4846 DeoptimizeIf(ne, instr->environment()); 4845 DeoptimizeIf(ne, instr);
4847 } 4846 }
4848 if (hchange->CheckFlag(HValue::kCanOverflow) && 4847 if (hchange->CheckFlag(HValue::kCanOverflow) &&
4849 !hchange->value()->CheckFlag(HValue::kUint32)) { 4848 !hchange->value()->CheckFlag(HValue::kUint32)) {
4850 __ SmiTag(output, input, SetCC); 4849 __ SmiTag(output, input, SetCC);
4851 DeoptimizeIf(vs, instr->environment()); 4850 DeoptimizeIf(vs, instr);
4852 } else { 4851 } else {
4853 __ SmiTag(output, input); 4852 __ SmiTag(output, input);
4854 } 4853 }
4855 } 4854 }
4856 4855
4857 4856
4858 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { 4857 void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
4859 Register input = ToRegister(instr->value()); 4858 Register input = ToRegister(instr->value());
4860 Register result = ToRegister(instr->result()); 4859 Register result = ToRegister(instr->result());
4861 if (instr->needs_check()) { 4860 if (instr->needs_check()) {
4862 STATIC_ASSERT(kHeapObjectTag == 1); 4861 STATIC_ASSERT(kHeapObjectTag == 1);
4863 // If the input is a HeapObject, SmiUntag will set the carry flag. 4862 // If the input is a HeapObject, SmiUntag will set the carry flag.
4864 __ SmiUntag(result, input, SetCC); 4863 __ SmiUntag(result, input, SetCC);
4865 DeoptimizeIf(cs, instr->environment()); 4864 DeoptimizeIf(cs, instr);
4866 } else { 4865 } else {
4867 __ SmiUntag(result, input); 4866 __ SmiUntag(result, input);
4868 } 4867 }
4869 } 4868 }
4870 4869
4871 4870
4872 void LCodeGen::EmitNumberUntagD(Register input_reg, 4871 void LCodeGen::EmitNumberUntagD(LNumberUntagD* instr, Register input_reg,
4873 DwVfpRegister result_reg, 4872 DwVfpRegister result_reg,
4874 bool can_convert_undefined_to_nan,
4875 bool deoptimize_on_minus_zero,
4876 LEnvironment* env,
4877 NumberUntagDMode mode) { 4873 NumberUntagDMode mode) {
4874 bool can_convert_undefined_to_nan =
4875 instr->hydrogen()->can_convert_undefined_to_nan();
4876 bool deoptimize_on_minus_zero = instr->hydrogen()->deoptimize_on_minus_zero();
4877
4878 Register scratch = scratch0(); 4878 Register scratch = scratch0();
4879 SwVfpRegister flt_scratch = double_scratch0().low(); 4879 SwVfpRegister flt_scratch = double_scratch0().low();
4880 DCHECK(!result_reg.is(double_scratch0())); 4880 DCHECK(!result_reg.is(double_scratch0()));
4881 Label convert, load_smi, done; 4881 Label convert, load_smi, done;
4882 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) { 4882 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) {
4883 // Smi check. 4883 // Smi check.
4884 __ UntagAndJumpIfSmi(scratch, input_reg, &load_smi); 4884 __ UntagAndJumpIfSmi(scratch, input_reg, &load_smi);
4885 // Heap number map check. 4885 // Heap number map check.
4886 __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); 4886 __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset));
4887 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex); 4887 __ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
4888 __ cmp(scratch, Operand(ip)); 4888 __ cmp(scratch, Operand(ip));
4889 if (can_convert_undefined_to_nan) { 4889 if (can_convert_undefined_to_nan) {
4890 __ b(ne, &convert); 4890 __ b(ne, &convert);
4891 } else { 4891 } else {
4892 DeoptimizeIf(ne, env); 4892 DeoptimizeIf(ne, instr);
4893 } 4893 }
4894 // load heap number 4894 // load heap number
4895 __ vldr(result_reg, input_reg, HeapNumber::kValueOffset - kHeapObjectTag); 4895 __ vldr(result_reg, input_reg, HeapNumber::kValueOffset - kHeapObjectTag);
4896 if (deoptimize_on_minus_zero) { 4896 if (deoptimize_on_minus_zero) {
4897 __ VmovLow(scratch, result_reg); 4897 __ VmovLow(scratch, result_reg);
4898 __ cmp(scratch, Operand::Zero()); 4898 __ cmp(scratch, Operand::Zero());
4899 __ b(ne, &done); 4899 __ b(ne, &done);
4900 __ VmovHigh(scratch, result_reg); 4900 __ VmovHigh(scratch, result_reg);
4901 __ cmp(scratch, Operand(HeapNumber::kSignMask)); 4901 __ cmp(scratch, Operand(HeapNumber::kSignMask));
4902 DeoptimizeIf(eq, env); 4902 DeoptimizeIf(eq, instr);
4903 } 4903 }
4904 __ jmp(&done); 4904 __ jmp(&done);
4905 if (can_convert_undefined_to_nan) { 4905 if (can_convert_undefined_to_nan) {
4906 __ bind(&convert); 4906 __ bind(&convert);
4907 // Convert undefined (and hole) to NaN. 4907 // Convert undefined (and hole) to NaN.
4908 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); 4908 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
4909 __ cmp(input_reg, Operand(ip)); 4909 __ cmp(input_reg, Operand(ip));
4910 DeoptimizeIf(ne, env); 4910 DeoptimizeIf(ne, instr);
4911 __ LoadRoot(scratch, Heap::kNanValueRootIndex); 4911 __ LoadRoot(scratch, Heap::kNanValueRootIndex);
4912 __ vldr(result_reg, scratch, HeapNumber::kValueOffset - kHeapObjectTag); 4912 __ vldr(result_reg, scratch, HeapNumber::kValueOffset - kHeapObjectTag);
4913 __ jmp(&done); 4913 __ jmp(&done);
4914 } 4914 }
4915 } else { 4915 } else {
4916 __ SmiUntag(scratch, input_reg); 4916 __ SmiUntag(scratch, input_reg);
4917 DCHECK(mode == NUMBER_CANDIDATE_IS_SMI); 4917 DCHECK(mode == NUMBER_CANDIDATE_IS_SMI);
4918 } 4918 }
4919 // Smi to double register conversion 4919 // Smi to double register conversion
4920 __ bind(&load_smi); 4920 __ bind(&load_smi);
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
4969 __ LoadRoot(ip, Heap::kTrueValueRootIndex); 4969 __ LoadRoot(ip, Heap::kTrueValueRootIndex);
4970 __ cmp(scratch2, Operand(ip)); 4970 __ cmp(scratch2, Operand(ip));
4971 __ b(ne, &check_false); 4971 __ b(ne, &check_false);
4972 __ mov(input_reg, Operand(1)); 4972 __ mov(input_reg, Operand(1));
4973 __ b(&done); 4973 __ b(&done);
4974 4974
4975 __ bind(&check_false); 4975 __ bind(&check_false);
4976 __ LoadRoot(ip, Heap::kFalseValueRootIndex); 4976 __ LoadRoot(ip, Heap::kFalseValueRootIndex);
4977 __ cmp(scratch2, Operand(ip)); 4977 __ cmp(scratch2, Operand(ip));
4978 __ RecordComment("Deferred TaggedToI: cannot truncate"); 4978 __ RecordComment("Deferred TaggedToI: cannot truncate");
4979 DeoptimizeIf(ne, instr->environment()); 4979 DeoptimizeIf(ne, instr);
4980 __ mov(input_reg, Operand::Zero()); 4980 __ mov(input_reg, Operand::Zero());
4981 } else { 4981 } else {
4982 __ RecordComment("Deferred TaggedToI: not a heap number"); 4982 __ RecordComment("Deferred TaggedToI: not a heap number");
4983 DeoptimizeIf(ne, instr->environment()); 4983 DeoptimizeIf(ne, instr);
4984 4984
4985 __ sub(ip, scratch2, Operand(kHeapObjectTag)); 4985 __ sub(ip, scratch2, Operand(kHeapObjectTag));
4986 __ vldr(double_scratch2, ip, HeapNumber::kValueOffset); 4986 __ vldr(double_scratch2, ip, HeapNumber::kValueOffset);
4987 __ TryDoubleToInt32Exact(input_reg, double_scratch2, double_scratch); 4987 __ TryDoubleToInt32Exact(input_reg, double_scratch2, double_scratch);
4988 __ RecordComment("Deferred TaggedToI: lost precision or NaN"); 4988 __ RecordComment("Deferred TaggedToI: lost precision or NaN");
4989 DeoptimizeIf(ne, instr->environment()); 4989 DeoptimizeIf(ne, instr);
4990 4990
4991 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 4991 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
4992 __ cmp(input_reg, Operand::Zero()); 4992 __ cmp(input_reg, Operand::Zero());
4993 __ b(ne, &done); 4993 __ b(ne, &done);
4994 __ VmovHigh(scratch1, double_scratch2); 4994 __ VmovHigh(scratch1, double_scratch2);
4995 __ tst(scratch1, Operand(HeapNumber::kSignMask)); 4995 __ tst(scratch1, Operand(HeapNumber::kSignMask));
4996 __ RecordComment("Deferred TaggedToI: minus zero"); 4996 __ RecordComment("Deferred TaggedToI: minus zero");
4997 DeoptimizeIf(ne, instr->environment()); 4997 DeoptimizeIf(ne, instr);
4998 } 4998 }
4999 } 4999 }
5000 __ bind(&done); 5000 __ bind(&done);
5001 } 5001 }
5002 5002
5003 5003
5004 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { 5004 void LCodeGen::DoTaggedToI(LTaggedToI* instr) {
5005 class DeferredTaggedToI FINAL : public LDeferredCode { 5005 class DeferredTaggedToI FINAL : public LDeferredCode {
5006 public: 5006 public:
5007 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) 5007 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr)
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
5042 LOperand* result = instr->result(); 5042 LOperand* result = instr->result();
5043 DCHECK(result->IsDoubleRegister()); 5043 DCHECK(result->IsDoubleRegister());
5044 5044
5045 Register input_reg = ToRegister(input); 5045 Register input_reg = ToRegister(input);
5046 DwVfpRegister result_reg = ToDoubleRegister(result); 5046 DwVfpRegister result_reg = ToDoubleRegister(result);
5047 5047
5048 HValue* value = instr->hydrogen()->value(); 5048 HValue* value = instr->hydrogen()->value();
5049 NumberUntagDMode mode = value->representation().IsSmi() 5049 NumberUntagDMode mode = value->representation().IsSmi()
5050 ? NUMBER_CANDIDATE_IS_SMI : NUMBER_CANDIDATE_IS_ANY_TAGGED; 5050 ? NUMBER_CANDIDATE_IS_SMI : NUMBER_CANDIDATE_IS_ANY_TAGGED;
5051 5051
5052 EmitNumberUntagD(input_reg, result_reg, 5052 EmitNumberUntagD(instr, input_reg, result_reg, mode);
5053 instr->hydrogen()->can_convert_undefined_to_nan(),
5054 instr->hydrogen()->deoptimize_on_minus_zero(),
5055 instr->environment(),
5056 mode);
5057 } 5053 }
5058 5054
5059 5055
5060 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { 5056 void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
5061 Register result_reg = ToRegister(instr->result()); 5057 Register result_reg = ToRegister(instr->result());
5062 Register scratch1 = scratch0(); 5058 Register scratch1 = scratch0();
5063 DwVfpRegister double_input = ToDoubleRegister(instr->value()); 5059 DwVfpRegister double_input = ToDoubleRegister(instr->value());
5064 LowDwVfpRegister double_scratch = double_scratch0(); 5060 LowDwVfpRegister double_scratch = double_scratch0();
5065 5061
5066 if (instr->truncating()) { 5062 if (instr->truncating()) {
5067 __ TruncateDoubleToI(result_reg, double_input); 5063 __ TruncateDoubleToI(result_reg, double_input);
5068 } else { 5064 } else {
5069 __ TryDoubleToInt32Exact(result_reg, double_input, double_scratch); 5065 __ TryDoubleToInt32Exact(result_reg, double_input, double_scratch);
5070 // Deoptimize if the input wasn't a int32 (inside a double). 5066 // Deoptimize if the input wasn't a int32 (inside a double).
5071 DeoptimizeIf(ne, instr->environment()); 5067 DeoptimizeIf(ne, instr);
5072 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 5068 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
5073 Label done; 5069 Label done;
5074 __ cmp(result_reg, Operand::Zero()); 5070 __ cmp(result_reg, Operand::Zero());
5075 __ b(ne, &done); 5071 __ b(ne, &done);
5076 __ VmovHigh(scratch1, double_input); 5072 __ VmovHigh(scratch1, double_input);
5077 __ tst(scratch1, Operand(HeapNumber::kSignMask)); 5073 __ tst(scratch1, Operand(HeapNumber::kSignMask));
5078 DeoptimizeIf(ne, instr->environment()); 5074 DeoptimizeIf(ne, instr);
5079 __ bind(&done); 5075 __ bind(&done);
5080 } 5076 }
5081 } 5077 }
5082 } 5078 }
5083 5079
5084 5080
5085 void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) { 5081 void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) {
5086 Register result_reg = ToRegister(instr->result()); 5082 Register result_reg = ToRegister(instr->result());
5087 Register scratch1 = scratch0(); 5083 Register scratch1 = scratch0();
5088 DwVfpRegister double_input = ToDoubleRegister(instr->value()); 5084 DwVfpRegister double_input = ToDoubleRegister(instr->value());
5089 LowDwVfpRegister double_scratch = double_scratch0(); 5085 LowDwVfpRegister double_scratch = double_scratch0();
5090 5086
5091 if (instr->truncating()) { 5087 if (instr->truncating()) {
5092 __ TruncateDoubleToI(result_reg, double_input); 5088 __ TruncateDoubleToI(result_reg, double_input);
5093 } else { 5089 } else {
5094 __ TryDoubleToInt32Exact(result_reg, double_input, double_scratch); 5090 __ TryDoubleToInt32Exact(result_reg, double_input, double_scratch);
5095 // Deoptimize if the input wasn't a int32 (inside a double). 5091 // Deoptimize if the input wasn't a int32 (inside a double).
5096 DeoptimizeIf(ne, instr->environment()); 5092 DeoptimizeIf(ne, instr);
5097 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 5093 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
5098 Label done; 5094 Label done;
5099 __ cmp(result_reg, Operand::Zero()); 5095 __ cmp(result_reg, Operand::Zero());
5100 __ b(ne, &done); 5096 __ b(ne, &done);
5101 __ VmovHigh(scratch1, double_input); 5097 __ VmovHigh(scratch1, double_input);
5102 __ tst(scratch1, Operand(HeapNumber::kSignMask)); 5098 __ tst(scratch1, Operand(HeapNumber::kSignMask));
5103 DeoptimizeIf(ne, instr->environment()); 5099 DeoptimizeIf(ne, instr);
5104 __ bind(&done); 5100 __ bind(&done);
5105 } 5101 }
5106 } 5102 }
5107 __ SmiTag(result_reg, SetCC); 5103 __ SmiTag(result_reg, SetCC);
5108 DeoptimizeIf(vs, instr->environment()); 5104 DeoptimizeIf(vs, instr);
5109 } 5105 }
5110 5106
5111 5107
5112 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { 5108 void LCodeGen::DoCheckSmi(LCheckSmi* instr) {
5113 LOperand* input = instr->value(); 5109 LOperand* input = instr->value();
5114 __ SmiTst(ToRegister(input)); 5110 __ SmiTst(ToRegister(input));
5115 DeoptimizeIf(ne, instr->environment()); 5111 DeoptimizeIf(ne, instr);
5116 } 5112 }
5117 5113
5118 5114
5119 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { 5115 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) {
5120 if (!instr->hydrogen()->value()->type().IsHeapObject()) { 5116 if (!instr->hydrogen()->value()->type().IsHeapObject()) {
5121 LOperand* input = instr->value(); 5117 LOperand* input = instr->value();
5122 __ SmiTst(ToRegister(input)); 5118 __ SmiTst(ToRegister(input));
5123 DeoptimizeIf(eq, instr->environment()); 5119 DeoptimizeIf(eq, instr);
5124 } 5120 }
5125 } 5121 }
5126 5122
5127 5123
5128 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { 5124 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
5129 Register input = ToRegister(instr->value()); 5125 Register input = ToRegister(instr->value());
5130 Register scratch = scratch0(); 5126 Register scratch = scratch0();
5131 5127
5132 __ ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); 5128 __ ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset));
5133 __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset)); 5129 __ ldrb(scratch, FieldMemOperand(scratch, Map::kInstanceTypeOffset));
5134 5130
5135 if (instr->hydrogen()->is_interval_check()) { 5131 if (instr->hydrogen()->is_interval_check()) {
5136 InstanceType first; 5132 InstanceType first;
5137 InstanceType last; 5133 InstanceType last;
5138 instr->hydrogen()->GetCheckInterval(&first, &last); 5134 instr->hydrogen()->GetCheckInterval(&first, &last);
5139 5135
5140 __ cmp(scratch, Operand(first)); 5136 __ cmp(scratch, Operand(first));
5141 5137
5142 // If there is only one type in the interval check for equality. 5138 // If there is only one type in the interval check for equality.
5143 if (first == last) { 5139 if (first == last) {
5144 DeoptimizeIf(ne, instr->environment()); 5140 DeoptimizeIf(ne, instr);
5145 } else { 5141 } else {
5146 DeoptimizeIf(lo, instr->environment()); 5142 DeoptimizeIf(lo, instr);
5147 // Omit check for the last type. 5143 // Omit check for the last type.
5148 if (last != LAST_TYPE) { 5144 if (last != LAST_TYPE) {
5149 __ cmp(scratch, Operand(last)); 5145 __ cmp(scratch, Operand(last));
5150 DeoptimizeIf(hi, instr->environment()); 5146 DeoptimizeIf(hi, instr);
5151 } 5147 }
5152 } 5148 }
5153 } else { 5149 } else {
5154 uint8_t mask; 5150 uint8_t mask;
5155 uint8_t tag; 5151 uint8_t tag;
5156 instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag); 5152 instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag);
5157 5153
5158 if (base::bits::IsPowerOfTwo32(mask)) { 5154 if (base::bits::IsPowerOfTwo32(mask)) {
5159 DCHECK(tag == 0 || base::bits::IsPowerOfTwo32(tag)); 5155 DCHECK(tag == 0 || base::bits::IsPowerOfTwo32(tag));
5160 __ tst(scratch, Operand(mask)); 5156 __ tst(scratch, Operand(mask));
5161 DeoptimizeIf(tag == 0 ? ne : eq, instr->environment()); 5157 DeoptimizeIf(tag == 0 ? ne : eq, instr);
5162 } else { 5158 } else {
5163 __ and_(scratch, scratch, Operand(mask)); 5159 __ and_(scratch, scratch, Operand(mask));
5164 __ cmp(scratch, Operand(tag)); 5160 __ cmp(scratch, Operand(tag));
5165 DeoptimizeIf(ne, instr->environment()); 5161 DeoptimizeIf(ne, instr);
5166 } 5162 }
5167 } 5163 }
5168 } 5164 }
5169 5165
5170 5166
5171 void LCodeGen::DoCheckValue(LCheckValue* instr) { 5167 void LCodeGen::DoCheckValue(LCheckValue* instr) {
5172 Register reg = ToRegister(instr->value()); 5168 Register reg = ToRegister(instr->value());
5173 Handle<HeapObject> object = instr->hydrogen()->object().handle(); 5169 Handle<HeapObject> object = instr->hydrogen()->object().handle();
5174 AllowDeferredHandleDereference smi_check; 5170 AllowDeferredHandleDereference smi_check;
5175 if (isolate()->heap()->InNewSpace(*object)) { 5171 if (isolate()->heap()->InNewSpace(*object)) {
5176 Register reg = ToRegister(instr->value()); 5172 Register reg = ToRegister(instr->value());
5177 Handle<Cell> cell = isolate()->factory()->NewCell(object); 5173 Handle<Cell> cell = isolate()->factory()->NewCell(object);
5178 __ mov(ip, Operand(Handle<Object>(cell))); 5174 __ mov(ip, Operand(Handle<Object>(cell)));
5179 __ ldr(ip, FieldMemOperand(ip, Cell::kValueOffset)); 5175 __ ldr(ip, FieldMemOperand(ip, Cell::kValueOffset));
5180 __ cmp(reg, ip); 5176 __ cmp(reg, ip);
5181 } else { 5177 } else {
5182 __ cmp(reg, Operand(object)); 5178 __ cmp(reg, Operand(object));
5183 } 5179 }
5184 DeoptimizeIf(ne, instr->environment()); 5180 DeoptimizeIf(ne, instr);
5185 } 5181 }
5186 5182
5187 5183
5188 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) { 5184 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) {
5189 { 5185 {
5190 PushSafepointRegistersScope scope(this); 5186 PushSafepointRegistersScope scope(this);
5191 __ push(object); 5187 __ push(object);
5192 __ mov(cp, Operand::Zero()); 5188 __ mov(cp, Operand::Zero());
5193 __ CallRuntimeSaveDoubles(Runtime::kTryMigrateInstance); 5189 __ CallRuntimeSaveDoubles(Runtime::kTryMigrateInstance);
5194 RecordSafepointWithRegisters( 5190 RecordSafepointWithRegisters(
5195 instr->pointer_map(), 1, Safepoint::kNoLazyDeopt); 5191 instr->pointer_map(), 1, Safepoint::kNoLazyDeopt);
5196 __ StoreToSafepointRegisterSlot(r0, scratch0()); 5192 __ StoreToSafepointRegisterSlot(r0, scratch0());
5197 } 5193 }
5198 __ tst(scratch0(), Operand(kSmiTagMask)); 5194 __ tst(scratch0(), Operand(kSmiTagMask));
5199 DeoptimizeIf(eq, instr->environment()); 5195 DeoptimizeIf(eq, instr);
5200 } 5196 }
5201 5197
5202 5198
5203 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { 5199 void LCodeGen::DoCheckMaps(LCheckMaps* instr) {
5204 class DeferredCheckMaps FINAL : public LDeferredCode { 5200 class DeferredCheckMaps FINAL : public LDeferredCode {
5205 public: 5201 public:
5206 DeferredCheckMaps(LCodeGen* codegen, LCheckMaps* instr, Register object) 5202 DeferredCheckMaps(LCodeGen* codegen, LCheckMaps* instr, Register object)
5207 : LDeferredCode(codegen), instr_(instr), object_(object) { 5203 : LDeferredCode(codegen), instr_(instr), object_(object) {
5208 SetExit(check_maps()); 5204 SetExit(check_maps());
5209 } 5205 }
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
5246 Handle<Map> map = maps->at(i).handle(); 5242 Handle<Map> map = maps->at(i).handle();
5247 __ CompareMap(map_reg, map, &success); 5243 __ CompareMap(map_reg, map, &success);
5248 __ b(eq, &success); 5244 __ b(eq, &success);
5249 } 5245 }
5250 5246
5251 Handle<Map> map = maps->at(maps->size() - 1).handle(); 5247 Handle<Map> map = maps->at(maps->size() - 1).handle();
5252 __ CompareMap(map_reg, map, &success); 5248 __ CompareMap(map_reg, map, &success);
5253 if (instr->hydrogen()->HasMigrationTarget()) { 5249 if (instr->hydrogen()->HasMigrationTarget()) {
5254 __ b(ne, deferred->entry()); 5250 __ b(ne, deferred->entry());
5255 } else { 5251 } else {
5256 DeoptimizeIf(ne, instr->environment()); 5252 DeoptimizeIf(ne, instr);
5257 } 5253 }
5258 5254
5259 __ bind(&success); 5255 __ bind(&success);
5260 } 5256 }
5261 5257
5262 5258
5263 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { 5259 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) {
5264 DwVfpRegister value_reg = ToDoubleRegister(instr->unclamped()); 5260 DwVfpRegister value_reg = ToDoubleRegister(instr->unclamped());
5265 Register result_reg = ToRegister(instr->result()); 5261 Register result_reg = ToRegister(instr->result());
5266 __ ClampDoubleToUint8(result_reg, value_reg, double_scratch0()); 5262 __ ClampDoubleToUint8(result_reg, value_reg, double_scratch0());
(...skipping 18 matching lines...) Expand all
5285 __ UntagAndJumpIfSmi(result_reg, input_reg, &is_smi); 5281 __ UntagAndJumpIfSmi(result_reg, input_reg, &is_smi);
5286 5282
5287 // Check for heap number 5283 // Check for heap number
5288 __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); 5284 __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset));
5289 __ cmp(scratch, Operand(factory()->heap_number_map())); 5285 __ cmp(scratch, Operand(factory()->heap_number_map()));
5290 __ b(eq, &heap_number); 5286 __ b(eq, &heap_number);
5291 5287
5292 // Check for undefined. Undefined is converted to zero for clamping 5288 // Check for undefined. Undefined is converted to zero for clamping
5293 // conversions. 5289 // conversions.
5294 __ cmp(input_reg, Operand(factory()->undefined_value())); 5290 __ cmp(input_reg, Operand(factory()->undefined_value()));
5295 DeoptimizeIf(ne, instr->environment()); 5291 DeoptimizeIf(ne, instr);
5296 __ mov(result_reg, Operand::Zero()); 5292 __ mov(result_reg, Operand::Zero());
5297 __ jmp(&done); 5293 __ jmp(&done);
5298 5294
5299 // Heap number 5295 // Heap number
5300 __ bind(&heap_number); 5296 __ bind(&heap_number);
5301 __ vldr(temp_reg, FieldMemOperand(input_reg, HeapNumber::kValueOffset)); 5297 __ vldr(temp_reg, FieldMemOperand(input_reg, HeapNumber::kValueOffset));
5302 __ ClampDoubleToUint8(result_reg, temp_reg, double_scratch0()); 5298 __ ClampDoubleToUint8(result_reg, temp_reg, double_scratch0());
5303 __ jmp(&done); 5299 __ jmp(&done);
5304 5300
5305 // smi 5301 // smi
(...skipping 357 matching lines...) Expand 10 before | Expand all | Expand 10 after
5663 Deoptimizer::BailoutType type = instr->hydrogen()->type(); 5659 Deoptimizer::BailoutType type = instr->hydrogen()->type();
5664 // TODO(danno): Stubs expect all deopts to be lazy for historical reasons (the 5660 // TODO(danno): Stubs expect all deopts to be lazy for historical reasons (the
5665 // needed return address), even though the implementation of LAZY and EAGER is 5661 // needed return address), even though the implementation of LAZY and EAGER is
5666 // now identical. When LAZY is eventually completely folded into EAGER, remove 5662 // now identical. When LAZY is eventually completely folded into EAGER, remove
5667 // the special case below. 5663 // the special case below.
5668 if (info()->IsStub() && type == Deoptimizer::EAGER) { 5664 if (info()->IsStub() && type == Deoptimizer::EAGER) {
5669 type = Deoptimizer::LAZY; 5665 type = Deoptimizer::LAZY;
5670 } 5666 }
5671 5667
5672 Comment(";;; deoptimize: %s", instr->hydrogen()->reason()); 5668 Comment(";;; deoptimize: %s", instr->hydrogen()->reason());
5673 DeoptimizeIf(al, instr->environment(), type); 5669 DeoptimizeIf(al, instr, type);
5674 } 5670 }
5675 5671
5676 5672
5677 void LCodeGen::DoDummy(LDummy* instr) { 5673 void LCodeGen::DoDummy(LDummy* instr) {
5678 // Nothing to see here, move on! 5674 // Nothing to see here, move on!
5679 } 5675 }
5680 5676
5681 5677
5682 void LCodeGen::DoDummyUse(LDummyUse* instr) { 5678 void LCodeGen::DoDummyUse(LDummyUse* instr) {
5683 // Nothing to see here, move on! 5679 // Nothing to see here, move on!
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
5756 DCHECK(!environment->HasBeenRegistered()); 5752 DCHECK(!environment->HasBeenRegistered());
5757 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); 5753 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
5758 5754
5759 GenerateOsrPrologue(); 5755 GenerateOsrPrologue();
5760 } 5756 }
5761 5757
5762 5758
5763 void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) { 5759 void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) {
5764 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); 5760 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
5765 __ cmp(r0, ip); 5761 __ cmp(r0, ip);
5766 DeoptimizeIf(eq, instr->environment()); 5762 DeoptimizeIf(eq, instr);
5767 5763
5768 Register null_value = r5; 5764 Register null_value = r5;
5769 __ LoadRoot(null_value, Heap::kNullValueRootIndex); 5765 __ LoadRoot(null_value, Heap::kNullValueRootIndex);
5770 __ cmp(r0, null_value); 5766 __ cmp(r0, null_value);
5771 DeoptimizeIf(eq, instr->environment()); 5767 DeoptimizeIf(eq, instr);
5772 5768
5773 __ SmiTst(r0); 5769 __ SmiTst(r0);
5774 DeoptimizeIf(eq, instr->environment()); 5770 DeoptimizeIf(eq, instr);
5775 5771
5776 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); 5772 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
5777 __ CompareObjectType(r0, r1, r1, LAST_JS_PROXY_TYPE); 5773 __ CompareObjectType(r0, r1, r1, LAST_JS_PROXY_TYPE);
5778 DeoptimizeIf(le, instr->environment()); 5774 DeoptimizeIf(le, instr);
5779 5775
5780 Label use_cache, call_runtime; 5776 Label use_cache, call_runtime;
5781 __ CheckEnumCache(null_value, &call_runtime); 5777 __ CheckEnumCache(null_value, &call_runtime);
5782 5778
5783 __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset)); 5779 __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset));
5784 __ b(&use_cache); 5780 __ b(&use_cache);
5785 5781
5786 // Get the set of properties to enumerate. 5782 // Get the set of properties to enumerate.
5787 __ bind(&call_runtime); 5783 __ bind(&call_runtime);
5788 __ push(r0); 5784 __ push(r0);
5789 CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr); 5785 CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr);
5790 5786
5791 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); 5787 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
5792 __ LoadRoot(ip, Heap::kMetaMapRootIndex); 5788 __ LoadRoot(ip, Heap::kMetaMapRootIndex);
5793 __ cmp(r1, ip); 5789 __ cmp(r1, ip);
5794 DeoptimizeIf(ne, instr->environment()); 5790 DeoptimizeIf(ne, instr);
5795 __ bind(&use_cache); 5791 __ bind(&use_cache);
5796 } 5792 }
5797 5793
5798 5794
5799 void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) { 5795 void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) {
5800 Register map = ToRegister(instr->map()); 5796 Register map = ToRegister(instr->map());
5801 Register result = ToRegister(instr->result()); 5797 Register result = ToRegister(instr->result());
5802 Label load_cache, done; 5798 Label load_cache, done;
5803 __ EnumLength(result, map); 5799 __ EnumLength(result, map);
5804 __ cmp(result, Operand(Smi::FromInt(0))); 5800 __ cmp(result, Operand(Smi::FromInt(0)));
5805 __ b(ne, &load_cache); 5801 __ b(ne, &load_cache);
5806 __ mov(result, Operand(isolate()->factory()->empty_fixed_array())); 5802 __ mov(result, Operand(isolate()->factory()->empty_fixed_array()));
5807 __ jmp(&done); 5803 __ jmp(&done);
5808 5804
5809 __ bind(&load_cache); 5805 __ bind(&load_cache);
5810 __ LoadInstanceDescriptors(map, result); 5806 __ LoadInstanceDescriptors(map, result);
5811 __ ldr(result, 5807 __ ldr(result,
5812 FieldMemOperand(result, DescriptorArray::kEnumCacheOffset)); 5808 FieldMemOperand(result, DescriptorArray::kEnumCacheOffset));
5813 __ ldr(result, 5809 __ ldr(result,
5814 FieldMemOperand(result, FixedArray::SizeFor(instr->idx()))); 5810 FieldMemOperand(result, FixedArray::SizeFor(instr->idx())));
5815 __ cmp(result, Operand::Zero()); 5811 __ cmp(result, Operand::Zero());
5816 DeoptimizeIf(eq, instr->environment()); 5812 DeoptimizeIf(eq, instr);
5817 5813
5818 __ bind(&done); 5814 __ bind(&done);
5819 } 5815 }
5820 5816
5821 5817
5822 void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) { 5818 void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) {
5823 Register object = ToRegister(instr->value()); 5819 Register object = ToRegister(instr->value());
5824 Register map = ToRegister(instr->map()); 5820 Register map = ToRegister(instr->map());
5825 __ ldr(scratch0(), FieldMemOperand(object, HeapObject::kMapOffset)); 5821 __ ldr(scratch0(), FieldMemOperand(object, HeapObject::kMapOffset));
5826 __ cmp(map, scratch0()); 5822 __ cmp(map, scratch0());
5827 DeoptimizeIf(ne, instr->environment()); 5823 DeoptimizeIf(ne, instr);
5828 } 5824 }
5829 5825
5830 5826
5831 void LCodeGen::DoDeferredLoadMutableDouble(LLoadFieldByIndex* instr, 5827 void LCodeGen::DoDeferredLoadMutableDouble(LLoadFieldByIndex* instr,
5832 Register result, 5828 Register result,
5833 Register object, 5829 Register object,
5834 Register index) { 5830 Register index) {
5835 PushSafepointRegistersScope scope(this); 5831 PushSafepointRegistersScope scope(this);
5836 __ Push(object); 5832 __ Push(object);
5837 __ Push(index); 5833 __ Push(index);
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
5914 __ Push(scope_info); 5910 __ Push(scope_info);
5915 __ push(ToRegister(instr->function())); 5911 __ push(ToRegister(instr->function()));
5916 CallRuntime(Runtime::kPushBlockContext, 2, instr); 5912 CallRuntime(Runtime::kPushBlockContext, 2, instr);
5917 RecordSafepoint(Safepoint::kNoLazyDeopt); 5913 RecordSafepoint(Safepoint::kNoLazyDeopt);
5918 } 5914 }
5919 5915
5920 5916
5921 #undef __ 5917 #undef __
5922 5918
5923 } } // namespace v8::internal 5919 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/arm/lithium-codegen-arm.h ('k') | src/arm64/lithium-codegen-arm64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698