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

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

Powered by Google App Engine
This is Rietveld 408576698