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

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

Issue 11745030: ARM: generate integer zero in a uniform manner. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 11 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/full-codegen-arm.cc ('k') | src/arm/macro-assembler-arm.cc » ('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 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
130 // cp: Callee's context. 130 // cp: Callee's context.
131 // fp: Caller's frame pointer. 131 // fp: Caller's frame pointer.
132 // lr: Caller's pc. 132 // lr: Caller's pc.
133 133
134 // Strict mode functions and builtins need to replace the receiver 134 // Strict mode functions and builtins need to replace the receiver
135 // with undefined when called as functions (without an explicit 135 // with undefined when called as functions (without an explicit
136 // receiver object). r5 is zero for method calls and non-zero for 136 // receiver object). r5 is zero for method calls and non-zero for
137 // function calls. 137 // function calls.
138 if (!info_->is_classic_mode() || info_->is_native()) { 138 if (!info_->is_classic_mode() || info_->is_native()) {
139 Label ok; 139 Label ok;
140 __ cmp(r5, Operand(0)); 140 __ cmp(r5, Operand::Zero());
141 __ b(eq, &ok); 141 __ b(eq, &ok);
142 int receiver_offset = scope()->num_parameters() * kPointerSize; 142 int receiver_offset = scope()->num_parameters() * kPointerSize;
143 __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); 143 __ LoadRoot(r2, Heap::kUndefinedValueRootIndex);
144 __ str(r2, MemOperand(sp, receiver_offset)); 144 __ str(r2, MemOperand(sp, receiver_offset));
145 __ bind(&ok); 145 __ bind(&ok);
146 } 146 }
147 } 147 }
148 148
149 info()->set_prologue_offset(masm_->pc_offset()); 149 info()->set_prologue_offset(masm_->pc_offset());
150 if (NeedsEagerFrame()) { 150 if (NeedsEagerFrame()) {
(...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after
517 return Operand(constant->Integer32Value()); 517 return Operand(constant->Integer32Value());
518 } else if (r.IsDouble()) { 518 } else if (r.IsDouble()) {
519 Abort("ToOperand Unsupported double immediate."); 519 Abort("ToOperand Unsupported double immediate.");
520 } 520 }
521 ASSERT(r.IsTagged()); 521 ASSERT(r.IsTagged());
522 return Operand(constant->handle()); 522 return Operand(constant->handle());
523 } else if (op->IsRegister()) { 523 } else if (op->IsRegister()) {
524 return Operand(ToRegister(op)); 524 return Operand(ToRegister(op));
525 } else if (op->IsDoubleRegister()) { 525 } else if (op->IsDoubleRegister()) {
526 Abort("ToOperand IsDoubleRegister unimplemented"); 526 Abort("ToOperand IsDoubleRegister unimplemented");
527 return Operand(0); 527 return Operand::Zero();
528 } 528 }
529 // Stack slots not implemented, use ToMemOperand instead. 529 // Stack slots not implemented, use ToMemOperand instead.
530 UNREACHABLE(); 530 UNREACHABLE();
531 return Operand(0); 531 return Operand::Zero();
532 } 532 }
533 533
534 534
535 MemOperand LCodeGen::ToMemOperand(LOperand* op) const { 535 MemOperand LCodeGen::ToMemOperand(LOperand* op) const {
536 ASSERT(!op->IsRegister()); 536 ASSERT(!op->IsRegister());
537 ASSERT(!op->IsDoubleRegister()); 537 ASSERT(!op->IsDoubleRegister());
538 ASSERT(op->IsStackSlot() || op->IsDoubleStackSlot()); 538 ASSERT(op->IsStackSlot() || op->IsDoubleStackSlot());
539 int index = op->index(); 539 int index = op->index();
540 if (index >= 0) { 540 if (index >= 0) {
541 // Local or spill slot. Skip the frame pointer, function, and 541 // Local or spill slot. Skip the frame pointer, function, and
(...skipping 527 matching lines...) Expand 10 before | Expand all | Expand 10 after
1069 if (instr->hydrogen()->HasPowerOf2Divisor()) { 1069 if (instr->hydrogen()->HasPowerOf2Divisor()) {
1070 Register dividend = ToRegister(instr->left()); 1070 Register dividend = ToRegister(instr->left());
1071 Register result = ToRegister(instr->result()); 1071 Register result = ToRegister(instr->result());
1072 1072
1073 int32_t divisor = 1073 int32_t divisor =
1074 HConstant::cast(instr->hydrogen()->right())->Integer32Value(); 1074 HConstant::cast(instr->hydrogen()->right())->Integer32Value();
1075 1075
1076 if (divisor < 0) divisor = -divisor; 1076 if (divisor < 0) divisor = -divisor;
1077 1077
1078 Label positive_dividend, done; 1078 Label positive_dividend, done;
1079 __ cmp(dividend, Operand(0)); 1079 __ cmp(dividend, Operand::Zero());
1080 __ b(pl, &positive_dividend); 1080 __ b(pl, &positive_dividend);
1081 __ rsb(result, dividend, Operand(0)); 1081 __ rsb(result, dividend, Operand::Zero());
1082 __ and_(result, result, Operand(divisor - 1), SetCC); 1082 __ and_(result, result, Operand(divisor - 1), SetCC);
1083 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 1083 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
1084 DeoptimizeIf(eq, instr->environment()); 1084 DeoptimizeIf(eq, instr->environment());
1085 } 1085 }
1086 __ rsb(result, result, Operand(0)); 1086 __ rsb(result, result, Operand::Zero());
1087 __ b(&done); 1087 __ b(&done);
1088 __ bind(&positive_dividend); 1088 __ bind(&positive_dividend);
1089 __ and_(result, dividend, Operand(divisor - 1)); 1089 __ and_(result, dividend, Operand(divisor - 1));
1090 __ bind(&done); 1090 __ bind(&done);
1091 return; 1091 return;
1092 } 1092 }
1093 1093
1094 // These registers hold untagged 32 bit values. 1094 // These registers hold untagged 32 bit values.
1095 Register left = ToRegister(instr->left()); 1095 Register left = ToRegister(instr->left());
1096 Register right = ToRegister(instr->right()); 1096 Register right = ToRegister(instr->right());
1097 Register result = ToRegister(instr->result()); 1097 Register result = ToRegister(instr->result());
1098 Label done; 1098 Label done;
1099 1099
1100 if (CpuFeatures::IsSupported(SUDIV)) { 1100 if (CpuFeatures::IsSupported(SUDIV)) {
1101 CpuFeatures::Scope scope(SUDIV); 1101 CpuFeatures::Scope scope(SUDIV);
1102 // Check for x % 0. 1102 // Check for x % 0.
1103 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { 1103 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
1104 __ cmp(right, Operand(0)); 1104 __ cmp(right, Operand::Zero());
1105 DeoptimizeIf(eq, instr->environment()); 1105 DeoptimizeIf(eq, instr->environment());
1106 } 1106 }
1107 1107
1108 // Check for (kMinInt % -1). 1108 // Check for (kMinInt % -1).
1109 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { 1109 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
1110 Label left_not_min_int; 1110 Label left_not_min_int;
1111 __ cmp(left, Operand(kMinInt)); 1111 __ cmp(left, Operand(kMinInt));
1112 __ b(ne, &left_not_min_int); 1112 __ b(ne, &left_not_min_int);
1113 __ cmp(right, Operand(-1)); 1113 __ cmp(right, Operand(-1));
1114 DeoptimizeIf(eq, instr->environment()); 1114 DeoptimizeIf(eq, instr->environment());
1115 __ bind(&left_not_min_int); 1115 __ bind(&left_not_min_int);
1116 } 1116 }
1117 1117
1118 // For r3 = r1 % r2; we can have the following ARM code 1118 // For r3 = r1 % r2; we can have the following ARM code
1119 // sdiv r3, r1, r2 1119 // sdiv r3, r1, r2
1120 // mls r3, r3, r2, r1 1120 // mls r3, r3, r2, r1
1121 1121
1122 __ sdiv(result, left, right); 1122 __ sdiv(result, left, right);
1123 __ mls(result, result, right, left); 1123 __ mls(result, result, right, left);
1124 __ cmp(result, Operand(0)); 1124 __ cmp(result, Operand::Zero());
1125 __ b(ne, &done); 1125 __ b(ne, &done);
1126 1126
1127 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 1127 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
1128 __ cmp(left, Operand(0)); 1128 __ cmp(left, Operand::Zero());
1129 DeoptimizeIf(lt, instr->environment()); 1129 DeoptimizeIf(lt, instr->environment());
1130 } 1130 }
1131 } else { 1131 } else {
1132 Register scratch = scratch0(); 1132 Register scratch = scratch0();
1133 Register scratch2 = ToRegister(instr->temp()); 1133 Register scratch2 = ToRegister(instr->temp());
1134 DwVfpRegister dividend = ToDoubleRegister(instr->temp2()); 1134 DwVfpRegister dividend = ToDoubleRegister(instr->temp2());
1135 DwVfpRegister divisor = ToDoubleRegister(instr->temp3()); 1135 DwVfpRegister divisor = ToDoubleRegister(instr->temp3());
1136 DwVfpRegister quotient = double_scratch0(); 1136 DwVfpRegister quotient = double_scratch0();
1137 1137
1138 ASSERT(!dividend.is(divisor)); 1138 ASSERT(!dividend.is(divisor));
1139 ASSERT(!dividend.is(quotient)); 1139 ASSERT(!dividend.is(quotient));
1140 ASSERT(!divisor.is(quotient)); 1140 ASSERT(!divisor.is(quotient));
1141 ASSERT(!scratch.is(left)); 1141 ASSERT(!scratch.is(left));
1142 ASSERT(!scratch.is(right)); 1142 ASSERT(!scratch.is(right));
1143 ASSERT(!scratch.is(result)); 1143 ASSERT(!scratch.is(result));
1144 1144
1145 Label vfp_modulo, both_positive, right_negative; 1145 Label vfp_modulo, both_positive, right_negative;
1146 1146
1147 CpuFeatures::Scope scope(VFP2); 1147 CpuFeatures::Scope scope(VFP2);
1148 1148
1149 // Check for x % 0. 1149 // Check for x % 0.
1150 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { 1150 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
1151 __ cmp(right, Operand(0)); 1151 __ cmp(right, Operand::Zero());
1152 DeoptimizeIf(eq, instr->environment()); 1152 DeoptimizeIf(eq, instr->environment());
1153 } 1153 }
1154 1154
1155 __ Move(result, left); 1155 __ Move(result, left);
1156 1156
1157 // (0 % x) must yield 0 (if x is finite, which is the case here). 1157 // (0 % x) must yield 0 (if x is finite, which is the case here).
1158 __ cmp(left, Operand(0)); 1158 __ cmp(left, Operand::Zero());
1159 __ b(eq, &done); 1159 __ b(eq, &done);
1160 // Preload right in a vfp register. 1160 // Preload right in a vfp register.
1161 __ vmov(divisor.low(), right); 1161 __ vmov(divisor.low(), right);
1162 __ b(lt, &vfp_modulo); 1162 __ b(lt, &vfp_modulo);
1163 1163
1164 __ cmp(left, Operand(right)); 1164 __ cmp(left, Operand(right));
1165 __ b(lt, &done); 1165 __ b(lt, &done);
1166 1166
1167 // Check for (positive) power of two on the right hand side. 1167 // Check for (positive) power of two on the right hand side.
1168 __ JumpIfNotPowerOfTwoOrZeroAndNeg(right, 1168 __ JumpIfNotPowerOfTwoOrZeroAndNeg(right,
1169 scratch, 1169 scratch,
1170 &right_negative, 1170 &right_negative,
1171 &both_positive); 1171 &both_positive);
1172 // Perform modulo operation (scratch contains right - 1). 1172 // Perform modulo operation (scratch contains right - 1).
1173 __ and_(result, scratch, Operand(left)); 1173 __ and_(result, scratch, Operand(left));
1174 __ b(&done); 1174 __ b(&done);
1175 1175
1176 __ bind(&right_negative); 1176 __ bind(&right_negative);
1177 // Negate right. The sign of the divisor does not matter. 1177 // Negate right. The sign of the divisor does not matter.
1178 __ rsb(right, right, Operand(0)); 1178 __ rsb(right, right, Operand::Zero());
1179 1179
1180 __ bind(&both_positive); 1180 __ bind(&both_positive);
1181 const int kUnfolds = 3; 1181 const int kUnfolds = 3;
1182 // If the right hand side is smaller than the (nonnegative) 1182 // If the right hand side is smaller than the (nonnegative)
1183 // left hand side, the left hand side is the result. 1183 // left hand side, the left hand side is the result.
1184 // Else try a few subtractions of the left hand side. 1184 // Else try a few subtractions of the left hand side.
1185 __ mov(scratch, left); 1185 __ mov(scratch, left);
1186 for (int i = 0; i < kUnfolds; i++) { 1186 for (int i = 0; i < kUnfolds; i++) {
1187 // Check if the left hand side is less or equal than the 1187 // Check if the left hand side is less or equal than the
1188 // the right hand side. 1188 // the right hand side.
(...skipping 30 matching lines...) Expand all
1219 __ vcvt_s32_f64(double_scratch.low(), double_scratch); 1219 __ vcvt_s32_f64(double_scratch.low(), double_scratch);
1220 __ vmov(scratch, double_scratch.low()); 1220 __ vmov(scratch, double_scratch.low());
1221 1221
1222 if (!instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 1222 if (!instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
1223 __ sub(result, left, scratch); 1223 __ sub(result, left, scratch);
1224 } else { 1224 } else {
1225 Label ok; 1225 Label ok;
1226 // Check for -0. 1226 // Check for -0.
1227 __ sub(scratch2, left, scratch, SetCC); 1227 __ sub(scratch2, left, scratch, SetCC);
1228 __ b(ne, &ok); 1228 __ b(ne, &ok);
1229 __ cmp(left, Operand(0)); 1229 __ cmp(left, Operand::Zero());
1230 DeoptimizeIf(mi, instr->environment()); 1230 DeoptimizeIf(mi, instr->environment());
1231 __ bind(&ok); 1231 __ bind(&ok);
1232 // Load the result and we are done. 1232 // Load the result and we are done.
1233 __ mov(result, scratch2); 1233 __ mov(result, scratch2);
1234 } 1234 }
1235 } 1235 }
1236 __ bind(&done); 1236 __ bind(&done);
1237 } 1237 }
1238 1238
1239 1239
(...skipping 14 matching lines...) Expand all
1254 1254
1255 switch (divisor_abs) { 1255 switch (divisor_abs) {
1256 case 0: 1256 case 0:
1257 DeoptimizeIf(al, environment); 1257 DeoptimizeIf(al, environment);
1258 return; 1258 return;
1259 1259
1260 case 1: 1260 case 1:
1261 if (divisor > 0) { 1261 if (divisor > 0) {
1262 __ Move(result, dividend); 1262 __ Move(result, dividend);
1263 } else { 1263 } else {
1264 __ rsb(result, dividend, Operand(0), SetCC); 1264 __ rsb(result, dividend, Operand::Zero(), SetCC);
1265 DeoptimizeIf(vs, environment); 1265 DeoptimizeIf(vs, environment);
1266 } 1266 }
1267 // Compute the remainder. 1267 // Compute the remainder.
1268 __ mov(remainder, Operand(0)); 1268 __ mov(remainder, Operand::Zero());
1269 return; 1269 return;
1270 1270
1271 default: 1271 default:
1272 if (IsPowerOf2(divisor_abs)) { 1272 if (IsPowerOf2(divisor_abs)) {
1273 // Branch and condition free code for integer division by a power 1273 // Branch and condition free code for integer division by a power
1274 // of two. 1274 // of two.
1275 int32_t power = WhichPowerOf2(divisor_abs); 1275 int32_t power = WhichPowerOf2(divisor_abs);
1276 if (power > 1) { 1276 if (power > 1) {
1277 __ mov(scratch, Operand(dividend, ASR, power - 1)); 1277 __ mov(scratch, Operand(dividend, ASR, power - 1));
1278 } 1278 }
1279 __ add(scratch, dividend, Operand(scratch, LSR, 32 - power)); 1279 __ add(scratch, dividend, Operand(scratch, LSR, 32 - power));
1280 __ mov(result, Operand(scratch, ASR, power)); 1280 __ mov(result, Operand(scratch, ASR, power));
1281 // Negate if necessary. 1281 // Negate if necessary.
1282 // We don't need to check for overflow because the case '-1' is 1282 // We don't need to check for overflow because the case '-1' is
1283 // handled separately. 1283 // handled separately.
1284 if (divisor < 0) { 1284 if (divisor < 0) {
1285 ASSERT(divisor != -1); 1285 ASSERT(divisor != -1);
1286 __ rsb(result, result, Operand(0)); 1286 __ rsb(result, result, Operand::Zero());
1287 } 1287 }
1288 // Compute the remainder. 1288 // Compute the remainder.
1289 if (divisor > 0) { 1289 if (divisor > 0) {
1290 __ sub(remainder, dividend, Operand(result, LSL, power)); 1290 __ sub(remainder, dividend, Operand(result, LSL, power));
1291 } else { 1291 } else {
1292 __ add(remainder, dividend, Operand(result, LSL, power)); 1292 __ add(remainder, dividend, Operand(result, LSL, power));
1293 } 1293 }
1294 return; 1294 return;
1295 } else { 1295 } else {
1296 // Use magic numbers for a few specific divisors. 1296 // Use magic numbers for a few specific divisors.
(...skipping 15 matching lines...) Expand all
1312 1312
1313 __ mov(ip, Operand(M)); 1313 __ mov(ip, Operand(M));
1314 __ smull(ip, scratch, dividend, ip); 1314 __ smull(ip, scratch, dividend, ip);
1315 if (M < 0) { 1315 if (M < 0) {
1316 __ add(scratch, scratch, Operand(dividend)); 1316 __ add(scratch, scratch, Operand(dividend));
1317 } 1317 }
1318 if (s > 0) { 1318 if (s > 0) {
1319 __ mov(scratch, Operand(scratch, ASR, s)); 1319 __ mov(scratch, Operand(scratch, ASR, s));
1320 } 1320 }
1321 __ add(result, scratch, Operand(dividend, LSR, 31)); 1321 __ add(result, scratch, Operand(dividend, LSR, 31));
1322 if (divisor < 0) __ rsb(result, result, Operand(0)); 1322 if (divisor < 0) __ rsb(result, result, Operand::Zero());
1323 // Compute the remainder. 1323 // Compute the remainder.
1324 __ mov(ip, Operand(divisor)); 1324 __ mov(ip, Operand(divisor));
1325 // This sequence could be replaced with 'mls' when 1325 // This sequence could be replaced with 'mls' when
1326 // it gets implemented. 1326 // it gets implemented.
1327 __ mul(scratch, result, ip); 1327 __ mul(scratch, result, ip);
1328 __ sub(remainder, dividend, scratch); 1328 __ sub(remainder, dividend, scratch);
1329 } 1329 }
1330 } 1330 }
1331 } 1331 }
1332 1332
(...skipping 14 matching lines...) Expand all
1347 LDivI* instr_; 1347 LDivI* instr_;
1348 }; 1348 };
1349 1349
1350 const Register left = ToRegister(instr->left()); 1350 const Register left = ToRegister(instr->left());
1351 const Register right = ToRegister(instr->right()); 1351 const Register right = ToRegister(instr->right());
1352 const Register scratch = scratch0(); 1352 const Register scratch = scratch0();
1353 const Register result = ToRegister(instr->result()); 1353 const Register result = ToRegister(instr->result());
1354 1354
1355 // Check for x / 0. 1355 // Check for x / 0.
1356 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) { 1356 if (instr->hydrogen()->CheckFlag(HValue::kCanBeDivByZero)) {
1357 __ cmp(right, Operand(0)); 1357 __ cmp(right, Operand::Zero());
1358 DeoptimizeIf(eq, instr->environment()); 1358 DeoptimizeIf(eq, instr->environment());
1359 } 1359 }
1360 1360
1361 // Check for (0 / -x) that will produce negative zero. 1361 // Check for (0 / -x) that will produce negative zero.
1362 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 1362 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
1363 Label left_not_zero; 1363 Label left_not_zero;
1364 __ cmp(left, Operand(0)); 1364 __ cmp(left, Operand::Zero());
1365 __ b(ne, &left_not_zero); 1365 __ b(ne, &left_not_zero);
1366 __ cmp(right, Operand(0)); 1366 __ cmp(right, Operand::Zero());
1367 DeoptimizeIf(mi, instr->environment()); 1367 DeoptimizeIf(mi, instr->environment());
1368 __ bind(&left_not_zero); 1368 __ bind(&left_not_zero);
1369 } 1369 }
1370 1370
1371 // Check for (kMinInt / -1). 1371 // Check for (kMinInt / -1).
1372 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { 1372 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
1373 Label left_not_min_int; 1373 Label left_not_min_int;
1374 __ cmp(left, Operand(kMinInt)); 1374 __ cmp(left, Operand(kMinInt));
1375 __ b(ne, &left_not_min_int); 1375 __ b(ne, &left_not_min_int);
1376 __ cmp(right, Operand(-1)); 1376 __ cmp(right, Operand(-1));
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
1434 const Register scratch = scratch0(); 1434 const Register scratch = scratch0();
1435 1435
1436 if (!CpuFeatures::IsSupported(SUDIV)) { 1436 if (!CpuFeatures::IsSupported(SUDIV)) {
1437 // If the CPU doesn't support sdiv instruction, we only optimize when we 1437 // If the CPU doesn't support sdiv instruction, we only optimize when we
1438 // have magic numbers for the divisor. The standard integer division routine 1438 // have magic numbers for the divisor. The standard integer division routine
1439 // is usually slower than transitionning to VFP. 1439 // is usually slower than transitionning to VFP.
1440 ASSERT(instr->right()->IsConstantOperand()); 1440 ASSERT(instr->right()->IsConstantOperand());
1441 int32_t divisor = ToInteger32(LConstantOperand::cast(instr->right())); 1441 int32_t divisor = ToInteger32(LConstantOperand::cast(instr->right()));
1442 ASSERT(LChunkBuilder::HasMagicNumberForDivisor(divisor)); 1442 ASSERT(LChunkBuilder::HasMagicNumberForDivisor(divisor));
1443 if (divisor < 0) { 1443 if (divisor < 0) {
1444 __ cmp(left, Operand(0)); 1444 __ cmp(left, Operand::Zero());
1445 DeoptimizeIf(eq, instr->environment()); 1445 DeoptimizeIf(eq, instr->environment());
1446 } 1446 }
1447 EmitSignedIntegerDivisionByConstant(result, 1447 EmitSignedIntegerDivisionByConstant(result,
1448 left, 1448 left,
1449 divisor, 1449 divisor,
1450 remainder, 1450 remainder,
1451 scratch, 1451 scratch,
1452 instr->environment()); 1452 instr->environment());
1453 // We performed a truncating division. Correct the result if necessary. 1453 // We performed a truncating division. Correct the result if necessary.
1454 __ cmp(remainder, Operand(0)); 1454 __ cmp(remainder, Operand::Zero());
1455 __ teq(remainder, Operand(divisor), ne); 1455 __ teq(remainder, Operand(divisor), ne);
1456 __ sub(result, result, Operand(1), LeaveCC, mi); 1456 __ sub(result, result, Operand(1), LeaveCC, mi);
1457 } else { 1457 } else {
1458 CpuFeatures::Scope scope(SUDIV); 1458 CpuFeatures::Scope scope(SUDIV);
1459 const Register right = ToRegister(instr->right()); 1459 const Register right = ToRegister(instr->right());
1460 1460
1461 // Check for x / 0. 1461 // Check for x / 0.
1462 __ cmp(right, Operand(0)); 1462 __ cmp(right, Operand::Zero());
1463 DeoptimizeIf(eq, instr->environment()); 1463 DeoptimizeIf(eq, instr->environment());
1464 1464
1465 // Check for (kMinInt / -1). 1465 // Check for (kMinInt / -1).
1466 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { 1466 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
1467 Label left_not_min_int; 1467 Label left_not_min_int;
1468 __ cmp(left, Operand(kMinInt)); 1468 __ cmp(left, Operand(kMinInt));
1469 __ b(ne, &left_not_min_int); 1469 __ b(ne, &left_not_min_int);
1470 __ cmp(right, Operand(-1)); 1470 __ cmp(right, Operand(-1));
1471 DeoptimizeIf(eq, instr->environment()); 1471 DeoptimizeIf(eq, instr->environment());
1472 __ bind(&left_not_min_int); 1472 __ bind(&left_not_min_int);
1473 } 1473 }
1474 1474
1475 // Check for (0 / -x) that will produce negative zero. 1475 // Check for (0 / -x) that will produce negative zero.
1476 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 1476 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
1477 __ cmp(right, Operand(0)); 1477 __ cmp(right, Operand::Zero());
1478 __ cmp(left, Operand(0), mi); 1478 __ cmp(left, Operand::Zero(), mi);
1479 // "right" can't be null because the code would have already been 1479 // "right" can't be null because the code would have already been
1480 // deoptimized. The Z flag is set only if (right < 0) and (left == 0). 1480 // deoptimized. The Z flag is set only if (right < 0) and (left == 0).
1481 // In this case we need to deoptimize to produce a -0. 1481 // In this case we need to deoptimize to produce a -0.
1482 DeoptimizeIf(eq, instr->environment()); 1482 DeoptimizeIf(eq, instr->environment());
1483 } 1483 }
1484 1484
1485 Label done; 1485 Label done;
1486 __ sdiv(result, left, right); 1486 __ sdiv(result, left, right);
1487 // If both operands have the same sign then we are done. 1487 // If both operands have the same sign then we are done.
1488 __ eor(remainder, left, Operand(right), SetCC); 1488 __ eor(remainder, left, Operand(right), SetCC);
1489 __ b(pl, &done); 1489 __ b(pl, &done);
1490 1490
1491 // Check if the result needs to be corrected. 1491 // Check if the result needs to be corrected.
1492 __ mls(remainder, result, right, left); 1492 __ mls(remainder, result, right, left);
1493 __ cmp(remainder, Operand(0)); 1493 __ cmp(remainder, Operand::Zero());
1494 __ sub(result, result, Operand(1), LeaveCC, ne); 1494 __ sub(result, result, Operand(1), LeaveCC, ne);
1495 1495
1496 __ bind(&done); 1496 __ bind(&done);
1497 } 1497 }
1498 } 1498 }
1499 1499
1500 1500
1501 void LCodeGen::DoDeferredBinaryOpStub(LPointerMap* pointer_map, 1501 void LCodeGen::DoDeferredBinaryOpStub(LPointerMap* pointer_map,
1502 LOperand* left_argument, 1502 LOperand* left_argument,
1503 LOperand* right_argument, 1503 LOperand* right_argument,
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1542 bool bailout_on_minus_zero = 1542 bool bailout_on_minus_zero =
1543 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero); 1543 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero);
1544 1544
1545 if (right_op->IsConstantOperand() && !can_overflow) { 1545 if (right_op->IsConstantOperand() && !can_overflow) {
1546 // Use optimized code for specific constants. 1546 // Use optimized code for specific constants.
1547 int32_t constant = ToInteger32(LConstantOperand::cast(right_op)); 1547 int32_t constant = ToInteger32(LConstantOperand::cast(right_op));
1548 1548
1549 if (bailout_on_minus_zero && (constant < 0)) { 1549 if (bailout_on_minus_zero && (constant < 0)) {
1550 // The case of a null constant will be handled separately. 1550 // The case of a null constant will be handled separately.
1551 // If constant is negative and left is null, the result should be -0. 1551 // If constant is negative and left is null, the result should be -0.
1552 __ cmp(left, Operand(0)); 1552 __ cmp(left, Operand::Zero());
1553 DeoptimizeIf(eq, instr->environment()); 1553 DeoptimizeIf(eq, instr->environment());
1554 } 1554 }
1555 1555
1556 switch (constant) { 1556 switch (constant) {
1557 case -1: 1557 case -1:
1558 __ rsb(result, left, Operand(0)); 1558 __ rsb(result, left, Operand::Zero());
1559 break; 1559 break;
1560 case 0: 1560 case 0:
1561 if (bailout_on_minus_zero) { 1561 if (bailout_on_minus_zero) {
1562 // If left is strictly negative and the constant is null, the 1562 // If left is strictly negative and the constant is null, the
1563 // result is -0. Deoptimize if required, otherwise return 0. 1563 // result is -0. Deoptimize if required, otherwise return 0.
1564 __ cmp(left, Operand(0)); 1564 __ cmp(left, Operand::Zero());
1565 DeoptimizeIf(mi, instr->environment()); 1565 DeoptimizeIf(mi, instr->environment());
1566 } 1566 }
1567 __ mov(result, Operand(0)); 1567 __ mov(result, Operand::Zero());
1568 break; 1568 break;
1569 case 1: 1569 case 1:
1570 __ Move(result, left); 1570 __ Move(result, left);
1571 break; 1571 break;
1572 default: 1572 default:
1573 // Multiplying by powers of two and powers of two plus or minus 1573 // Multiplying by powers of two and powers of two plus or minus
1574 // one can be done faster with shifted operands. 1574 // one can be done faster with shifted operands.
1575 // For other constants we emit standard code. 1575 // For other constants we emit standard code.
1576 int32_t mask = constant >> 31; 1576 int32_t mask = constant >> 31;
1577 uint32_t constant_abs = (constant + mask) ^ mask; 1577 uint32_t constant_abs = (constant + mask) ^ mask;
1578 1578
1579 if (IsPowerOf2(constant_abs) || 1579 if (IsPowerOf2(constant_abs) ||
1580 IsPowerOf2(constant_abs - 1) || 1580 IsPowerOf2(constant_abs - 1) ||
1581 IsPowerOf2(constant_abs + 1)) { 1581 IsPowerOf2(constant_abs + 1)) {
1582 if (IsPowerOf2(constant_abs)) { 1582 if (IsPowerOf2(constant_abs)) {
1583 int32_t shift = WhichPowerOf2(constant_abs); 1583 int32_t shift = WhichPowerOf2(constant_abs);
1584 __ mov(result, Operand(left, LSL, shift)); 1584 __ mov(result, Operand(left, LSL, shift));
1585 } else if (IsPowerOf2(constant_abs - 1)) { 1585 } else if (IsPowerOf2(constant_abs - 1)) {
1586 int32_t shift = WhichPowerOf2(constant_abs - 1); 1586 int32_t shift = WhichPowerOf2(constant_abs - 1);
1587 __ add(result, left, Operand(left, LSL, shift)); 1587 __ add(result, left, Operand(left, LSL, shift));
1588 } else if (IsPowerOf2(constant_abs + 1)) { 1588 } else if (IsPowerOf2(constant_abs + 1)) {
1589 int32_t shift = WhichPowerOf2(constant_abs + 1); 1589 int32_t shift = WhichPowerOf2(constant_abs + 1);
1590 __ rsb(result, left, Operand(left, LSL, shift)); 1590 __ rsb(result, left, Operand(left, LSL, shift));
1591 } 1591 }
1592 1592
1593 // Correct the sign of the result is the constant is negative. 1593 // Correct the sign of the result is the constant is negative.
1594 if (constant < 0) __ rsb(result, result, Operand(0)); 1594 if (constant < 0) __ rsb(result, result, Operand::Zero());
1595 1595
1596 } else { 1596 } else {
1597 // Generate standard code. 1597 // Generate standard code.
1598 __ mov(ip, Operand(constant)); 1598 __ mov(ip, Operand(constant));
1599 __ mul(result, left, ip); 1599 __ mul(result, left, ip);
1600 } 1600 }
1601 } 1601 }
1602 1602
1603 } else { 1603 } else {
1604 Register right = EmitLoadRegister(right_op, scratch); 1604 Register right = EmitLoadRegister(right_op, scratch);
1605 if (bailout_on_minus_zero) { 1605 if (bailout_on_minus_zero) {
1606 __ orr(ToRegister(instr->temp()), left, right); 1606 __ orr(ToRegister(instr->temp()), left, right);
1607 } 1607 }
1608 1608
1609 if (can_overflow) { 1609 if (can_overflow) {
1610 // scratch:result = left * right. 1610 // scratch:result = left * right.
1611 __ smull(result, scratch, left, right); 1611 __ smull(result, scratch, left, right);
1612 __ cmp(scratch, Operand(result, ASR, 31)); 1612 __ cmp(scratch, Operand(result, ASR, 31));
1613 DeoptimizeIf(ne, instr->environment()); 1613 DeoptimizeIf(ne, instr->environment());
1614 } else { 1614 } else {
1615 __ mul(result, left, right); 1615 __ mul(result, left, right);
1616 } 1616 }
1617 1617
1618 if (bailout_on_minus_zero) { 1618 if (bailout_on_minus_zero) {
1619 // Bail out if the result is supposed to be negative zero. 1619 // Bail out if the result is supposed to be negative zero.
1620 Label done; 1620 Label done;
1621 __ cmp(result, Operand(0)); 1621 __ cmp(result, Operand::Zero());
1622 __ b(ne, &done); 1622 __ b(ne, &done);
1623 __ cmp(ToRegister(instr->temp()), Operand(0)); 1623 __ cmp(ToRegister(instr->temp()), Operand::Zero());
1624 DeoptimizeIf(mi, instr->environment()); 1624 DeoptimizeIf(mi, instr->environment());
1625 __ bind(&done); 1625 __ bind(&done);
1626 } 1626 }
1627 } 1627 }
1628 } 1628 }
1629 1629
1630 1630
1631 void LCodeGen::DoBitI(LBitI* instr) { 1631 void LCodeGen::DoBitI(LBitI* instr) {
1632 LOperand* left_op = instr->left(); 1632 LOperand* left_op = instr->left();
1633 LOperand* right_op = instr->right(); 1633 LOperand* right_op = instr->right();
(...skipping 459 matching lines...) Expand 10 before | Expand all | Expand 10 after
2093 } 2093 }
2094 2094
2095 2095
2096 void LCodeGen::DoBranch(LBranch* instr) { 2096 void LCodeGen::DoBranch(LBranch* instr) {
2097 int true_block = chunk_->LookupDestination(instr->true_block_id()); 2097 int true_block = chunk_->LookupDestination(instr->true_block_id());
2098 int false_block = chunk_->LookupDestination(instr->false_block_id()); 2098 int false_block = chunk_->LookupDestination(instr->false_block_id());
2099 2099
2100 Representation r = instr->hydrogen()->value()->representation(); 2100 Representation r = instr->hydrogen()->value()->representation();
2101 if (r.IsInteger32()) { 2101 if (r.IsInteger32()) {
2102 Register reg = ToRegister(instr->value()); 2102 Register reg = ToRegister(instr->value());
2103 __ cmp(reg, Operand(0)); 2103 __ cmp(reg, Operand::Zero());
2104 EmitBranch(true_block, false_block, ne); 2104 EmitBranch(true_block, false_block, ne);
2105 } else if (r.IsDouble()) { 2105 } else if (r.IsDouble()) {
2106 CpuFeatures::Scope scope(VFP2); 2106 CpuFeatures::Scope scope(VFP2);
2107 DwVfpRegister reg = ToDoubleRegister(instr->value()); 2107 DwVfpRegister reg = ToDoubleRegister(instr->value());
2108 Register scratch = scratch0(); 2108 Register scratch = scratch0();
2109 2109
2110 // Test the double value. Zero and NaN are false. 2110 // Test the double value. Zero and NaN are false.
2111 __ VFPCompareAndLoadFlags(reg, 0.0, scratch); 2111 __ VFPCompareAndLoadFlags(reg, 0.0, scratch);
2112 __ tst(scratch, Operand(kVFPZConditionFlagBit | kVFPVConditionFlagBit)); 2112 __ tst(scratch, Operand(kVFPZConditionFlagBit | kVFPVConditionFlagBit));
2113 EmitBranch(true_block, false_block, eq); 2113 EmitBranch(true_block, false_block, eq);
2114 } else { 2114 } else {
2115 ASSERT(r.IsTagged()); 2115 ASSERT(r.IsTagged());
2116 Register reg = ToRegister(instr->value()); 2116 Register reg = ToRegister(instr->value());
2117 HType type = instr->hydrogen()->value()->type(); 2117 HType type = instr->hydrogen()->value()->type();
2118 if (type.IsBoolean()) { 2118 if (type.IsBoolean()) {
2119 __ CompareRoot(reg, Heap::kTrueValueRootIndex); 2119 __ CompareRoot(reg, Heap::kTrueValueRootIndex);
2120 EmitBranch(true_block, false_block, eq); 2120 EmitBranch(true_block, false_block, eq);
2121 } else if (type.IsSmi()) { 2121 } else if (type.IsSmi()) {
2122 __ cmp(reg, Operand(0)); 2122 __ cmp(reg, Operand::Zero());
2123 EmitBranch(true_block, false_block, ne); 2123 EmitBranch(true_block, false_block, ne);
2124 } else { 2124 } else {
2125 Label* true_label = chunk_->GetAssemblyLabel(true_block); 2125 Label* true_label = chunk_->GetAssemblyLabel(true_block);
2126 Label* false_label = chunk_->GetAssemblyLabel(false_block); 2126 Label* false_label = chunk_->GetAssemblyLabel(false_block);
2127 2127
2128 ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types(); 2128 ToBooleanStub::Types expected = instr->hydrogen()->expected_input_types();
2129 // Avoid deopts in the case where we've never executed this path before. 2129 // Avoid deopts in the case where we've never executed this path before.
2130 if (expected.IsEmpty()) expected = ToBooleanStub::all_types(); 2130 if (expected.IsEmpty()) expected = ToBooleanStub::all_types();
2131 2131
2132 if (expected.Contains(ToBooleanStub::UNDEFINED)) { 2132 if (expected.Contains(ToBooleanStub::UNDEFINED)) {
2133 // undefined -> false. 2133 // undefined -> false.
2134 __ CompareRoot(reg, Heap::kUndefinedValueRootIndex); 2134 __ CompareRoot(reg, Heap::kUndefinedValueRootIndex);
2135 __ b(eq, false_label); 2135 __ b(eq, false_label);
2136 } 2136 }
2137 if (expected.Contains(ToBooleanStub::BOOLEAN)) { 2137 if (expected.Contains(ToBooleanStub::BOOLEAN)) {
2138 // Boolean -> its value. 2138 // Boolean -> its value.
2139 __ CompareRoot(reg, Heap::kTrueValueRootIndex); 2139 __ CompareRoot(reg, Heap::kTrueValueRootIndex);
2140 __ b(eq, true_label); 2140 __ b(eq, true_label);
2141 __ CompareRoot(reg, Heap::kFalseValueRootIndex); 2141 __ CompareRoot(reg, Heap::kFalseValueRootIndex);
2142 __ b(eq, false_label); 2142 __ b(eq, false_label);
2143 } 2143 }
2144 if (expected.Contains(ToBooleanStub::NULL_TYPE)) { 2144 if (expected.Contains(ToBooleanStub::NULL_TYPE)) {
2145 // 'null' -> false. 2145 // 'null' -> false.
2146 __ CompareRoot(reg, Heap::kNullValueRootIndex); 2146 __ CompareRoot(reg, Heap::kNullValueRootIndex);
2147 __ b(eq, false_label); 2147 __ b(eq, false_label);
2148 } 2148 }
2149 2149
2150 if (expected.Contains(ToBooleanStub::SMI)) { 2150 if (expected.Contains(ToBooleanStub::SMI)) {
2151 // Smis: 0 -> false, all other -> true. 2151 // Smis: 0 -> false, all other -> true.
2152 __ cmp(reg, Operand(0)); 2152 __ cmp(reg, Operand::Zero());
2153 __ b(eq, false_label); 2153 __ b(eq, false_label);
2154 __ JumpIfSmi(reg, true_label); 2154 __ JumpIfSmi(reg, true_label);
2155 } else if (expected.NeedsMap()) { 2155 } else if (expected.NeedsMap()) {
2156 // If we need a map later and have a Smi -> deopt. 2156 // If we need a map later and have a Smi -> deopt.
2157 __ tst(reg, Operand(kSmiTagMask)); 2157 __ tst(reg, Operand(kSmiTagMask));
2158 DeoptimizeIf(eq, instr->environment()); 2158 DeoptimizeIf(eq, instr->environment());
2159 } 2159 }
2160 2160
2161 const Register map = scratch0(); 2161 const Register map = scratch0();
2162 if (expected.NeedsMap()) { 2162 if (expected.NeedsMap()) {
(...skipping 12 matching lines...) Expand all
2175 __ CompareInstanceType(map, ip, FIRST_SPEC_OBJECT_TYPE); 2175 __ CompareInstanceType(map, ip, FIRST_SPEC_OBJECT_TYPE);
2176 __ b(ge, true_label); 2176 __ b(ge, true_label);
2177 } 2177 }
2178 2178
2179 if (expected.Contains(ToBooleanStub::STRING)) { 2179 if (expected.Contains(ToBooleanStub::STRING)) {
2180 // String value -> false iff empty. 2180 // String value -> false iff empty.
2181 Label not_string; 2181 Label not_string;
2182 __ CompareInstanceType(map, ip, FIRST_NONSTRING_TYPE); 2182 __ CompareInstanceType(map, ip, FIRST_NONSTRING_TYPE);
2183 __ b(ge, &not_string); 2183 __ b(ge, &not_string);
2184 __ ldr(ip, FieldMemOperand(reg, String::kLengthOffset)); 2184 __ ldr(ip, FieldMemOperand(reg, String::kLengthOffset));
2185 __ cmp(ip, Operand(0)); 2185 __ cmp(ip, Operand::Zero());
2186 __ b(ne, true_label); 2186 __ b(ne, true_label);
2187 __ b(false_label); 2187 __ b(false_label);
2188 __ bind(&not_string); 2188 __ bind(&not_string);
2189 } 2189 }
2190 2190
2191 if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) { 2191 if (expected.Contains(ToBooleanStub::HEAP_NUMBER)) {
2192 CpuFeatures::Scope scope(VFP2); 2192 CpuFeatures::Scope scope(VFP2);
2193 // heap number -> false iff +0, -0, or NaN. 2193 // heap number -> false iff +0, -0, or NaN.
2194 DwVfpRegister dbl_scratch = double_scratch0(); 2194 DwVfpRegister dbl_scratch = double_scratch0();
2195 Label not_heap_number; 2195 Label not_heap_number;
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after
2470 } 2470 }
2471 2471
2472 2472
2473 void LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) { 2473 void LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) {
2474 Token::Value op = instr->op(); 2474 Token::Value op = instr->op();
2475 int true_block = chunk_->LookupDestination(instr->true_block_id()); 2475 int true_block = chunk_->LookupDestination(instr->true_block_id());
2476 int false_block = chunk_->LookupDestination(instr->false_block_id()); 2476 int false_block = chunk_->LookupDestination(instr->false_block_id());
2477 2477
2478 Handle<Code> ic = CompareIC::GetUninitialized(op); 2478 Handle<Code> ic = CompareIC::GetUninitialized(op);
2479 CallCode(ic, RelocInfo::CODE_TARGET, instr); 2479 CallCode(ic, RelocInfo::CODE_TARGET, instr);
2480 __ cmp(r0, Operand(0)); // This instruction also signals no smi code inlined. 2480 // This instruction also signals no smi code inlined.
2481 __ cmp(r0, Operand::Zero());
2481 2482
2482 Condition condition = ComputeCompareCondition(op); 2483 Condition condition = ComputeCompareCondition(op);
2483 2484
2484 EmitBranch(true_block, false_block, condition); 2485 EmitBranch(true_block, false_block, condition);
2485 } 2486 }
2486 2487
2487 2488
2488 static InstanceType TestType(HHasInstanceTypeAndBranch* instr) { 2489 static InstanceType TestType(HHasInstanceTypeAndBranch* instr) {
2489 InstanceType from = instr->from(); 2490 InstanceType from = instr->from();
2490 InstanceType to = instr->to(); 2491 InstanceType to = instr->to();
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
2644 } 2645 }
2645 2646
2646 2647
2647 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { 2648 void LCodeGen::DoInstanceOf(LInstanceOf* instr) {
2648 ASSERT(ToRegister(instr->left()).is(r0)); // Object is in r0. 2649 ASSERT(ToRegister(instr->left()).is(r0)); // Object is in r0.
2649 ASSERT(ToRegister(instr->right()).is(r1)); // Function is in r1. 2650 ASSERT(ToRegister(instr->right()).is(r1)); // Function is in r1.
2650 2651
2651 InstanceofStub stub(InstanceofStub::kArgsInRegisters); 2652 InstanceofStub stub(InstanceofStub::kArgsInRegisters);
2652 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr); 2653 CallCode(stub.GetCode(), RelocInfo::CODE_TARGET, instr);
2653 2654
2654 __ cmp(r0, Operand(0)); 2655 __ cmp(r0, Operand::Zero());
2655 __ mov(r0, Operand(factory()->false_value()), LeaveCC, ne); 2656 __ mov(r0, Operand(factory()->false_value()), LeaveCC, ne);
2656 __ mov(r0, Operand(factory()->true_value()), LeaveCC, eq); 2657 __ mov(r0, Operand(factory()->true_value()), LeaveCC, eq);
2657 } 2658 }
2658 2659
2659 2660
2660 void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { 2661 void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) {
2661 class DeferredInstanceOfKnownGlobal: public LDeferredCode { 2662 class DeferredInstanceOfKnownGlobal: public LDeferredCode {
2662 public: 2663 public:
2663 DeferredInstanceOfKnownGlobal(LCodeGen* codegen, 2664 DeferredInstanceOfKnownGlobal(LCodeGen* codegen,
2664 LInstanceOfKnownGlobal* instr) 2665 LInstanceOfKnownGlobal* instr)
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
2788 // restore all registers. 2789 // restore all registers.
2789 __ StoreToSafepointRegisterSlot(result, result); 2790 __ StoreToSafepointRegisterSlot(result, result);
2790 } 2791 }
2791 2792
2792 2793
2793 void LCodeGen::DoCmpT(LCmpT* instr) { 2794 void LCodeGen::DoCmpT(LCmpT* instr) {
2794 Token::Value op = instr->op(); 2795 Token::Value op = instr->op();
2795 2796
2796 Handle<Code> ic = CompareIC::GetUninitialized(op); 2797 Handle<Code> ic = CompareIC::GetUninitialized(op);
2797 CallCode(ic, RelocInfo::CODE_TARGET, instr); 2798 CallCode(ic, RelocInfo::CODE_TARGET, instr);
2798 __ cmp(r0, Operand(0)); // This instruction also signals no smi code inlined. 2799 // This instruction also signals no smi code inlined.
2800 __ cmp(r0, Operand::Zero());
2799 2801
2800 Condition condition = ComputeCompareCondition(op); 2802 Condition condition = ComputeCompareCondition(op);
2801 __ LoadRoot(ToRegister(instr->result()), 2803 __ LoadRoot(ToRegister(instr->result()),
2802 Heap::kTrueValueRootIndex, 2804 Heap::kTrueValueRootIndex,
2803 condition); 2805 condition);
2804 __ LoadRoot(ToRegister(instr->result()), 2806 __ LoadRoot(ToRegister(instr->result()),
2805 Heap::kFalseValueRootIndex, 2807 Heap::kFalseValueRootIndex,
2806 NegateCondition(condition)); 2808 NegateCondition(condition));
2807 } 2809 }
2808 2810
(...skipping 719 matching lines...) Expand 10 before | Expand all | Expand 10 after
3528 // number of arguments. 3530 // number of arguments.
3529 __ push(receiver); 3531 __ push(receiver);
3530 __ mov(receiver, length); 3532 __ mov(receiver, length);
3531 // The arguments are at a one pointer size offset from elements. 3533 // The arguments are at a one pointer size offset from elements.
3532 __ add(elements, elements, Operand(1 * kPointerSize)); 3534 __ add(elements, elements, Operand(1 * kPointerSize));
3533 3535
3534 // Loop through the arguments pushing them onto the execution 3536 // Loop through the arguments pushing them onto the execution
3535 // stack. 3537 // stack.
3536 Label invoke, loop; 3538 Label invoke, loop;
3537 // length is a small non-negative integer, due to the test above. 3539 // length is a small non-negative integer, due to the test above.
3538 __ cmp(length, Operand(0)); 3540 __ cmp(length, Operand::Zero());
3539 __ b(eq, &invoke); 3541 __ b(eq, &invoke);
3540 __ bind(&loop); 3542 __ bind(&loop);
3541 __ ldr(scratch, MemOperand(elements, length, LSL, 2)); 3543 __ ldr(scratch, MemOperand(elements, length, LSL, 2));
3542 __ push(scratch); 3544 __ push(scratch);
3543 __ sub(length, length, Operand(1), SetCC); 3545 __ sub(length, length, Operand(1), SetCC);
3544 __ b(ne, &loop); 3546 __ b(ne, &loop);
3545 3547
3546 __ bind(&invoke); 3548 __ bind(&invoke);
3547 ASSERT(instr->HasPointerMap()); 3549 ASSERT(instr->HasPointerMap());
3548 LPointerMap* pointers = instr->pointer_map(); 3550 LPointerMap* pointers = instr->pointer_map();
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
3732 __ StoreToSafepointRegisterSlot(tmp1, result); 3734 __ StoreToSafepointRegisterSlot(tmp1, result);
3733 } 3735 }
3734 3736
3735 __ bind(&done); 3737 __ bind(&done);
3736 } 3738 }
3737 3739
3738 3740
3739 void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) { 3741 void LCodeGen::EmitIntegerMathAbs(LUnaryMathOperation* instr) {
3740 Register input = ToRegister(instr->value()); 3742 Register input = ToRegister(instr->value());
3741 Register result = ToRegister(instr->result()); 3743 Register result = ToRegister(instr->result());
3742 __ cmp(input, Operand(0)); 3744 __ cmp(input, Operand::Zero());
3743 __ Move(result, input, pl); 3745 __ Move(result, input, pl);
3744 // We can make rsb conditional because the previous cmp instruction 3746 // We can make rsb conditional because the previous cmp instruction
3745 // will clear the V (overflow) flag and rsb won't set this flag 3747 // will clear the V (overflow) flag and rsb won't set this flag
3746 // if input is positive. 3748 // if input is positive.
3747 __ rsb(result, input, Operand(0), SetCC, mi); 3749 __ rsb(result, input, Operand::Zero(), SetCC, mi);
3748 // Deoptimize on overflow. 3750 // Deoptimize on overflow.
3749 DeoptimizeIf(vs, instr->environment()); 3751 DeoptimizeIf(vs, instr->environment());
3750 } 3752 }
3751 3753
3752 3754
3753 void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) { 3755 void LCodeGen::DoMathAbs(LUnaryMathOperation* instr) {
3754 CpuFeatures::Scope scope(VFP2); 3756 CpuFeatures::Scope scope(VFP2);
3755 // Class for deferred case. 3757 // Class for deferred case.
3756 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode { 3758 class DeferredMathAbsTaggedHeapNumber: public LDeferredCode {
3757 public: 3759 public:
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
3796 __ EmitVFPTruncate(kRoundToMinusInf, 3798 __ EmitVFPTruncate(kRoundToMinusInf,
3797 result, 3799 result,
3798 input, 3800 input,
3799 scratch, 3801 scratch,
3800 double_scratch0()); 3802 double_scratch0());
3801 DeoptimizeIf(ne, instr->environment()); 3803 DeoptimizeIf(ne, instr->environment());
3802 3804
3803 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 3805 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
3804 // Test for -0. 3806 // Test for -0.
3805 Label done; 3807 Label done;
3806 __ cmp(result, Operand(0)); 3808 __ cmp(result, Operand::Zero());
3807 __ b(ne, &done); 3809 __ b(ne, &done);
3808 __ vmov(scratch, input.high()); 3810 __ vmov(scratch, input.high());
3809 __ tst(scratch, Operand(HeapNumber::kSignMask)); 3811 __ tst(scratch, Operand(HeapNumber::kSignMask));
3810 DeoptimizeIf(ne, instr->environment()); 3812 DeoptimizeIf(ne, instr->environment());
3811 __ bind(&done); 3813 __ bind(&done);
3812 } 3814 }
3813 } 3815 }
3814 3816
3815 3817
3816 void LCodeGen::DoMathRound(LUnaryMathOperation* instr) { 3818 void LCodeGen::DoMathRound(LUnaryMathOperation* instr) {
3817 CpuFeatures::Scope scope(VFP2); 3819 CpuFeatures::Scope scope(VFP2);
3818 DwVfpRegister input = ToDoubleRegister(instr->value()); 3820 DwVfpRegister input = ToDoubleRegister(instr->value());
3819 Register result = ToRegister(instr->result()); 3821 Register result = ToRegister(instr->result());
3820 DwVfpRegister double_scratch1 = ToDoubleRegister(instr->temp()); 3822 DwVfpRegister double_scratch1 = ToDoubleRegister(instr->temp());
3821 Register scratch = scratch0(); 3823 Register scratch = scratch0();
3822 Label done, check_sign_on_zero; 3824 Label done, check_sign_on_zero;
3823 3825
3824 // Extract exponent bits. 3826 // Extract exponent bits.
3825 __ vmov(result, input.high()); 3827 __ vmov(result, input.high());
3826 __ ubfx(scratch, 3828 __ ubfx(scratch,
3827 result, 3829 result,
3828 HeapNumber::kExponentShift, 3830 HeapNumber::kExponentShift,
3829 HeapNumber::kExponentBits); 3831 HeapNumber::kExponentBits);
3830 3832
3831 // If the number is in ]-0.5, +0.5[, the result is +/- 0. 3833 // If the number is in ]-0.5, +0.5[, the result is +/- 0.
3832 __ cmp(scratch, Operand(HeapNumber::kExponentBias - 2)); 3834 __ cmp(scratch, Operand(HeapNumber::kExponentBias - 2));
3833 __ mov(result, Operand(0), LeaveCC, le); 3835 __ mov(result, Operand::Zero(), LeaveCC, le);
3834 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 3836 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
3835 __ b(le, &check_sign_on_zero); 3837 __ b(le, &check_sign_on_zero);
3836 } else { 3838 } else {
3837 __ b(le, &done); 3839 __ b(le, &done);
3838 } 3840 }
3839 3841
3840 // The following conversion will not work with numbers 3842 // The following conversion will not work with numbers
3841 // outside of ]-2^32, 2^32[. 3843 // outside of ]-2^32, 2^32[.
3842 __ cmp(scratch, Operand(HeapNumber::kExponentBias + 32)); 3844 __ cmp(scratch, Operand(HeapNumber::kExponentBias + 32));
3843 DeoptimizeIf(ge, instr->environment()); 3845 DeoptimizeIf(ge, instr->environment());
3844 3846
3845 __ Vmov(double_scratch0(), 0.5, scratch); 3847 __ Vmov(double_scratch0(), 0.5, scratch);
3846 __ vadd(double_scratch0(), input, double_scratch0()); 3848 __ vadd(double_scratch0(), input, double_scratch0());
3847 3849
3848 // Save the original sign for later comparison. 3850 // Save the original sign for later comparison.
3849 __ and_(scratch, result, Operand(HeapNumber::kSignMask)); 3851 __ and_(scratch, result, Operand(HeapNumber::kSignMask));
3850 3852
3851 // Check sign of the result: if the sign changed, the input 3853 // Check sign of the result: if the sign changed, the input
3852 // value was in ]0.5, 0[ and the result should be -0. 3854 // value was in ]0.5, 0[ and the result should be -0.
3853 __ vmov(result, double_scratch0().high()); 3855 __ vmov(result, double_scratch0().high());
3854 __ eor(result, result, Operand(scratch), SetCC); 3856 __ eor(result, result, Operand(scratch), SetCC);
3855 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 3857 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
3856 DeoptimizeIf(mi, instr->environment()); 3858 DeoptimizeIf(mi, instr->environment());
3857 } else { 3859 } else {
3858 __ mov(result, Operand(0), LeaveCC, mi); 3860 __ mov(result, Operand::Zero(), LeaveCC, mi);
3859 __ b(mi, &done); 3861 __ b(mi, &done);
3860 } 3862 }
3861 3863
3862 __ EmitVFPTruncate(kRoundToMinusInf, 3864 __ EmitVFPTruncate(kRoundToMinusInf,
3863 result, 3865 result,
3864 double_scratch0(), 3866 double_scratch0(),
3865 scratch, 3867 scratch,
3866 double_scratch1); 3868 double_scratch1);
3867 DeoptimizeIf(ne, instr->environment()); 3869 DeoptimizeIf(ne, instr->environment());
3868 3870
3869 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 3871 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
3870 // Test for -0. 3872 // Test for -0.
3871 __ cmp(result, Operand(0)); 3873 __ cmp(result, Operand::Zero());
3872 __ b(ne, &done); 3874 __ b(ne, &done);
3873 __ bind(&check_sign_on_zero); 3875 __ bind(&check_sign_on_zero);
3874 __ vmov(scratch, input.high()); 3876 __ vmov(scratch, input.high());
3875 __ tst(scratch, Operand(HeapNumber::kSignMask)); 3877 __ tst(scratch, Operand(HeapNumber::kSignMask));
3876 DeoptimizeIf(ne, instr->environment()); 3878 DeoptimizeIf(ne, instr->environment());
3877 } 3879 }
3878 __ bind(&done); 3880 __ bind(&done);
3879 } 3881 }
3880 3882
3881 3883
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
3965 STATIC_ASSERT(kPointerSize == kSeedSize); 3967 STATIC_ASSERT(kPointerSize == kSeedSize);
3966 3968
3967 __ ldr(r0, FieldMemOperand(r0, GlobalObject::kNativeContextOffset)); 3969 __ ldr(r0, FieldMemOperand(r0, GlobalObject::kNativeContextOffset));
3968 static const int kRandomSeedOffset = 3970 static const int kRandomSeedOffset =
3969 FixedArray::kHeaderSize + Context::RANDOM_SEED_INDEX * kPointerSize; 3971 FixedArray::kHeaderSize + Context::RANDOM_SEED_INDEX * kPointerSize;
3970 __ ldr(r2, FieldMemOperand(r0, kRandomSeedOffset)); 3972 __ ldr(r2, FieldMemOperand(r0, kRandomSeedOffset));
3971 // r2: FixedArray of the native context's random seeds 3973 // r2: FixedArray of the native context's random seeds
3972 3974
3973 // Load state[0]. 3975 // Load state[0].
3974 __ ldr(r1, FieldMemOperand(r2, ByteArray::kHeaderSize)); 3976 __ ldr(r1, FieldMemOperand(r2, ByteArray::kHeaderSize));
3975 __ cmp(r1, Operand(0)); 3977 __ cmp(r1, Operand::Zero());
3976 __ b(eq, deferred->entry()); 3978 __ b(eq, deferred->entry());
3977 // Load state[1]. 3979 // Load state[1].
3978 __ ldr(r0, FieldMemOperand(r2, ByteArray::kHeaderSize + kSeedSize)); 3980 __ ldr(r0, FieldMemOperand(r2, ByteArray::kHeaderSize + kSeedSize));
3979 // r1: state[0]. 3981 // r1: state[0].
3980 // r0: state[1]. 3982 // r0: state[1].
3981 3983
3982 // state[0] = 18273 * (state[0] & 0xFFFF) + (state[0] >> 16) 3984 // state[0] = 18273 * (state[0] & 0xFFFF) + (state[0] >> 16)
3983 __ and_(r3, r1, Operand(0xFFFF)); 3985 __ and_(r3, r1, Operand(0xFFFF));
3984 __ mov(r4, Operand(18273)); 3986 __ mov(r4, Operand(18273));
3985 __ mul(r3, r3, r4); 3987 __ mul(r3, r3, r4);
(...skipping 14 matching lines...) Expand all
4000 __ add(r0, r0, Operand(r1, LSL, 14)); 4002 __ add(r0, r0, Operand(r1, LSL, 14));
4001 4003
4002 __ bind(deferred->exit()); 4004 __ bind(deferred->exit());
4003 // 0x41300000 is the top half of 1.0 x 2^20 as a double. 4005 // 0x41300000 is the top half of 1.0 x 2^20 as a double.
4004 // Create this constant using mov/orr to avoid PC relative load. 4006 // Create this constant using mov/orr to avoid PC relative load.
4005 __ mov(r1, Operand(0x41000000)); 4007 __ mov(r1, Operand(0x41000000));
4006 __ orr(r1, r1, Operand(0x300000)); 4008 __ orr(r1, r1, Operand(0x300000));
4007 // Move 0x41300000xxxxxxxx (x = random bits) to VFP. 4009 // Move 0x41300000xxxxxxxx (x = random bits) to VFP.
4008 __ vmov(d7, r0, r1); 4010 __ vmov(d7, r0, r1);
4009 // Move 0x4130000000000000 to VFP. 4011 // Move 0x4130000000000000 to VFP.
4010 __ mov(r0, Operand(0, RelocInfo::NONE32)); 4012 __ mov(r0, Operand::Zero());
4011 __ vmov(d8, r0, r1); 4013 __ vmov(d8, r0, r1);
4012 // Subtract and store the result in the heap number. 4014 // Subtract and store the result in the heap number.
4013 __ vsub(d7, d7, d8); 4015 __ vsub(d7, d7, d8);
4014 } 4016 }
4015 4017
4016 4018
4017 void LCodeGen::DoDeferredRandom(LRandom* instr) { 4019 void LCodeGen::DoDeferredRandom(LRandom* instr) {
4018 __ PrepareCallCFunction(1, scratch0()); 4020 __ PrepareCallCFunction(1, scratch0());
4019 __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1); 4021 __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1);
4020 // Return value is in r0. 4022 // Return value is in r0.
(...skipping 554 matching lines...) Expand 10 before | Expand all | Expand 10 after
4575 4577
4576 4578
4577 void LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) { 4579 void LCodeGen::DoDeferredStringCharCodeAt(LStringCharCodeAt* instr) {
4578 Register string = ToRegister(instr->string()); 4580 Register string = ToRegister(instr->string());
4579 Register result = ToRegister(instr->result()); 4581 Register result = ToRegister(instr->result());
4580 Register scratch = scratch0(); 4582 Register scratch = scratch0();
4581 4583
4582 // TODO(3095996): Get rid of this. For now, we need to make the 4584 // TODO(3095996): Get rid of this. For now, we need to make the
4583 // result register contain a valid pointer because it is already 4585 // result register contain a valid pointer because it is already
4584 // contained in the register pointer map. 4586 // contained in the register pointer map.
4585 __ mov(result, Operand(0)); 4587 __ mov(result, Operand::Zero());
4586 4588
4587 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); 4589 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
4588 __ push(string); 4590 __ push(string);
4589 // Push the index as a smi. This is safe because of the checks in 4591 // Push the index as a smi. This is safe because of the checks in
4590 // DoStringCharCodeAt above. 4592 // DoStringCharCodeAt above.
4591 if (instr->index()->IsConstantOperand()) { 4593 if (instr->index()->IsConstantOperand()) {
4592 int const_index = ToInteger32(LConstantOperand::cast(instr->index())); 4594 int const_index = ToInteger32(LConstantOperand::cast(instr->index()));
4593 __ mov(scratch, Operand(Smi::FromInt(const_index))); 4595 __ mov(scratch, Operand(Smi::FromInt(const_index)));
4594 __ push(scratch); 4596 __ push(scratch);
4595 } else { 4597 } else {
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
4635 } 4637 }
4636 4638
4637 4639
4638 void LCodeGen::DoDeferredStringCharFromCode(LStringCharFromCode* instr) { 4640 void LCodeGen::DoDeferredStringCharFromCode(LStringCharFromCode* instr) {
4639 Register char_code = ToRegister(instr->char_code()); 4641 Register char_code = ToRegister(instr->char_code());
4640 Register result = ToRegister(instr->result()); 4642 Register result = ToRegister(instr->result());
4641 4643
4642 // TODO(3095996): Get rid of this. For now, we need to make the 4644 // TODO(3095996): Get rid of this. For now, we need to make the
4643 // result register contain a valid pointer because it is already 4645 // result register contain a valid pointer because it is already
4644 // contained in the register pointer map. 4646 // contained in the register pointer map.
4645 __ mov(result, Operand(0)); 4647 __ mov(result, Operand::Zero());
4646 4648
4647 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); 4649 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
4648 __ SmiTag(char_code); 4650 __ SmiTag(char_code);
4649 __ push(char_code); 4651 __ push(char_code);
4650 CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr); 4652 CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr);
4651 __ StoreToSafepointRegisterSlot(r0, result); 4653 __ StoreToSafepointRegisterSlot(r0, result);
4652 } 4654 }
4653 4655
4654 4656
4655 void LCodeGen::DoStringLength(LStringLength* instr) { 4657 void LCodeGen::DoStringLength(LStringLength* instr) {
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
4756 const int mantissa_shift_for_hi_word = 4758 const int mantissa_shift_for_hi_word =
4757 meaningful_bits - HeapNumber::kMantissaBitsInTopWord; 4759 meaningful_bits - HeapNumber::kMantissaBitsInTopWord;
4758 const int mantissa_shift_for_lo_word = 4760 const int mantissa_shift_for_lo_word =
4759 kBitsPerInt - mantissa_shift_for_hi_word; 4761 kBitsPerInt - mantissa_shift_for_hi_word;
4760 masm->mov(scratch, Operand(biased_exponent << HeapNumber::kExponentShift)); 4762 masm->mov(scratch, Operand(biased_exponent << HeapNumber::kExponentShift));
4761 if (mantissa_shift_for_hi_word > 0) { 4763 if (mantissa_shift_for_hi_word > 0) {
4762 masm->mov(loword, Operand(hiword, LSL, mantissa_shift_for_lo_word)); 4764 masm->mov(loword, Operand(hiword, LSL, mantissa_shift_for_lo_word));
4763 masm->orr(hiword, scratch, 4765 masm->orr(hiword, scratch,
4764 Operand(hiword, LSR, mantissa_shift_for_hi_word)); 4766 Operand(hiword, LSR, mantissa_shift_for_hi_word));
4765 } else { 4767 } else {
4766 masm->mov(loword, Operand(0, RelocInfo::NONE32)); 4768 masm->mov(loword, Operand::Zero());
4767 masm->orr(hiword, scratch, 4769 masm->orr(hiword, scratch,
4768 Operand(hiword, LSL, -mantissa_shift_for_hi_word)); 4770 Operand(hiword, LSL, -mantissa_shift_for_hi_word));
4769 } 4771 }
4770 4772
4771 // If least significant bit of biased exponent was not 1 it was corrupted 4773 // If least significant bit of biased exponent was not 1 it was corrupted
4772 // by most significant bit of mantissa so we should fix that. 4774 // by most significant bit of mantissa so we should fix that.
4773 if (!(biased_exponent & 1)) { 4775 if (!(biased_exponent & 1)) {
4774 masm->bic(hiword, hiword, Operand(1 << HeapNumber::kExponentShift)); 4776 masm->bic(hiword, hiword, Operand(1 << HeapNumber::kExponentShift));
4775 } 4777 }
4776 } 4778 }
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
4834 __ Move(dst, r5); 4836 __ Move(dst, r5);
4835 __ b(&done); 4837 __ b(&done);
4836 } 4838 }
4837 4839
4838 // Slow case: Call the runtime system to do the number allocation. 4840 // Slow case: Call the runtime system to do the number allocation.
4839 __ bind(&slow); 4841 __ bind(&slow);
4840 4842
4841 // TODO(3095996): Put a valid pointer value in the stack slot where the result 4843 // TODO(3095996): Put a valid pointer value in the stack slot where the result
4842 // register is stored, as this register is in the pointer map, but contains an 4844 // register is stored, as this register is in the pointer map, but contains an
4843 // integer value. 4845 // integer value.
4844 __ mov(ip, Operand(0)); 4846 __ mov(ip, Operand::Zero());
4845 __ StoreToSafepointRegisterSlot(ip, dst); 4847 __ StoreToSafepointRegisterSlot(ip, dst);
4846 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); 4848 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr);
4847 __ Move(dst, r0); 4849 __ Move(dst, r0);
4848 __ sub(dst, dst, Operand(kHeapObjectTag)); 4850 __ sub(dst, dst, Operand(kHeapObjectTag));
4849 4851
4850 // Done. Put the value in dbl_scratch into the value of the allocated heap 4852 // Done. Put the value in dbl_scratch into the value of the allocated heap
4851 // number. 4853 // number.
4852 __ bind(&done); 4854 __ bind(&done);
4853 if (CpuFeatures::IsSupported(VFP2)) { 4855 if (CpuFeatures::IsSupported(VFP2)) {
4854 CpuFeatures::Scope scope(VFP2); 4856 CpuFeatures::Scope scope(VFP2);
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
4899 // Now that we have finished with the object's real address tag it 4901 // Now that we have finished with the object's real address tag it
4900 __ add(reg, reg, Operand(kHeapObjectTag)); 4902 __ add(reg, reg, Operand(kHeapObjectTag));
4901 } 4903 }
4902 4904
4903 4905
4904 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) { 4906 void LCodeGen::DoDeferredNumberTagD(LNumberTagD* instr) {
4905 // TODO(3095996): Get rid of this. For now, we need to make the 4907 // TODO(3095996): Get rid of this. For now, we need to make the
4906 // result register contain a valid pointer because it is already 4908 // result register contain a valid pointer because it is already
4907 // contained in the register pointer map. 4909 // contained in the register pointer map.
4908 Register reg = ToRegister(instr->result()); 4910 Register reg = ToRegister(instr->result());
4909 __ mov(reg, Operand(0)); 4911 __ mov(reg, Operand::Zero());
4910 4912
4911 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); 4913 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
4912 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr); 4914 CallRuntimeFromDeferred(Runtime::kAllocateHeapNumber, 0, instr);
4913 __ sub(r0, r0, Operand(kHeapObjectTag)); 4915 __ sub(r0, r0, Operand(kHeapObjectTag));
4914 __ StoreToSafepointRegisterSlot(r0, reg); 4916 __ StoreToSafepointRegisterSlot(r0, reg);
4915 } 4917 }
4916 4918
4917 4919
4918 void LCodeGen::DoSmiTag(LSmiTag* instr) { 4920 void LCodeGen::DoSmiTag(LSmiTag* instr) {
4919 ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow)); 4921 ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow));
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
4970 __ vldr(result_reg, ip, HeapNumber::kValueOffset); 4972 __ vldr(result_reg, ip, HeapNumber::kValueOffset);
4971 __ jmp(&done); 4973 __ jmp(&done);
4972 4974
4973 __ bind(&heap_number); 4975 __ bind(&heap_number);
4974 } 4976 }
4975 // Heap number to double register conversion. 4977 // Heap number to double register conversion.
4976 __ sub(ip, input_reg, Operand(kHeapObjectTag)); 4978 __ sub(ip, input_reg, Operand(kHeapObjectTag));
4977 __ vldr(result_reg, ip, HeapNumber::kValueOffset); 4979 __ vldr(result_reg, ip, HeapNumber::kValueOffset);
4978 if (deoptimize_on_minus_zero) { 4980 if (deoptimize_on_minus_zero) {
4979 __ vmov(ip, result_reg.low()); 4981 __ vmov(ip, result_reg.low());
4980 __ cmp(ip, Operand(0)); 4982 __ cmp(ip, Operand::Zero());
4981 __ b(ne, &done); 4983 __ b(ne, &done);
4982 __ vmov(ip, result_reg.high()); 4984 __ vmov(ip, result_reg.high());
4983 __ cmp(ip, Operand(HeapNumber::kSignMask)); 4985 __ cmp(ip, Operand(HeapNumber::kSignMask));
4984 DeoptimizeIf(eq, env); 4986 DeoptimizeIf(eq, env);
4985 } 4987 }
4986 __ jmp(&done); 4988 __ jmp(&done);
4987 4989
4988 // Smi to double register conversion 4990 // Smi to double register conversion
4989 __ bind(&load_smi); 4991 __ bind(&load_smi);
4990 // scratch: untagged value of input_reg 4992 // scratch: untagged value of input_reg
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
5025 !scratch3.is(scratch2)); 5027 !scratch3.is(scratch2));
5026 // Performs a truncating conversion of a floating point number as used by 5028 // Performs a truncating conversion of a floating point number as used by
5027 // the JS bitwise operations. 5029 // the JS bitwise operations.
5028 Label heap_number; 5030 Label heap_number;
5029 __ b(eq, &heap_number); 5031 __ b(eq, &heap_number);
5030 // Check for undefined. Undefined is converted to zero for truncating 5032 // Check for undefined. Undefined is converted to zero for truncating
5031 // conversions. 5033 // conversions.
5032 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); 5034 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
5033 __ cmp(input_reg, Operand(ip)); 5035 __ cmp(input_reg, Operand(ip));
5034 DeoptimizeIf(ne, instr->environment()); 5036 DeoptimizeIf(ne, instr->environment());
5035 __ mov(input_reg, Operand(0)); 5037 __ mov(input_reg, Operand::Zero());
5036 __ b(&done); 5038 __ b(&done);
5037 5039
5038 __ bind(&heap_number); 5040 __ bind(&heap_number);
5039 __ sub(scratch1, input_reg, Operand(kHeapObjectTag)); 5041 __ sub(scratch1, input_reg, Operand(kHeapObjectTag));
5040 __ vldr(double_scratch2, scratch1, HeapNumber::kValueOffset); 5042 __ vldr(double_scratch2, scratch1, HeapNumber::kValueOffset);
5041 5043
5042 __ EmitECMATruncate(input_reg, 5044 __ EmitECMATruncate(input_reg,
5043 double_scratch2, 5045 double_scratch2,
5044 double_scratch, 5046 double_scratch,
5045 scratch1, 5047 scratch1,
5046 scratch2, 5048 scratch2,
5047 scratch3); 5049 scratch3);
5048 5050
5049 } else { 5051 } else {
5050 CpuFeatures::Scope scope(VFP3); 5052 CpuFeatures::Scope scope(VFP3);
5051 // Deoptimize if we don't have a heap number. 5053 // Deoptimize if we don't have a heap number.
5052 DeoptimizeIf(ne, instr->environment()); 5054 DeoptimizeIf(ne, instr->environment());
5053 5055
5054 __ sub(ip, input_reg, Operand(kHeapObjectTag)); 5056 __ sub(ip, input_reg, Operand(kHeapObjectTag));
5055 __ vldr(double_scratch, ip, HeapNumber::kValueOffset); 5057 __ vldr(double_scratch, ip, HeapNumber::kValueOffset);
5056 __ EmitVFPTruncate(kRoundToZero, 5058 __ EmitVFPTruncate(kRoundToZero,
5057 input_reg, 5059 input_reg,
5058 double_scratch, 5060 double_scratch,
5059 scratch1, 5061 scratch1,
5060 double_scratch2, 5062 double_scratch2,
5061 kCheckForInexactConversion); 5063 kCheckForInexactConversion);
5062 DeoptimizeIf(ne, instr->environment()); 5064 DeoptimizeIf(ne, instr->environment());
5063 5065
5064 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 5066 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
5065 __ cmp(input_reg, Operand(0)); 5067 __ cmp(input_reg, Operand::Zero());
5066 __ b(ne, &done); 5068 __ b(ne, &done);
5067 __ vmov(scratch1, double_scratch.high()); 5069 __ vmov(scratch1, double_scratch.high());
5068 __ tst(scratch1, Operand(HeapNumber::kSignMask)); 5070 __ tst(scratch1, Operand(HeapNumber::kSignMask));
5069 DeoptimizeIf(ne, instr->environment()); 5071 DeoptimizeIf(ne, instr->environment());
5070 } 5072 }
5071 } 5073 }
5072 __ bind(&done); 5074 __ bind(&done);
5073 } 5075 }
5074 5076
5075 5077
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after
5286 5288
5287 // Check for heap number 5289 // Check for heap number
5288 __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); 5290 __ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset));
5289 __ cmp(scratch, Operand(factory()->heap_number_map())); 5291 __ cmp(scratch, Operand(factory()->heap_number_map()));
5290 __ b(eq, &heap_number); 5292 __ b(eq, &heap_number);
5291 5293
5292 // Check for undefined. Undefined is converted to zero for clamping 5294 // Check for undefined. Undefined is converted to zero for clamping
5293 // conversions. 5295 // conversions.
5294 __ cmp(input_reg, Operand(factory()->undefined_value())); 5296 __ cmp(input_reg, Operand(factory()->undefined_value()));
5295 DeoptimizeIf(ne, instr->environment()); 5297 DeoptimizeIf(ne, instr->environment());
5296 __ mov(result_reg, Operand(0)); 5298 __ mov(result_reg, Operand::Zero());
5297 __ jmp(&done); 5299 __ jmp(&done);
5298 5300
5299 // Heap number 5301 // Heap number
5300 __ bind(&heap_number); 5302 __ bind(&heap_number);
5301 __ vldr(double_scratch0(), FieldMemOperand(input_reg, 5303 __ vldr(double_scratch0(), FieldMemOperand(input_reg,
5302 HeapNumber::kValueOffset)); 5304 HeapNumber::kValueOffset));
5303 __ ClampDoubleToUint8(result_reg, double_scratch0(), temp_reg); 5305 __ ClampDoubleToUint8(result_reg, double_scratch0(), temp_reg);
5304 __ jmp(&done); 5306 __ jmp(&done);
5305 5307
5306 // smi 5308 // smi
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
5408 5410
5409 void LCodeGen::DoDeferredAllocateObject(LAllocateObject* instr) { 5411 void LCodeGen::DoDeferredAllocateObject(LAllocateObject* instr) {
5410 Register result = ToRegister(instr->result()); 5412 Register result = ToRegister(instr->result());
5411 Handle<JSFunction> constructor = instr->hydrogen()->constructor(); 5413 Handle<JSFunction> constructor = instr->hydrogen()->constructor();
5412 Handle<Map> initial_map(constructor->initial_map()); 5414 Handle<Map> initial_map(constructor->initial_map());
5413 int instance_size = initial_map->instance_size(); 5415 int instance_size = initial_map->instance_size();
5414 5416
5415 // TODO(3095996): Get rid of this. For now, we need to make the 5417 // TODO(3095996): Get rid of this. For now, we need to make the
5416 // result register contain a valid pointer because it is already 5418 // result register contain a valid pointer because it is already
5417 // contained in the register pointer map. 5419 // contained in the register pointer map.
5418 __ mov(result, Operand(0)); 5420 __ mov(result, Operand::Zero());
5419 5421
5420 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); 5422 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters);
5421 __ mov(r0, Operand(Smi::FromInt(instance_size))); 5423 __ mov(r0, Operand(Smi::FromInt(instance_size)));
5422 __ push(r0); 5424 __ push(r0);
5423 CallRuntimeFromDeferred(Runtime::kAllocateInNewSpace, 1, instr); 5425 CallRuntimeFromDeferred(Runtime::kAllocateInNewSpace, 1, instr);
5424 __ StoreToSafepointRegisterSlot(r0, result); 5426 __ StoreToSafepointRegisterSlot(r0, result);
5425 } 5427 }
5426 5428
5427 5429
5428 void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) { 5430 void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) {
(...skipping 608 matching lines...) Expand 10 before | Expand all | Expand 10 after
6037 __ b(ne, &load_cache); 6039 __ b(ne, &load_cache);
6038 __ mov(result, Operand(isolate()->factory()->empty_fixed_array())); 6040 __ mov(result, Operand(isolate()->factory()->empty_fixed_array()));
6039 __ jmp(&done); 6041 __ jmp(&done);
6040 6042
6041 __ bind(&load_cache); 6043 __ bind(&load_cache);
6042 __ LoadInstanceDescriptors(map, result); 6044 __ LoadInstanceDescriptors(map, result);
6043 __ ldr(result, 6045 __ ldr(result,
6044 FieldMemOperand(result, DescriptorArray::kEnumCacheOffset)); 6046 FieldMemOperand(result, DescriptorArray::kEnumCacheOffset));
6045 __ ldr(result, 6047 __ ldr(result,
6046 FieldMemOperand(result, FixedArray::SizeFor(instr->idx()))); 6048 FieldMemOperand(result, FixedArray::SizeFor(instr->idx())));
6047 __ cmp(result, Operand(0)); 6049 __ cmp(result, Operand::Zero());
6048 DeoptimizeIf(eq, instr->environment()); 6050 DeoptimizeIf(eq, instr->environment());
6049 6051
6050 __ bind(&done); 6052 __ bind(&done);
6051 } 6053 }
6052 6054
6053 6055
6054 void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) { 6056 void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) {
6055 Register object = ToRegister(instr->value()); 6057 Register object = ToRegister(instr->value());
6056 Register map = ToRegister(instr->map()); 6058 Register map = ToRegister(instr->map());
6057 __ ldr(scratch0(), FieldMemOperand(object, HeapObject::kMapOffset)); 6059 __ ldr(scratch0(), FieldMemOperand(object, HeapObject::kMapOffset));
6058 __ cmp(map, scratch0()); 6060 __ cmp(map, scratch0());
6059 DeoptimizeIf(ne, instr->environment()); 6061 DeoptimizeIf(ne, instr->environment());
6060 } 6062 }
6061 6063
6062 6064
6063 void LCodeGen::DoLoadFieldByIndex(LLoadFieldByIndex* instr) { 6065 void LCodeGen::DoLoadFieldByIndex(LLoadFieldByIndex* instr) {
6064 Register object = ToRegister(instr->object()); 6066 Register object = ToRegister(instr->object());
6065 Register index = ToRegister(instr->index()); 6067 Register index = ToRegister(instr->index());
6066 Register result = ToRegister(instr->result()); 6068 Register result = ToRegister(instr->result());
6067 Register scratch = scratch0(); 6069 Register scratch = scratch0();
6068 6070
6069 Label out_of_object, done; 6071 Label out_of_object, done;
6070 __ cmp(index, Operand(0)); 6072 __ cmp(index, Operand::Zero());
6071 __ b(lt, &out_of_object); 6073 __ b(lt, &out_of_object);
6072 6074
6073 STATIC_ASSERT(kPointerSizeLog2 > kSmiTagSize); 6075 STATIC_ASSERT(kPointerSizeLog2 > kSmiTagSize);
6074 __ add(scratch, object, Operand(index, LSL, kPointerSizeLog2 - kSmiTagSize)); 6076 __ add(scratch, object, Operand(index, LSL, kPointerSizeLog2 - kSmiTagSize));
6075 __ ldr(result, FieldMemOperand(scratch, JSObject::kHeaderSize)); 6077 __ ldr(result, FieldMemOperand(scratch, JSObject::kHeaderSize));
6076 6078
6077 __ b(&done); 6079 __ b(&done);
6078 6080
6079 __ bind(&out_of_object); 6081 __ bind(&out_of_object);
6080 __ ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset)); 6082 __ ldr(result, FieldMemOperand(object, JSObject::kPropertiesOffset));
6081 // Index is equal to negated out of object property index plus 1. 6083 // Index is equal to negated out of object property index plus 1.
6082 __ sub(scratch, result, Operand(index, LSL, kPointerSizeLog2 - kSmiTagSize)); 6084 __ sub(scratch, result, Operand(index, LSL, kPointerSizeLog2 - kSmiTagSize));
6083 __ ldr(result, FieldMemOperand(scratch, 6085 __ ldr(result, FieldMemOperand(scratch,
6084 FixedArray::kHeaderSize - kPointerSize)); 6086 FixedArray::kHeaderSize - kPointerSize));
6085 __ bind(&done); 6087 __ bind(&done);
6086 } 6088 }
6087 6089
6088 6090
6089 #undef __ 6091 #undef __
6090 6092
6091 } } // namespace v8::internal 6093 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/arm/full-codegen-arm.cc ('k') | src/arm/macro-assembler-arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698