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

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

Issue 874323003: Externalize deoptimization reasons. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: minor change Created 5 years, 10 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
« no previous file with comments | « src/mips/lithium-codegen-mips.h ('k') | src/mips64/lithium-codegen-mips64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved.7 1 // Copyright 2012 the V8 project authors. All rights reserved.7
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 795 matching lines...) Expand 10 before | Expand all | Expand 10 after
806 int pc_offset = masm()->pc_offset(); 806 int pc_offset = masm()->pc_offset();
807 environment->Register(deoptimization_index, 807 environment->Register(deoptimization_index,
808 translation.index(), 808 translation.index(),
809 (mode == Safepoint::kLazyDeopt) ? pc_offset : -1); 809 (mode == Safepoint::kLazyDeopt) ? pc_offset : -1);
810 deoptimizations_.Add(environment, zone()); 810 deoptimizations_.Add(environment, zone());
811 } 811 }
812 } 812 }
813 813
814 814
815 void LCodeGen::DeoptimizeIf(Condition condition, LInstruction* instr, 815 void LCodeGen::DeoptimizeIf(Condition condition, LInstruction* instr,
816 Deoptimizer::DeoptReason deopt_reason,
816 Deoptimizer::BailoutType bailout_type, 817 Deoptimizer::BailoutType bailout_type,
817 const char* detail, Register src1, 818 Register src1, const Operand& src2) {
818 const Operand& src2) {
819 LEnvironment* environment = instr->environment(); 819 LEnvironment* environment = instr->environment();
820 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); 820 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
821 DCHECK(environment->HasBeenRegistered()); 821 DCHECK(environment->HasBeenRegistered());
822 int id = environment->deoptimization_index(); 822 int id = environment->deoptimization_index();
823 DCHECK(info()->IsOptimizing() || info()->IsStub()); 823 DCHECK(info()->IsOptimizing() || info()->IsStub());
824 Address entry = 824 Address entry =
825 Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type); 825 Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type);
826 if (entry == NULL) { 826 if (entry == NULL) {
827 Abort(kBailoutWasNotPrepared); 827 Abort(kBailoutWasNotPrepared);
828 return; 828 return;
(...skipping 21 matching lines...) Expand all
850 if (info()->ShouldTrapOnDeopt()) { 850 if (info()->ShouldTrapOnDeopt()) {
851 Label skip; 851 Label skip;
852 if (condition != al) { 852 if (condition != al) {
853 __ Branch(&skip, NegateCondition(condition), src1, src2); 853 __ Branch(&skip, NegateCondition(condition), src1, src2);
854 } 854 }
855 __ stop("trap_on_deopt"); 855 __ stop("trap_on_deopt");
856 __ bind(&skip); 856 __ bind(&skip);
857 } 857 }
858 858
859 Deoptimizer::Reason reason(instr->hydrogen_value()->position().raw(), 859 Deoptimizer::Reason reason(instr->hydrogen_value()->position().raw(),
860 instr->Mnemonic(), detail); 860 instr->Mnemonic(), deopt_reason);
861 DCHECK(info()->IsStub() || frame_is_built_); 861 DCHECK(info()->IsStub() || frame_is_built_);
862 // Go through jump table if we need to handle condition, build frame, or 862 // Go through jump table if we need to handle condition, build frame, or
863 // restore caller doubles. 863 // restore caller doubles.
864 if (condition == al && frame_is_built_ && 864 if (condition == al && frame_is_built_ &&
865 !info()->saves_caller_doubles()) { 865 !info()->saves_caller_doubles()) {
866 DeoptComment(reason); 866 DeoptComment(reason);
867 __ Call(entry, RelocInfo::RUNTIME_ENTRY, condition, src1, src2); 867 __ Call(entry, RelocInfo::RUNTIME_ENTRY, condition, src1, src2);
868 } else { 868 } else {
869 Deoptimizer::JumpTableEntry table_entry(entry, reason, bailout_type, 869 Deoptimizer::JumpTableEntry table_entry(entry, reason, bailout_type,
870 !frame_is_built_); 870 !frame_is_built_);
871 // We often have several deopts to the same entry, reuse the last 871 // We often have several deopts to the same entry, reuse the last
872 // jump entry if this is the case. 872 // jump entry if this is the case.
873 if (jump_table_.is_empty() || 873 if (jump_table_.is_empty() ||
874 !table_entry.IsEquivalentTo(jump_table_.last())) { 874 !table_entry.IsEquivalentTo(jump_table_.last())) {
875 jump_table_.Add(table_entry, zone()); 875 jump_table_.Add(table_entry, zone());
876 } 876 }
877 __ Branch(&jump_table_.last().label, condition, src1, src2); 877 __ Branch(&jump_table_.last().label, condition, src1, src2);
878 } 878 }
879 } 879 }
880 880
881 881
882 void LCodeGen::DeoptimizeIf(Condition condition, LInstruction* instr, 882 void LCodeGen::DeoptimizeIf(Condition condition, LInstruction* instr,
883 const char* detail, Register src1, 883 Deoptimizer::DeoptReason deopt_reason,
884 const Operand& src2) { 884 Register src1, const Operand& src2) {
885 Deoptimizer::BailoutType bailout_type = info()->IsStub() 885 Deoptimizer::BailoutType bailout_type = info()->IsStub()
886 ? Deoptimizer::LAZY 886 ? Deoptimizer::LAZY
887 : Deoptimizer::EAGER; 887 : Deoptimizer::EAGER;
888 DeoptimizeIf(condition, instr, bailout_type, detail, src1, src2); 888 DeoptimizeIf(condition, instr, deopt_reason, bailout_type, src1, src2);
889 } 889 }
890 890
891 891
892 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { 892 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) {
893 int length = deoptimizations_.length(); 893 int length = deoptimizations_.length();
894 if (length == 0) return; 894 if (length == 0) return;
895 Handle<DeoptimizationInputData> data = 895 Handle<DeoptimizationInputData> data =
896 DeoptimizationInputData::New(isolate(), length, TENURED); 896 DeoptimizationInputData::New(isolate(), length, TENURED);
897 897
898 Handle<ByteArray> translations = 898 Handle<ByteArray> translations =
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after
1109 HMod* hmod = instr->hydrogen(); 1109 HMod* hmod = instr->hydrogen();
1110 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); 1110 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1);
1111 Label dividend_is_not_negative, done; 1111 Label dividend_is_not_negative, done;
1112 1112
1113 if (hmod->CheckFlag(HValue::kLeftCanBeNegative)) { 1113 if (hmod->CheckFlag(HValue::kLeftCanBeNegative)) {
1114 __ Branch(&dividend_is_not_negative, ge, dividend, Operand(zero_reg)); 1114 __ Branch(&dividend_is_not_negative, ge, dividend, Operand(zero_reg));
1115 // Note: The code below even works when right contains kMinInt. 1115 // Note: The code below even works when right contains kMinInt.
1116 __ subu(dividend, zero_reg, dividend); 1116 __ subu(dividend, zero_reg, dividend);
1117 __ And(dividend, dividend, Operand(mask)); 1117 __ And(dividend, dividend, Operand(mask));
1118 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { 1118 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1119 DeoptimizeIf(eq, instr, "minus zero", dividend, Operand(zero_reg)); 1119 DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero, dividend,
1120 Operand(zero_reg));
1120 } 1121 }
1121 __ Branch(USE_DELAY_SLOT, &done); 1122 __ Branch(USE_DELAY_SLOT, &done);
1122 __ subu(dividend, zero_reg, dividend); 1123 __ subu(dividend, zero_reg, dividend);
1123 } 1124 }
1124 1125
1125 __ bind(&dividend_is_not_negative); 1126 __ bind(&dividend_is_not_negative);
1126 __ And(dividend, dividend, Operand(mask)); 1127 __ And(dividend, dividend, Operand(mask));
1127 __ bind(&done); 1128 __ bind(&done);
1128 } 1129 }
1129 1130
(...skipping 11 matching lines...) Expand all
1141 1142
1142 __ TruncatingDiv(result, dividend, Abs(divisor)); 1143 __ TruncatingDiv(result, dividend, Abs(divisor));
1143 __ Mul(result, result, Operand(Abs(divisor))); 1144 __ Mul(result, result, Operand(Abs(divisor)));
1144 __ Subu(result, dividend, Operand(result)); 1145 __ Subu(result, dividend, Operand(result));
1145 1146
1146 // Check for negative zero. 1147 // Check for negative zero.
1147 HMod* hmod = instr->hydrogen(); 1148 HMod* hmod = instr->hydrogen();
1148 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { 1149 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1149 Label remainder_not_zero; 1150 Label remainder_not_zero;
1150 __ Branch(&remainder_not_zero, ne, result, Operand(zero_reg)); 1151 __ Branch(&remainder_not_zero, ne, result, Operand(zero_reg));
1151 DeoptimizeIf(lt, instr, "minus zero", dividend, Operand(zero_reg)); 1152 DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero, dividend,
1153 Operand(zero_reg));
1152 __ bind(&remainder_not_zero); 1154 __ bind(&remainder_not_zero);
1153 } 1155 }
1154 } 1156 }
1155 1157
1156 1158
1157 void LCodeGen::DoModI(LModI* instr) { 1159 void LCodeGen::DoModI(LModI* instr) {
1158 HMod* hmod = instr->hydrogen(); 1160 HMod* hmod = instr->hydrogen();
1159 const Register left_reg = ToRegister(instr->left()); 1161 const Register left_reg = ToRegister(instr->left());
1160 const Register right_reg = ToRegister(instr->right()); 1162 const Register right_reg = ToRegister(instr->right());
1161 const Register result_reg = ToRegister(instr->result()); 1163 const Register result_reg = ToRegister(instr->result());
1162 1164
1163 // div runs in the background while we check for special cases. 1165 // div runs in the background while we check for special cases.
1164 __ Mod(result_reg, left_reg, right_reg); 1166 __ Mod(result_reg, left_reg, right_reg);
1165 1167
1166 Label done; 1168 Label done;
1167 // Check for x % 0, we have to deopt in this case because we can't return a 1169 // Check for x % 0, we have to deopt in this case because we can't return a
1168 // NaN. 1170 // NaN.
1169 if (hmod->CheckFlag(HValue::kCanBeDivByZero)) { 1171 if (hmod->CheckFlag(HValue::kCanBeDivByZero)) {
1170 DeoptimizeIf(eq, instr, "division by zero", right_reg, Operand(zero_reg)); 1172 DeoptimizeIf(eq, instr, Deoptimizer::kDivisionByZero, right_reg,
1173 Operand(zero_reg));
1171 } 1174 }
1172 1175
1173 // Check for kMinInt % -1, div will return kMinInt, which is not what we 1176 // Check for kMinInt % -1, div will return kMinInt, which is not what we
1174 // want. We have to deopt if we care about -0, because we can't return that. 1177 // want. We have to deopt if we care about -0, because we can't return that.
1175 if (hmod->CheckFlag(HValue::kCanOverflow)) { 1178 if (hmod->CheckFlag(HValue::kCanOverflow)) {
1176 Label no_overflow_possible; 1179 Label no_overflow_possible;
1177 __ Branch(&no_overflow_possible, ne, left_reg, Operand(kMinInt)); 1180 __ Branch(&no_overflow_possible, ne, left_reg, Operand(kMinInt));
1178 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { 1181 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1179 DeoptimizeIf(eq, instr, "minus zero", right_reg, Operand(-1)); 1182 DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero, right_reg, Operand(-1));
1180 } else { 1183 } else {
1181 __ Branch(&no_overflow_possible, ne, right_reg, Operand(-1)); 1184 __ Branch(&no_overflow_possible, ne, right_reg, Operand(-1));
1182 __ Branch(USE_DELAY_SLOT, &done); 1185 __ Branch(USE_DELAY_SLOT, &done);
1183 __ mov(result_reg, zero_reg); 1186 __ mov(result_reg, zero_reg);
1184 } 1187 }
1185 __ bind(&no_overflow_possible); 1188 __ bind(&no_overflow_possible);
1186 } 1189 }
1187 1190
1188 // If we care about -0, test if the dividend is <0 and the result is 0. 1191 // If we care about -0, test if the dividend is <0 and the result is 0.
1189 __ Branch(&done, ge, left_reg, Operand(zero_reg)); 1192 __ Branch(&done, ge, left_reg, Operand(zero_reg));
1190 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { 1193 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1191 DeoptimizeIf(eq, instr, "minus zero", result_reg, Operand(zero_reg)); 1194 DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero, result_reg,
1195 Operand(zero_reg));
1192 } 1196 }
1193 __ bind(&done); 1197 __ bind(&done);
1194 } 1198 }
1195 1199
1196 1200
1197 void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) { 1201 void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) {
1198 Register dividend = ToRegister(instr->dividend()); 1202 Register dividend = ToRegister(instr->dividend());
1199 int32_t divisor = instr->divisor(); 1203 int32_t divisor = instr->divisor();
1200 Register result = ToRegister(instr->result()); 1204 Register result = ToRegister(instr->result());
1201 DCHECK(divisor == kMinInt || base::bits::IsPowerOfTwo32(Abs(divisor))); 1205 DCHECK(divisor == kMinInt || base::bits::IsPowerOfTwo32(Abs(divisor)));
1202 DCHECK(!result.is(dividend)); 1206 DCHECK(!result.is(dividend));
1203 1207
1204 // Check for (0 / -x) that will produce negative zero. 1208 // Check for (0 / -x) that will produce negative zero.
1205 HDiv* hdiv = instr->hydrogen(); 1209 HDiv* hdiv = instr->hydrogen();
1206 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { 1210 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
1207 DeoptimizeIf(eq, instr, "minus zero", dividend, Operand(zero_reg)); 1211 DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero, dividend,
1212 Operand(zero_reg));
1208 } 1213 }
1209 // Check for (kMinInt / -1). 1214 // Check for (kMinInt / -1).
1210 if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) { 1215 if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) {
1211 DeoptimizeIf(eq, instr, "overflow", dividend, Operand(kMinInt)); 1216 DeoptimizeIf(eq, instr, Deoptimizer::kOverflow, dividend, Operand(kMinInt));
1212 } 1217 }
1213 // Deoptimize if remainder will not be 0. 1218 // Deoptimize if remainder will not be 0.
1214 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) && 1219 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) &&
1215 divisor != 1 && divisor != -1) { 1220 divisor != 1 && divisor != -1) {
1216 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); 1221 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1);
1217 __ And(at, dividend, Operand(mask)); 1222 __ And(at, dividend, Operand(mask));
1218 DeoptimizeIf(ne, instr, "lost precision", at, Operand(zero_reg)); 1223 DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecision, at, Operand(zero_reg));
1219 } 1224 }
1220 1225
1221 if (divisor == -1) { // Nice shortcut, not needed for correctness. 1226 if (divisor == -1) { // Nice shortcut, not needed for correctness.
1222 __ Subu(result, zero_reg, dividend); 1227 __ Subu(result, zero_reg, dividend);
1223 return; 1228 return;
1224 } 1229 }
1225 uint16_t shift = WhichPowerOf2Abs(divisor); 1230 uint16_t shift = WhichPowerOf2Abs(divisor);
1226 if (shift == 0) { 1231 if (shift == 0) {
1227 __ Move(result, dividend); 1232 __ Move(result, dividend);
1228 } else if (shift == 1) { 1233 } else if (shift == 1) {
(...skipping 16 matching lines...) Expand all
1245 DCHECK(!dividend.is(result)); 1250 DCHECK(!dividend.is(result));
1246 1251
1247 if (divisor == 0) { 1252 if (divisor == 0) {
1248 DeoptimizeIf(al, instr); 1253 DeoptimizeIf(al, instr);
1249 return; 1254 return;
1250 } 1255 }
1251 1256
1252 // Check for (0 / -x) that will produce negative zero. 1257 // Check for (0 / -x) that will produce negative zero.
1253 HDiv* hdiv = instr->hydrogen(); 1258 HDiv* hdiv = instr->hydrogen();
1254 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { 1259 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
1255 DeoptimizeIf(eq, instr, "minus zero", dividend, Operand(zero_reg)); 1260 DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero, dividend,
1261 Operand(zero_reg));
1256 } 1262 }
1257 1263
1258 __ TruncatingDiv(result, dividend, Abs(divisor)); 1264 __ TruncatingDiv(result, dividend, Abs(divisor));
1259 if (divisor < 0) __ Subu(result, zero_reg, result); 1265 if (divisor < 0) __ Subu(result, zero_reg, result);
1260 1266
1261 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) { 1267 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) {
1262 __ Mul(scratch0(), result, Operand(divisor)); 1268 __ Mul(scratch0(), result, Operand(divisor));
1263 __ Subu(scratch0(), scratch0(), dividend); 1269 __ Subu(scratch0(), scratch0(), dividend);
1264 DeoptimizeIf(ne, instr, "lost precision", scratch0(), Operand(zero_reg)); 1270 DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecision, scratch0(),
1271 Operand(zero_reg));
1265 } 1272 }
1266 } 1273 }
1267 1274
1268 1275
1269 // TODO(svenpanne) Refactor this to avoid code duplication with DoFlooringDivI. 1276 // TODO(svenpanne) Refactor this to avoid code duplication with DoFlooringDivI.
1270 void LCodeGen::DoDivI(LDivI* instr) { 1277 void LCodeGen::DoDivI(LDivI* instr) {
1271 HBinaryOperation* hdiv = instr->hydrogen(); 1278 HBinaryOperation* hdiv = instr->hydrogen();
1272 Register dividend = ToRegister(instr->dividend()); 1279 Register dividend = ToRegister(instr->dividend());
1273 Register divisor = ToRegister(instr->divisor()); 1280 Register divisor = ToRegister(instr->divisor());
1274 const Register result = ToRegister(instr->result()); 1281 const Register result = ToRegister(instr->result());
1275 Register remainder = ToRegister(instr->temp()); 1282 Register remainder = ToRegister(instr->temp());
1276 1283
1277 // On MIPS div is asynchronous - it will run in the background while we 1284 // On MIPS div is asynchronous - it will run in the background while we
1278 // check for special cases. 1285 // check for special cases.
1279 __ Div(remainder, result, dividend, divisor); 1286 __ Div(remainder, result, dividend, divisor);
1280 1287
1281 // Check for x / 0. 1288 // Check for x / 0.
1282 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { 1289 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
1283 DeoptimizeIf(eq, instr, "division by zero", divisor, Operand(zero_reg)); 1290 DeoptimizeIf(eq, instr, Deoptimizer::kDivisionByZero, divisor,
1291 Operand(zero_reg));
1284 } 1292 }
1285 1293
1286 // Check for (0 / -x) that will produce negative zero. 1294 // Check for (0 / -x) that will produce negative zero.
1287 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { 1295 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) {
1288 Label left_not_zero; 1296 Label left_not_zero;
1289 __ Branch(&left_not_zero, ne, dividend, Operand(zero_reg)); 1297 __ Branch(&left_not_zero, ne, dividend, Operand(zero_reg));
1290 DeoptimizeIf(lt, instr, "minus zero", divisor, Operand(zero_reg)); 1298 DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero, divisor,
1299 Operand(zero_reg));
1291 __ bind(&left_not_zero); 1300 __ bind(&left_not_zero);
1292 } 1301 }
1293 1302
1294 // Check for (kMinInt / -1). 1303 // Check for (kMinInt / -1).
1295 if (hdiv->CheckFlag(HValue::kCanOverflow) && 1304 if (hdiv->CheckFlag(HValue::kCanOverflow) &&
1296 !hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { 1305 !hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
1297 Label left_not_min_int; 1306 Label left_not_min_int;
1298 __ Branch(&left_not_min_int, ne, dividend, Operand(kMinInt)); 1307 __ Branch(&left_not_min_int, ne, dividend, Operand(kMinInt));
1299 DeoptimizeIf(eq, instr, "overflow", divisor, Operand(-1)); 1308 DeoptimizeIf(eq, instr, Deoptimizer::kOverflow, divisor, Operand(-1));
1300 __ bind(&left_not_min_int); 1309 __ bind(&left_not_min_int);
1301 } 1310 }
1302 1311
1303 if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { 1312 if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
1304 DeoptimizeIf(ne, instr, "lost precision", remainder, Operand(zero_reg)); 1313 DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecision, remainder,
1314 Operand(zero_reg));
1305 } 1315 }
1306 } 1316 }
1307 1317
1308 1318
1309 void LCodeGen::DoMultiplyAddD(LMultiplyAddD* instr) { 1319 void LCodeGen::DoMultiplyAddD(LMultiplyAddD* instr) {
1310 DoubleRegister addend = ToDoubleRegister(instr->addend()); 1320 DoubleRegister addend = ToDoubleRegister(instr->addend());
1311 DoubleRegister multiplier = ToDoubleRegister(instr->multiplier()); 1321 DoubleRegister multiplier = ToDoubleRegister(instr->multiplier());
1312 DoubleRegister multiplicand = ToDoubleRegister(instr->multiplicand()); 1322 DoubleRegister multiplicand = ToDoubleRegister(instr->multiplicand());
1313 1323
1314 // This is computed in-place. 1324 // This is computed in-place.
(...skipping 25 matching lines...) Expand all
1340 } 1350 }
1341 1351
1342 // If the divisor is negative, we have to negate and handle edge cases. 1352 // If the divisor is negative, we have to negate and handle edge cases.
1343 1353
1344 // dividend can be the same register as result so save the value of it 1354 // dividend can be the same register as result so save the value of it
1345 // for checking overflow. 1355 // for checking overflow.
1346 __ Move(scratch, dividend); 1356 __ Move(scratch, dividend);
1347 1357
1348 __ Subu(result, zero_reg, dividend); 1358 __ Subu(result, zero_reg, dividend);
1349 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 1359 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
1350 DeoptimizeIf(eq, instr, "minus zero", result, Operand(zero_reg)); 1360 DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero, result, Operand(zero_reg));
1351 } 1361 }
1352 1362
1353 // Dividing by -1 is basically negation, unless we overflow. 1363 // Dividing by -1 is basically negation, unless we overflow.
1354 __ Xor(scratch, scratch, result); 1364 __ Xor(scratch, scratch, result);
1355 if (divisor == -1) { 1365 if (divisor == -1) {
1356 if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { 1366 if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) {
1357 DeoptimizeIf(ge, instr, "overflow", scratch, Operand(zero_reg)); 1367 DeoptimizeIf(ge, instr, Deoptimizer::kOverflow, scratch,
1368 Operand(zero_reg));
1358 } 1369 }
1359 return; 1370 return;
1360 } 1371 }
1361 1372
1362 // If the negation could not overflow, simply shifting is OK. 1373 // If the negation could not overflow, simply shifting is OK.
1363 if (!instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { 1374 if (!instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) {
1364 __ sra(result, result, shift); 1375 __ sra(result, result, shift);
1365 return; 1376 return;
1366 } 1377 }
1367 1378
(...skipping 14 matching lines...) Expand all
1382 DCHECK(!dividend.is(result)); 1393 DCHECK(!dividend.is(result));
1383 1394
1384 if (divisor == 0) { 1395 if (divisor == 0) {
1385 DeoptimizeIf(al, instr); 1396 DeoptimizeIf(al, instr);
1386 return; 1397 return;
1387 } 1398 }
1388 1399
1389 // Check for (0 / -x) that will produce negative zero. 1400 // Check for (0 / -x) that will produce negative zero.
1390 HMathFloorOfDiv* hdiv = instr->hydrogen(); 1401 HMathFloorOfDiv* hdiv = instr->hydrogen();
1391 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { 1402 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
1392 DeoptimizeIf(eq, instr, "minus zero", dividend, Operand(zero_reg)); 1403 DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero, dividend,
1404 Operand(zero_reg));
1393 } 1405 }
1394 1406
1395 // Easy case: We need no dynamic check for the dividend and the flooring 1407 // Easy case: We need no dynamic check for the dividend and the flooring
1396 // division is the same as the truncating division. 1408 // division is the same as the truncating division.
1397 if ((divisor > 0 && !hdiv->CheckFlag(HValue::kLeftCanBeNegative)) || 1409 if ((divisor > 0 && !hdiv->CheckFlag(HValue::kLeftCanBeNegative)) ||
1398 (divisor < 0 && !hdiv->CheckFlag(HValue::kLeftCanBePositive))) { 1410 (divisor < 0 && !hdiv->CheckFlag(HValue::kLeftCanBePositive))) {
1399 __ TruncatingDiv(result, dividend, Abs(divisor)); 1411 __ TruncatingDiv(result, dividend, Abs(divisor));
1400 if (divisor < 0) __ Subu(result, zero_reg, result); 1412 if (divisor < 0) __ Subu(result, zero_reg, result);
1401 return; 1413 return;
1402 } 1414 }
(...skipping 23 matching lines...) Expand all
1426 Register dividend = ToRegister(instr->dividend()); 1438 Register dividend = ToRegister(instr->dividend());
1427 Register divisor = ToRegister(instr->divisor()); 1439 Register divisor = ToRegister(instr->divisor());
1428 const Register result = ToRegister(instr->result()); 1440 const Register result = ToRegister(instr->result());
1429 Register remainder = scratch0(); 1441 Register remainder = scratch0();
1430 // On MIPS div is asynchronous - it will run in the background while we 1442 // On MIPS div is asynchronous - it will run in the background while we
1431 // check for special cases. 1443 // check for special cases.
1432 __ Div(remainder, result, dividend, divisor); 1444 __ Div(remainder, result, dividend, divisor);
1433 1445
1434 // Check for x / 0. 1446 // Check for x / 0.
1435 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { 1447 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
1436 DeoptimizeIf(eq, instr, "division by zero", divisor, Operand(zero_reg)); 1448 DeoptimizeIf(eq, instr, Deoptimizer::kDivisionByZero, divisor,
1449 Operand(zero_reg));
1437 } 1450 }
1438 1451
1439 // Check for (0 / -x) that will produce negative zero. 1452 // Check for (0 / -x) that will produce negative zero.
1440 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { 1453 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) {
1441 Label left_not_zero; 1454 Label left_not_zero;
1442 __ Branch(&left_not_zero, ne, dividend, Operand(zero_reg)); 1455 __ Branch(&left_not_zero, ne, dividend, Operand(zero_reg));
1443 DeoptimizeIf(lt, instr, "minus zero", divisor, Operand(zero_reg)); 1456 DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero, divisor,
1457 Operand(zero_reg));
1444 __ bind(&left_not_zero); 1458 __ bind(&left_not_zero);
1445 } 1459 }
1446 1460
1447 // Check for (kMinInt / -1). 1461 // Check for (kMinInt / -1).
1448 if (hdiv->CheckFlag(HValue::kCanOverflow) && 1462 if (hdiv->CheckFlag(HValue::kCanOverflow) &&
1449 !hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { 1463 !hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
1450 Label left_not_min_int; 1464 Label left_not_min_int;
1451 __ Branch(&left_not_min_int, ne, dividend, Operand(kMinInt)); 1465 __ Branch(&left_not_min_int, ne, dividend, Operand(kMinInt));
1452 DeoptimizeIf(eq, instr, "overflow", divisor, Operand(-1)); 1466 DeoptimizeIf(eq, instr, Deoptimizer::kOverflow, divisor, Operand(-1));
1453 __ bind(&left_not_min_int); 1467 __ bind(&left_not_min_int);
1454 } 1468 }
1455 1469
1456 // We performed a truncating division. Correct the result if necessary. 1470 // We performed a truncating division. Correct the result if necessary.
1457 Label done; 1471 Label done;
1458 __ Branch(&done, eq, remainder, Operand(zero_reg), USE_DELAY_SLOT); 1472 __ Branch(&done, eq, remainder, Operand(zero_reg), USE_DELAY_SLOT);
1459 __ Xor(remainder, remainder, Operand(divisor)); 1473 __ Xor(remainder, remainder, Operand(divisor));
1460 __ Branch(&done, ge, remainder, Operand(zero_reg)); 1474 __ Branch(&done, ge, remainder, Operand(zero_reg));
1461 __ Subu(result, result, Operand(1)); 1475 __ Subu(result, result, Operand(1));
1462 __ bind(&done); 1476 __ bind(&done);
(...skipping 10 matching lines...) Expand all
1473 bool bailout_on_minus_zero = 1487 bool bailout_on_minus_zero =
1474 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero); 1488 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero);
1475 bool overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); 1489 bool overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow);
1476 1490
1477 if (right_op->IsConstantOperand()) { 1491 if (right_op->IsConstantOperand()) {
1478 int32_t constant = ToInteger32(LConstantOperand::cast(right_op)); 1492 int32_t constant = ToInteger32(LConstantOperand::cast(right_op));
1479 1493
1480 if (bailout_on_minus_zero && (constant < 0)) { 1494 if (bailout_on_minus_zero && (constant < 0)) {
1481 // The case of a null constant will be handled separately. 1495 // The case of a null constant will be handled separately.
1482 // If constant is negative and left is null, the result should be -0. 1496 // If constant is negative and left is null, the result should be -0.
1483 DeoptimizeIf(eq, instr, "minus zero", left, Operand(zero_reg)); 1497 DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero, left, Operand(zero_reg));
1484 } 1498 }
1485 1499
1486 switch (constant) { 1500 switch (constant) {
1487 case -1: 1501 case -1:
1488 if (overflow) { 1502 if (overflow) {
1489 __ SubuAndCheckForOverflow(result, zero_reg, left, scratch); 1503 __ SubuAndCheckForOverflow(result, zero_reg, left, scratch);
1490 DeoptimizeIf(lt, instr, "overflow", scratch, Operand(zero_reg)); 1504 DeoptimizeIf(lt, instr, Deoptimizer::kOverflow, scratch,
1505 Operand(zero_reg));
1491 } else { 1506 } else {
1492 __ Subu(result, zero_reg, left); 1507 __ Subu(result, zero_reg, left);
1493 } 1508 }
1494 break; 1509 break;
1495 case 0: 1510 case 0:
1496 if (bailout_on_minus_zero) { 1511 if (bailout_on_minus_zero) {
1497 // If left is strictly negative and the constant is null, the 1512 // If left is strictly negative and the constant is null, the
1498 // result is -0. Deoptimize if required, otherwise return 0. 1513 // result is -0. Deoptimize if required, otherwise return 0.
1499 DeoptimizeIf(lt, instr, "minus zero", left, Operand(zero_reg)); 1514 DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero, left,
1515 Operand(zero_reg));
1500 } 1516 }
1501 __ mov(result, zero_reg); 1517 __ mov(result, zero_reg);
1502 break; 1518 break;
1503 case 1: 1519 case 1:
1504 // Nothing to do. 1520 // Nothing to do.
1505 __ Move(result, left); 1521 __ Move(result, left);
1506 break; 1522 break;
1507 default: 1523 default:
1508 // Multiplying by powers of two and powers of two plus or minus 1524 // Multiplying by powers of two and powers of two plus or minus
1509 // one can be done faster with shifted operands. 1525 // one can be done faster with shifted operands.
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1541 1557
1542 if (overflow) { 1558 if (overflow) {
1543 // hi:lo = left * right. 1559 // hi:lo = left * right.
1544 if (instr->hydrogen()->representation().IsSmi()) { 1560 if (instr->hydrogen()->representation().IsSmi()) {
1545 __ SmiUntag(result, left); 1561 __ SmiUntag(result, left);
1546 __ Mul(scratch, result, result, right); 1562 __ Mul(scratch, result, result, right);
1547 } else { 1563 } else {
1548 __ Mul(scratch, result, left, right); 1564 __ Mul(scratch, result, left, right);
1549 } 1565 }
1550 __ sra(at, result, 31); 1566 __ sra(at, result, 31);
1551 DeoptimizeIf(ne, instr, "overflow", scratch, Operand(at)); 1567 DeoptimizeIf(ne, instr, Deoptimizer::kOverflow, scratch, Operand(at));
1552 } else { 1568 } else {
1553 if (instr->hydrogen()->representation().IsSmi()) { 1569 if (instr->hydrogen()->representation().IsSmi()) {
1554 __ SmiUntag(result, left); 1570 __ SmiUntag(result, left);
1555 __ Mul(result, result, right); 1571 __ Mul(result, result, right);
1556 } else { 1572 } else {
1557 __ Mul(result, left, right); 1573 __ Mul(result, left, right);
1558 } 1574 }
1559 } 1575 }
1560 1576
1561 if (bailout_on_minus_zero) { 1577 if (bailout_on_minus_zero) {
1562 Label done; 1578 Label done;
1563 __ Xor(at, left, right); 1579 __ Xor(at, left, right);
1564 __ Branch(&done, ge, at, Operand(zero_reg)); 1580 __ Branch(&done, ge, at, Operand(zero_reg));
1565 // Bail out if the result is minus zero. 1581 // Bail out if the result is minus zero.
1566 DeoptimizeIf(eq, instr, "minus zero", result, Operand(zero_reg)); 1582 DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero, result,
1583 Operand(zero_reg));
1567 __ bind(&done); 1584 __ bind(&done);
1568 } 1585 }
1569 } 1586 }
1570 } 1587 }
1571 1588
1572 1589
1573 void LCodeGen::DoBitI(LBitI* instr) { 1590 void LCodeGen::DoBitI(LBitI* instr) {
1574 LOperand* left_op = instr->left(); 1591 LOperand* left_op = instr->left();
1575 LOperand* right_op = instr->right(); 1592 LOperand* right_op = instr->right();
1576 DCHECK(left_op->IsRegister()); 1593 DCHECK(left_op->IsRegister());
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
1620 switch (instr->op()) { 1637 switch (instr->op()) {
1621 case Token::ROR: 1638 case Token::ROR:
1622 __ Ror(result, left, Operand(ToRegister(right_op))); 1639 __ Ror(result, left, Operand(ToRegister(right_op)));
1623 break; 1640 break;
1624 case Token::SAR: 1641 case Token::SAR:
1625 __ srav(result, left, ToRegister(right_op)); 1642 __ srav(result, left, ToRegister(right_op));
1626 break; 1643 break;
1627 case Token::SHR: 1644 case Token::SHR:
1628 __ srlv(result, left, ToRegister(right_op)); 1645 __ srlv(result, left, ToRegister(right_op));
1629 if (instr->can_deopt()) { 1646 if (instr->can_deopt()) {
1630 DeoptimizeIf(lt, instr, "negative value", result, Operand(zero_reg)); 1647 DeoptimizeIf(lt, instr, Deoptimizer::kNegativeValue, result,
1648 Operand(zero_reg));
1631 } 1649 }
1632 break; 1650 break;
1633 case Token::SHL: 1651 case Token::SHL:
1634 __ sllv(result, left, ToRegister(right_op)); 1652 __ sllv(result, left, ToRegister(right_op));
1635 break; 1653 break;
1636 default: 1654 default:
1637 UNREACHABLE(); 1655 UNREACHABLE();
1638 break; 1656 break;
1639 } 1657 }
1640 } else { 1658 } else {
(...skipping 14 matching lines...) Expand all
1655 } else { 1673 } else {
1656 __ Move(result, left); 1674 __ Move(result, left);
1657 } 1675 }
1658 break; 1676 break;
1659 case Token::SHR: 1677 case Token::SHR:
1660 if (shift_count != 0) { 1678 if (shift_count != 0) {
1661 __ srl(result, left, shift_count); 1679 __ srl(result, left, shift_count);
1662 } else { 1680 } else {
1663 if (instr->can_deopt()) { 1681 if (instr->can_deopt()) {
1664 __ And(at, left, Operand(0x80000000)); 1682 __ And(at, left, Operand(0x80000000));
1665 DeoptimizeIf(ne, instr, "negative value", at, Operand(zero_reg)); 1683 DeoptimizeIf(ne, instr, Deoptimizer::kNegativeValue, at,
1684 Operand(zero_reg));
1666 } 1685 }
1667 __ Move(result, left); 1686 __ Move(result, left);
1668 } 1687 }
1669 break; 1688 break;
1670 case Token::SHL: 1689 case Token::SHL:
1671 if (shift_count != 0) { 1690 if (shift_count != 0) {
1672 if (instr->hydrogen_value()->representation().IsSmi() && 1691 if (instr->hydrogen_value()->representation().IsSmi() &&
1673 instr->can_deopt()) { 1692 instr->can_deopt()) {
1674 if (shift_count != 1) { 1693 if (shift_count != 1) {
1675 __ sll(result, left, shift_count - 1); 1694 __ sll(result, left, shift_count - 1);
1676 __ SmiTagCheckOverflow(result, result, scratch); 1695 __ SmiTagCheckOverflow(result, result, scratch);
1677 } else { 1696 } else {
1678 __ SmiTagCheckOverflow(result, left, scratch); 1697 __ SmiTagCheckOverflow(result, left, scratch);
1679 } 1698 }
1680 DeoptimizeIf(lt, instr, "overflow", scratch, Operand(zero_reg)); 1699 DeoptimizeIf(lt, instr, Deoptimizer::kOverflow, scratch,
1700 Operand(zero_reg));
1681 } else { 1701 } else {
1682 __ sll(result, left, shift_count); 1702 __ sll(result, left, shift_count);
1683 } 1703 }
1684 } else { 1704 } else {
1685 __ Move(result, left); 1705 __ Move(result, left);
1686 } 1706 }
1687 break; 1707 break;
1688 default: 1708 default:
1689 UNREACHABLE(); 1709 UNREACHABLE();
1690 break; 1710 break;
(...skipping 27 matching lines...) Expand all
1718 overflow); // Reg at also used as scratch. 1738 overflow); // Reg at also used as scratch.
1719 } else { 1739 } else {
1720 DCHECK(right->IsRegister()); 1740 DCHECK(right->IsRegister());
1721 // Due to overflow check macros not supporting constant operands, 1741 // Due to overflow check macros not supporting constant operands,
1722 // handling the IsConstantOperand case was moved to prev if clause. 1742 // handling the IsConstantOperand case was moved to prev if clause.
1723 __ SubuAndCheckForOverflow(ToRegister(result), 1743 __ SubuAndCheckForOverflow(ToRegister(result),
1724 ToRegister(left), 1744 ToRegister(left),
1725 ToRegister(right), 1745 ToRegister(right),
1726 overflow); // Reg at also used as scratch. 1746 overflow); // Reg at also used as scratch.
1727 } 1747 }
1728 DeoptimizeIf(lt, instr, "overflow", overflow, Operand(zero_reg)); 1748 DeoptimizeIf(lt, instr, Deoptimizer::kOverflow, overflow,
1749 Operand(zero_reg));
1729 } 1750 }
1730 } 1751 }
1731 1752
1732 1753
1733 void LCodeGen::DoConstantI(LConstantI* instr) { 1754 void LCodeGen::DoConstantI(LConstantI* instr) {
1734 __ li(ToRegister(instr->result()), Operand(instr->value())); 1755 __ li(ToRegister(instr->result()), Operand(instr->value()));
1735 } 1756 }
1736 1757
1737 1758
1738 void LCodeGen::DoConstantS(LConstantS* instr) { 1759 void LCodeGen::DoConstantS(LConstantS* instr) {
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
1786 Register result = ToRegister(instr->result()); 1807 Register result = ToRegister(instr->result());
1787 Register scratch = ToRegister(instr->temp()); 1808 Register scratch = ToRegister(instr->temp());
1788 Smi* index = instr->index(); 1809 Smi* index = instr->index();
1789 Label runtime, done; 1810 Label runtime, done;
1790 DCHECK(object.is(a0)); 1811 DCHECK(object.is(a0));
1791 DCHECK(result.is(v0)); 1812 DCHECK(result.is(v0));
1792 DCHECK(!scratch.is(scratch0())); 1813 DCHECK(!scratch.is(scratch0()));
1793 DCHECK(!scratch.is(object)); 1814 DCHECK(!scratch.is(object));
1794 1815
1795 __ SmiTst(object, at); 1816 __ SmiTst(object, at);
1796 DeoptimizeIf(eq, instr, "Smi", at, Operand(zero_reg)); 1817 DeoptimizeIf(eq, instr, Deoptimizer::kSmi, at, Operand(zero_reg));
1797 __ GetObjectType(object, scratch, scratch); 1818 __ GetObjectType(object, scratch, scratch);
1798 DeoptimizeIf(ne, instr, "not a date object", scratch, Operand(JS_DATE_TYPE)); 1819 DeoptimizeIf(ne, instr, Deoptimizer::kNotADateObject, scratch,
1820 Operand(JS_DATE_TYPE));
1799 1821
1800 if (index->value() == 0) { 1822 if (index->value() == 0) {
1801 __ lw(result, FieldMemOperand(object, JSDate::kValueOffset)); 1823 __ lw(result, FieldMemOperand(object, JSDate::kValueOffset));
1802 } else { 1824 } else {
1803 if (index->value() < JSDate::kFirstUncachedField) { 1825 if (index->value() < JSDate::kFirstUncachedField) {
1804 ExternalReference stamp = ExternalReference::date_cache_stamp(isolate()); 1826 ExternalReference stamp = ExternalReference::date_cache_stamp(isolate());
1805 __ li(scratch, Operand(stamp)); 1827 __ li(scratch, Operand(stamp));
1806 __ lw(scratch, MemOperand(scratch)); 1828 __ lw(scratch, MemOperand(scratch));
1807 __ lw(scratch0(), FieldMemOperand(object, JSDate::kCacheStampOffset)); 1829 __ lw(scratch0(), FieldMemOperand(object, JSDate::kCacheStampOffset));
1808 __ Branch(&runtime, ne, scratch, Operand(scratch0())); 1830 __ Branch(&runtime, ne, scratch, Operand(scratch0()));
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
1923 overflow); // Reg at also used as scratch. 1945 overflow); // Reg at also used as scratch.
1924 } else { 1946 } else {
1925 DCHECK(right->IsRegister()); 1947 DCHECK(right->IsRegister());
1926 // Due to overflow check macros not supporting constant operands, 1948 // Due to overflow check macros not supporting constant operands,
1927 // handling the IsConstantOperand case was moved to prev if clause. 1949 // handling the IsConstantOperand case was moved to prev if clause.
1928 __ AdduAndCheckForOverflow(ToRegister(result), 1950 __ AdduAndCheckForOverflow(ToRegister(result),
1929 ToRegister(left), 1951 ToRegister(left),
1930 ToRegister(right), 1952 ToRegister(right),
1931 overflow); // Reg at also used as scratch. 1953 overflow); // Reg at also used as scratch.
1932 } 1954 }
1933 DeoptimizeIf(lt, instr, "overflow", overflow, Operand(zero_reg)); 1955 DeoptimizeIf(lt, instr, Deoptimizer::kOverflow, overflow,
1956 Operand(zero_reg));
1934 } 1957 }
1935 } 1958 }
1936 1959
1937 1960
1938 void LCodeGen::DoMathMinMax(LMathMinMax* instr) { 1961 void LCodeGen::DoMathMinMax(LMathMinMax* instr) {
1939 LOperand* left = instr->left(); 1962 LOperand* left = instr->left();
1940 LOperand* right = instr->right(); 1963 LOperand* right = instr->right();
1941 HMathMinMax::Operation operation = instr->hydrogen()->operation(); 1964 HMathMinMax::Operation operation = instr->hydrogen()->operation();
1942 Condition condition = (operation == HMathMinMax::kMathMin) ? le : ge; 1965 Condition condition = (operation == HMathMinMax::kMathMin) ? le : ge;
1943 if (instr->hydrogen()->representation().IsSmiOrInteger32()) { 1966 if (instr->hydrogen()->representation().IsSmiOrInteger32()) {
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after
2184 __ Branch(instr->FalseLabel(chunk_), eq, reg, Operand(at)); 2207 __ Branch(instr->FalseLabel(chunk_), eq, reg, Operand(at));
2185 } 2208 }
2186 2209
2187 if (expected.Contains(ToBooleanStub::SMI)) { 2210 if (expected.Contains(ToBooleanStub::SMI)) {
2188 // Smis: 0 -> false, all other -> true. 2211 // Smis: 0 -> false, all other -> true.
2189 __ Branch(instr->FalseLabel(chunk_), eq, reg, Operand(zero_reg)); 2212 __ Branch(instr->FalseLabel(chunk_), eq, reg, Operand(zero_reg));
2190 __ JumpIfSmi(reg, instr->TrueLabel(chunk_)); 2213 __ JumpIfSmi(reg, instr->TrueLabel(chunk_));
2191 } else if (expected.NeedsMap()) { 2214 } else if (expected.NeedsMap()) {
2192 // If we need a map later and have a Smi -> deopt. 2215 // If we need a map later and have a Smi -> deopt.
2193 __ SmiTst(reg, at); 2216 __ SmiTst(reg, at);
2194 DeoptimizeIf(eq, instr, "Smi", at, Operand(zero_reg)); 2217 DeoptimizeIf(eq, instr, Deoptimizer::kSmi, at, Operand(zero_reg));
2195 } 2218 }
2196 2219
2197 const Register map = scratch0(); 2220 const Register map = scratch0();
2198 if (expected.NeedsMap()) { 2221 if (expected.NeedsMap()) {
2199 __ lw(map, FieldMemOperand(reg, HeapObject::kMapOffset)); 2222 __ lw(map, FieldMemOperand(reg, HeapObject::kMapOffset));
2200 if (expected.CanBeUndetectable()) { 2223 if (expected.CanBeUndetectable()) {
2201 // Undetectable -> false. 2224 // Undetectable -> false.
2202 __ lbu(at, FieldMemOperand(map, Map::kBitFieldOffset)); 2225 __ lbu(at, FieldMemOperand(map, Map::kBitFieldOffset));
2203 __ And(at, at, Operand(1 << Map::kIsUndetectable)); 2226 __ And(at, at, Operand(1 << Map::kIsUndetectable));
2204 __ Branch(instr->FalseLabel(chunk_), ne, at, Operand(zero_reg)); 2227 __ Branch(instr->FalseLabel(chunk_), ne, at, Operand(zero_reg));
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
2240 __ BranchF(instr->TrueLabel(chunk_), instr->FalseLabel(chunk_), 2263 __ BranchF(instr->TrueLabel(chunk_), instr->FalseLabel(chunk_),
2241 ne, dbl_scratch, kDoubleRegZero); 2264 ne, dbl_scratch, kDoubleRegZero);
2242 // Falls through if dbl_scratch == 0. 2265 // Falls through if dbl_scratch == 0.
2243 __ Branch(instr->FalseLabel(chunk_)); 2266 __ Branch(instr->FalseLabel(chunk_));
2244 __ bind(&not_heap_number); 2267 __ bind(&not_heap_number);
2245 } 2268 }
2246 2269
2247 if (!expected.IsGeneric()) { 2270 if (!expected.IsGeneric()) {
2248 // We've seen something for the first time -> deopt. 2271 // We've seen something for the first time -> deopt.
2249 // This can only happen if we are not generic already. 2272 // This can only happen if we are not generic already.
2250 DeoptimizeIf(al, instr, "unexpected object", zero_reg, 2273 DeoptimizeIf(al, instr, Deoptimizer::kUnexpectedObject, zero_reg,
2251 Operand(zero_reg)); 2274 Operand(zero_reg));
2252 } 2275 }
2253 } 2276 }
2254 } 2277 }
2255 } 2278 }
2256 2279
2257 2280
2258 void LCodeGen::EmitGoto(int block) { 2281 void LCodeGen::EmitGoto(int block) {
2259 if (!IsNextEmittedBlock(block)) { 2282 if (!IsNextEmittedBlock(block)) {
2260 __ jmp(chunk_->GetAssemblyLabel(LookupDestination(block))); 2283 __ jmp(chunk_->GetAssemblyLabel(LookupDestination(block)));
(...skipping 625 matching lines...) Expand 10 before | Expand all | Expand 10 after
2886 } 2909 }
2887 } 2910 }
2888 2911
2889 2912
2890 void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) { 2913 void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) {
2891 Register result = ToRegister(instr->result()); 2914 Register result = ToRegister(instr->result());
2892 __ li(at, Operand(Handle<Object>(instr->hydrogen()->cell().handle()))); 2915 __ li(at, Operand(Handle<Object>(instr->hydrogen()->cell().handle())));
2893 __ lw(result, FieldMemOperand(at, Cell::kValueOffset)); 2916 __ lw(result, FieldMemOperand(at, Cell::kValueOffset));
2894 if (instr->hydrogen()->RequiresHoleCheck()) { 2917 if (instr->hydrogen()->RequiresHoleCheck()) {
2895 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); 2918 __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
2896 DeoptimizeIf(eq, instr, "hole", result, Operand(at)); 2919 DeoptimizeIf(eq, instr, Deoptimizer::kHole, result, Operand(at));
2897 } 2920 }
2898 } 2921 }
2899 2922
2900 2923
2901 template <class T> 2924 template <class T>
2902 void LCodeGen::EmitVectorLoadICRegisters(T* instr) { 2925 void LCodeGen::EmitVectorLoadICRegisters(T* instr) {
2903 DCHECK(FLAG_vector_ics); 2926 DCHECK(FLAG_vector_ics);
2904 Register vector_register = ToRegister(instr->temp_vector()); 2927 Register vector_register = ToRegister(instr->temp_vector());
2905 Register slot_register = VectorLoadICDescriptor::SlotRegister(); 2928 Register slot_register = VectorLoadICDescriptor::SlotRegister();
2906 DCHECK(vector_register.is(VectorLoadICDescriptor::VectorRegister())); 2929 DCHECK(vector_register.is(VectorLoadICDescriptor::VectorRegister()));
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
2941 2964
2942 // If the cell we are storing to contains the hole it could have 2965 // If the cell we are storing to contains the hole it could have
2943 // been deleted from the property dictionary. In that case, we need 2966 // been deleted from the property dictionary. In that case, we need
2944 // to update the property details in the property dictionary to mark 2967 // to update the property details in the property dictionary to mark
2945 // it as no longer deleted. 2968 // it as no longer deleted.
2946 if (instr->hydrogen()->RequiresHoleCheck()) { 2969 if (instr->hydrogen()->RequiresHoleCheck()) {
2947 // We use a temp to check the payload. 2970 // We use a temp to check the payload.
2948 Register payload = ToRegister(instr->temp()); 2971 Register payload = ToRegister(instr->temp());
2949 __ lw(payload, FieldMemOperand(cell, Cell::kValueOffset)); 2972 __ lw(payload, FieldMemOperand(cell, Cell::kValueOffset));
2950 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); 2973 __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
2951 DeoptimizeIf(eq, instr, "hole", payload, Operand(at)); 2974 DeoptimizeIf(eq, instr, Deoptimizer::kHole, payload, Operand(at));
2952 } 2975 }
2953 2976
2954 // Store the value. 2977 // Store the value.
2955 __ sw(value, FieldMemOperand(cell, Cell::kValueOffset)); 2978 __ sw(value, FieldMemOperand(cell, Cell::kValueOffset));
2956 // Cells are always rescanned, so no write barrier here. 2979 // Cells are always rescanned, so no write barrier here.
2957 } 2980 }
2958 2981
2959 2982
2960 2983
2961 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { 2984 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
2962 Register context = ToRegister(instr->context()); 2985 Register context = ToRegister(instr->context());
2963 Register result = ToRegister(instr->result()); 2986 Register result = ToRegister(instr->result());
2964 2987
2965 __ lw(result, ContextOperand(context, instr->slot_index())); 2988 __ lw(result, ContextOperand(context, instr->slot_index()));
2966 if (instr->hydrogen()->RequiresHoleCheck()) { 2989 if (instr->hydrogen()->RequiresHoleCheck()) {
2967 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); 2990 __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
2968 2991
2969 if (instr->hydrogen()->DeoptimizesOnHole()) { 2992 if (instr->hydrogen()->DeoptimizesOnHole()) {
2970 DeoptimizeIf(eq, instr, "hole", result, Operand(at)); 2993 DeoptimizeIf(eq, instr, Deoptimizer::kHole, result, Operand(at));
2971 } else { 2994 } else {
2972 Label is_not_hole; 2995 Label is_not_hole;
2973 __ Branch(&is_not_hole, ne, result, Operand(at)); 2996 __ Branch(&is_not_hole, ne, result, Operand(at));
2974 __ LoadRoot(result, Heap::kUndefinedValueRootIndex); 2997 __ LoadRoot(result, Heap::kUndefinedValueRootIndex);
2975 __ bind(&is_not_hole); 2998 __ bind(&is_not_hole);
2976 } 2999 }
2977 } 3000 }
2978 } 3001 }
2979 3002
2980 3003
2981 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { 3004 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) {
2982 Register context = ToRegister(instr->context()); 3005 Register context = ToRegister(instr->context());
2983 Register value = ToRegister(instr->value()); 3006 Register value = ToRegister(instr->value());
2984 Register scratch = scratch0(); 3007 Register scratch = scratch0();
2985 MemOperand target = ContextOperand(context, instr->slot_index()); 3008 MemOperand target = ContextOperand(context, instr->slot_index());
2986 3009
2987 Label skip_assignment; 3010 Label skip_assignment;
2988 3011
2989 if (instr->hydrogen()->RequiresHoleCheck()) { 3012 if (instr->hydrogen()->RequiresHoleCheck()) {
2990 __ lw(scratch, target); 3013 __ lw(scratch, target);
2991 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); 3014 __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
2992 3015
2993 if (instr->hydrogen()->DeoptimizesOnHole()) { 3016 if (instr->hydrogen()->DeoptimizesOnHole()) {
2994 DeoptimizeIf(eq, instr, "hole", scratch, Operand(at)); 3017 DeoptimizeIf(eq, instr, Deoptimizer::kHole, scratch, Operand(at));
2995 } else { 3018 } else {
2996 __ Branch(&skip_assignment, ne, scratch, Operand(at)); 3019 __ Branch(&skip_assignment, ne, scratch, Operand(at));
2997 } 3020 }
2998 } 3021 }
2999 3022
3000 __ sw(value, target); 3023 __ sw(value, target);
3001 if (instr->hydrogen()->NeedsWriteBarrier()) { 3024 if (instr->hydrogen()->NeedsWriteBarrier()) {
3002 SmiCheck check_needed = 3025 SmiCheck check_needed =
3003 instr->hydrogen()->value()->type().IsHeapObject() 3026 instr->hydrogen()->value()->type().IsHeapObject()
3004 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; 3027 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
3064 Register scratch = scratch0(); 3087 Register scratch = scratch0();
3065 Register function = ToRegister(instr->function()); 3088 Register function = ToRegister(instr->function());
3066 Register result = ToRegister(instr->result()); 3089 Register result = ToRegister(instr->result());
3067 3090
3068 // Get the prototype or initial map from the function. 3091 // Get the prototype or initial map from the function.
3069 __ lw(result, 3092 __ lw(result,
3070 FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); 3093 FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
3071 3094
3072 // Check that the function has a prototype or an initial map. 3095 // Check that the function has a prototype or an initial map.
3073 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); 3096 __ LoadRoot(at, Heap::kTheHoleValueRootIndex);
3074 DeoptimizeIf(eq, instr, "hole", result, Operand(at)); 3097 DeoptimizeIf(eq, instr, Deoptimizer::kHole, result, Operand(at));
3075 3098
3076 // If the function does not have an initial map, we're done. 3099 // If the function does not have an initial map, we're done.
3077 Label done; 3100 Label done;
3078 __ GetObjectType(result, scratch, scratch); 3101 __ GetObjectType(result, scratch, scratch);
3079 __ Branch(&done, ne, scratch, Operand(MAP_TYPE)); 3102 __ Branch(&done, ne, scratch, Operand(MAP_TYPE));
3080 3103
3081 // Get the prototype from the initial map. 3104 // Get the prototype from the initial map.
3082 __ lw(result, FieldMemOperand(result, Map::kPrototypeOffset)); 3105 __ lw(result, FieldMemOperand(result, Map::kPrototypeOffset));
3083 3106
3084 // All done. 3107 // All done.
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
3200 __ lhu(result, mem_operand); 3223 __ lhu(result, mem_operand);
3201 break; 3224 break;
3202 case EXTERNAL_INT32_ELEMENTS: 3225 case EXTERNAL_INT32_ELEMENTS:
3203 case INT32_ELEMENTS: 3226 case INT32_ELEMENTS:
3204 __ lw(result, mem_operand); 3227 __ lw(result, mem_operand);
3205 break; 3228 break;
3206 case EXTERNAL_UINT32_ELEMENTS: 3229 case EXTERNAL_UINT32_ELEMENTS:
3207 case UINT32_ELEMENTS: 3230 case UINT32_ELEMENTS:
3208 __ lw(result, mem_operand); 3231 __ lw(result, mem_operand);
3209 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) { 3232 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) {
3210 DeoptimizeIf(Ugreater_equal, instr, "negative value", result, 3233 DeoptimizeIf(Ugreater_equal, instr, Deoptimizer::kNegativeValue,
3211 Operand(0x80000000)); 3234 result, Operand(0x80000000));
3212 } 3235 }
3213 break; 3236 break;
3214 case FLOAT32_ELEMENTS: 3237 case FLOAT32_ELEMENTS:
3215 case FLOAT64_ELEMENTS: 3238 case FLOAT64_ELEMENTS:
3216 case EXTERNAL_FLOAT32_ELEMENTS: 3239 case EXTERNAL_FLOAT32_ELEMENTS:
3217 case EXTERNAL_FLOAT64_ELEMENTS: 3240 case EXTERNAL_FLOAT64_ELEMENTS:
3218 case FAST_DOUBLE_ELEMENTS: 3241 case FAST_DOUBLE_ELEMENTS:
3219 case FAST_ELEMENTS: 3242 case FAST_ELEMENTS:
3220 case FAST_SMI_ELEMENTS: 3243 case FAST_SMI_ELEMENTS:
3221 case FAST_HOLEY_DOUBLE_ELEMENTS: 3244 case FAST_HOLEY_DOUBLE_ELEMENTS:
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
3254 int shift_size = (instr->hydrogen()->key()->representation().IsSmi()) 3277 int shift_size = (instr->hydrogen()->key()->representation().IsSmi())
3255 ? (element_size_shift - kSmiTagSize) : element_size_shift; 3278 ? (element_size_shift - kSmiTagSize) : element_size_shift;
3256 __ sll(at, key, shift_size); 3279 __ sll(at, key, shift_size);
3257 __ Addu(scratch, scratch, at); 3280 __ Addu(scratch, scratch, at);
3258 } 3281 }
3259 3282
3260 __ ldc1(result, MemOperand(scratch)); 3283 __ ldc1(result, MemOperand(scratch));
3261 3284
3262 if (instr->hydrogen()->RequiresHoleCheck()) { 3285 if (instr->hydrogen()->RequiresHoleCheck()) {
3263 __ lw(scratch, MemOperand(scratch, kHoleNanUpper32Offset)); 3286 __ lw(scratch, MemOperand(scratch, kHoleNanUpper32Offset));
3264 DeoptimizeIf(eq, instr, "hole", scratch, Operand(kHoleNanUpper32)); 3287 DeoptimizeIf(eq, instr, Deoptimizer::kHole, scratch,
3288 Operand(kHoleNanUpper32));
3265 } 3289 }
3266 } 3290 }
3267 3291
3268 3292
3269 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { 3293 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) {
3270 Register elements = ToRegister(instr->elements()); 3294 Register elements = ToRegister(instr->elements());
3271 Register result = ToRegister(instr->result()); 3295 Register result = ToRegister(instr->result());
3272 Register scratch = scratch0(); 3296 Register scratch = scratch0();
3273 Register store_base = scratch; 3297 Register store_base = scratch;
3274 int offset = instr->base_offset(); 3298 int offset = instr->base_offset();
(...skipping 15 matching lines...) Expand all
3290 __ sll(scratch, key, kPointerSizeLog2); 3314 __ sll(scratch, key, kPointerSizeLog2);
3291 __ addu(scratch, elements, scratch); 3315 __ addu(scratch, elements, scratch);
3292 } 3316 }
3293 } 3317 }
3294 __ lw(result, MemOperand(store_base, offset)); 3318 __ lw(result, MemOperand(store_base, offset));
3295 3319
3296 // Check for the hole value. 3320 // Check for the hole value.
3297 if (instr->hydrogen()->RequiresHoleCheck()) { 3321 if (instr->hydrogen()->RequiresHoleCheck()) {
3298 if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) { 3322 if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) {
3299 __ SmiTst(result, scratch); 3323 __ SmiTst(result, scratch);
3300 DeoptimizeIf(ne, instr, "not a Smi", scratch, Operand(zero_reg)); 3324 DeoptimizeIf(ne, instr, Deoptimizer::kNotASmi, scratch,
3325 Operand(zero_reg));
3301 } else { 3326 } else {
3302 __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex); 3327 __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex);
3303 DeoptimizeIf(eq, instr, "hole", result, Operand(scratch)); 3328 DeoptimizeIf(eq, instr, Deoptimizer::kHole, result, Operand(scratch));
3304 } 3329 }
3305 } 3330 }
3306 } 3331 }
3307 3332
3308 3333
3309 void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) { 3334 void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) {
3310 if (instr->is_typed_elements()) { 3335 if (instr->is_typed_elements()) {
3311 DoLoadKeyedExternalArray(instr); 3336 DoLoadKeyedExternalArray(instr);
3312 } else if (instr->hydrogen()->representation().IsDouble()) { 3337 } else if (instr->hydrogen()->representation().IsDouble()) {
3313 DoLoadKeyedFixedDoubleArray(instr); 3338 DoLoadKeyedFixedDoubleArray(instr);
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
3439 } 3464 }
3440 3465
3441 // Normal function. Replace undefined or null with global receiver. 3466 // Normal function. Replace undefined or null with global receiver.
3442 __ LoadRoot(scratch, Heap::kNullValueRootIndex); 3467 __ LoadRoot(scratch, Heap::kNullValueRootIndex);
3443 __ Branch(&global_object, eq, receiver, Operand(scratch)); 3468 __ Branch(&global_object, eq, receiver, Operand(scratch));
3444 __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex); 3469 __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex);
3445 __ Branch(&global_object, eq, receiver, Operand(scratch)); 3470 __ Branch(&global_object, eq, receiver, Operand(scratch));
3446 3471
3447 // Deoptimize if the receiver is not a JS object. 3472 // Deoptimize if the receiver is not a JS object.
3448 __ SmiTst(receiver, scratch); 3473 __ SmiTst(receiver, scratch);
3449 DeoptimizeIf(eq, instr, "Smi", scratch, Operand(zero_reg)); 3474 DeoptimizeIf(eq, instr, Deoptimizer::kSmi, scratch, Operand(zero_reg));
3450 3475
3451 __ GetObjectType(receiver, scratch, scratch); 3476 __ GetObjectType(receiver, scratch, scratch);
3452 DeoptimizeIf(lt, instr, "not a JavaScript object", scratch, 3477 DeoptimizeIf(lt, instr, Deoptimizer::kNotAJavaScriptObject, scratch,
3453 Operand(FIRST_SPEC_OBJECT_TYPE)); 3478 Operand(FIRST_SPEC_OBJECT_TYPE));
3454 3479
3455 __ Branch(&result_in_receiver); 3480 __ Branch(&result_in_receiver);
3456 __ bind(&global_object); 3481 __ bind(&global_object);
3457 __ lw(result, FieldMemOperand(function, JSFunction::kContextOffset)); 3482 __ lw(result, FieldMemOperand(function, JSFunction::kContextOffset));
3458 __ lw(result, 3483 __ lw(result,
3459 ContextOperand(result, Context::GLOBAL_OBJECT_INDEX)); 3484 ContextOperand(result, Context::GLOBAL_OBJECT_INDEX));
3460 __ lw(result, 3485 __ lw(result,
3461 FieldMemOperand(result, GlobalObject::kGlobalProxyOffset)); 3486 FieldMemOperand(result, GlobalObject::kGlobalProxyOffset));
3462 3487
(...skipping 15 matching lines...) Expand all
3478 Register length = ToRegister(instr->length()); 3503 Register length = ToRegister(instr->length());
3479 Register elements = ToRegister(instr->elements()); 3504 Register elements = ToRegister(instr->elements());
3480 Register scratch = scratch0(); 3505 Register scratch = scratch0();
3481 DCHECK(receiver.is(a0)); // Used for parameter count. 3506 DCHECK(receiver.is(a0)); // Used for parameter count.
3482 DCHECK(function.is(a1)); // Required by InvokeFunction. 3507 DCHECK(function.is(a1)); // Required by InvokeFunction.
3483 DCHECK(ToRegister(instr->result()).is(v0)); 3508 DCHECK(ToRegister(instr->result()).is(v0));
3484 3509
3485 // Copy the arguments to this function possibly from the 3510 // Copy the arguments to this function possibly from the
3486 // adaptor frame below it. 3511 // adaptor frame below it.
3487 const uint32_t kArgumentsLimit = 1 * KB; 3512 const uint32_t kArgumentsLimit = 1 * KB;
3488 DeoptimizeIf(hi, instr, "too many arguments", length, 3513 DeoptimizeIf(hi, instr, Deoptimizer::kTooManyArguments, length,
3489 Operand(kArgumentsLimit)); 3514 Operand(kArgumentsLimit));
3490 3515
3491 // Push the receiver and use the register to keep the original 3516 // Push the receiver and use the register to keep the original
3492 // number of arguments. 3517 // number of arguments.
3493 __ push(receiver); 3518 __ push(receiver);
3494 __ Move(receiver, length); 3519 __ Move(receiver, length);
3495 // The arguments are at a one pointer size offset from elements. 3520 // The arguments are at a one pointer size offset from elements.
3496 __ Addu(elements, elements, Operand(1 * kPointerSize)); 3521 __ Addu(elements, elements, Operand(1 * kPointerSize));
3497 3522
3498 // Loop through the arguments pushing them onto the execution 3523 // Loop through the arguments pushing them onto the execution
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
3604 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { 3629 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) {
3605 DCHECK(instr->context() != NULL); 3630 DCHECK(instr->context() != NULL);
3606 DCHECK(ToRegister(instr->context()).is(cp)); 3631 DCHECK(ToRegister(instr->context()).is(cp));
3607 Register input = ToRegister(instr->value()); 3632 Register input = ToRegister(instr->value());
3608 Register result = ToRegister(instr->result()); 3633 Register result = ToRegister(instr->result());
3609 Register scratch = scratch0(); 3634 Register scratch = scratch0();
3610 3635
3611 // Deoptimize if not a heap number. 3636 // Deoptimize if not a heap number.
3612 __ lw(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); 3637 __ lw(scratch, FieldMemOperand(input, HeapObject::kMapOffset));
3613 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); 3638 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex);
3614 DeoptimizeIf(ne, instr, "not a heap number", scratch, Operand(at)); 3639 DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumber, scratch, Operand(at));
3615 3640
3616 Label done; 3641 Label done;
3617 Register exponent = scratch0(); 3642 Register exponent = scratch0();
3618 scratch = no_reg; 3643 scratch = no_reg;
3619 __ lw(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset)); 3644 __ lw(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset));
3620 // Check the sign of the argument. If the argument is positive, just 3645 // Check the sign of the argument. If the argument is positive, just
3621 // return it. 3646 // return it.
3622 __ Move(result, input); 3647 __ Move(result, input);
3623 __ And(at, exponent, Operand(HeapNumber::kSignMask)); 3648 __ And(at, exponent, Operand(HeapNumber::kSignMask));
3624 __ Branch(&done, eq, at, Operand(zero_reg)); 3649 __ Branch(&done, eq, at, Operand(zero_reg));
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
3671 3696
3672 void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) { 3697 void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) {
3673 Register input = ToRegister(instr->value()); 3698 Register input = ToRegister(instr->value());
3674 Register result = ToRegister(instr->result()); 3699 Register result = ToRegister(instr->result());
3675 Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_); 3700 Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_);
3676 Label done; 3701 Label done;
3677 __ Branch(USE_DELAY_SLOT, &done, ge, input, Operand(zero_reg)); 3702 __ Branch(USE_DELAY_SLOT, &done, ge, input, Operand(zero_reg));
3678 __ mov(result, input); 3703 __ mov(result, input);
3679 __ subu(result, zero_reg, input); 3704 __ subu(result, zero_reg, input);
3680 // Overflow if result is still negative, i.e. 0x80000000. 3705 // Overflow if result is still negative, i.e. 0x80000000.
3681 DeoptimizeIf(lt, instr, "overflow", result, Operand(zero_reg)); 3706 DeoptimizeIf(lt, instr, Deoptimizer::kOverflow, result, Operand(zero_reg));
3682 __ bind(&done); 3707 __ bind(&done);
3683 } 3708 }
3684 3709
3685 3710
3686 void LCodeGen::DoMathAbs(LMathAbs* instr) { 3711 void LCodeGen::DoMathAbs(LMathAbs* instr) {
3687 // Class for deferred case. 3712 // Class for deferred case.
3688 class DeferredMathAbsTaggedHeapNumber FINAL : public LDeferredCode { 3713 class DeferredMathAbsTaggedHeapNumber FINAL : public LDeferredCode {
3689 public: 3714 public:
3690 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, LMathAbs* instr) 3715 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, LMathAbs* instr)
3691 : LDeferredCode(codegen), instr_(instr) { } 3716 : LDeferredCode(codegen), instr_(instr) { }
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
3726 Register except_flag = ToRegister(instr->temp()); 3751 Register except_flag = ToRegister(instr->temp());
3727 3752
3728 __ EmitFPUTruncate(kRoundToMinusInf, 3753 __ EmitFPUTruncate(kRoundToMinusInf,
3729 result, 3754 result,
3730 input, 3755 input,
3731 scratch1, 3756 scratch1,
3732 double_scratch0(), 3757 double_scratch0(),
3733 except_flag); 3758 except_flag);
3734 3759
3735 // Deopt if the operation did not succeed. 3760 // Deopt if the operation did not succeed.
3736 DeoptimizeIf(ne, instr, "lost precision or NaN", except_flag, 3761 DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecisionOrNaN, except_flag,
3737 Operand(zero_reg)); 3762 Operand(zero_reg));
3738 3763
3739 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 3764 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
3740 // Test for -0. 3765 // Test for -0.
3741 Label done; 3766 Label done;
3742 __ Branch(&done, ne, result, Operand(zero_reg)); 3767 __ Branch(&done, ne, result, Operand(zero_reg));
3743 __ Mfhc1(scratch1, input); 3768 __ Mfhc1(scratch1, input);
3744 __ And(scratch1, scratch1, Operand(HeapNumber::kSignMask)); 3769 __ And(scratch1, scratch1, Operand(HeapNumber::kSignMask));
3745 DeoptimizeIf(ne, instr, "minus zero", scratch1, Operand(zero_reg)); 3770 DeoptimizeIf(ne, instr, Deoptimizer::kMinusZero, scratch1,
3771 Operand(zero_reg));
3746 __ bind(&done); 3772 __ bind(&done);
3747 } 3773 }
3748 } 3774 }
3749 3775
3750 3776
3751 void LCodeGen::DoMathRound(LMathRound* instr) { 3777 void LCodeGen::DoMathRound(LMathRound* instr) {
3752 DoubleRegister input = ToDoubleRegister(instr->value()); 3778 DoubleRegister input = ToDoubleRegister(instr->value());
3753 Register result = ToRegister(instr->result()); 3779 Register result = ToRegister(instr->result());
3754 DoubleRegister double_scratch1 = ToDoubleRegister(instr->temp()); 3780 DoubleRegister double_scratch1 = ToDoubleRegister(instr->temp());
3755 Register scratch = scratch0(); 3781 Register scratch = scratch0();
(...skipping 12 matching lines...) Expand all
3768 __ mov(result, zero_reg); 3794 __ mov(result, zero_reg);
3769 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 3795 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
3770 __ Branch(&check_sign_on_zero); 3796 __ Branch(&check_sign_on_zero);
3771 } else { 3797 } else {
3772 __ Branch(&done); 3798 __ Branch(&done);
3773 } 3799 }
3774 __ bind(&skip1); 3800 __ bind(&skip1);
3775 3801
3776 // The following conversion will not work with numbers 3802 // The following conversion will not work with numbers
3777 // outside of ]-2^32, 2^32[. 3803 // outside of ]-2^32, 2^32[.
3778 DeoptimizeIf(ge, instr, "overflow", scratch, 3804 DeoptimizeIf(ge, instr, Deoptimizer::kOverflow, scratch,
3779 Operand(HeapNumber::kExponentBias + 32)); 3805 Operand(HeapNumber::kExponentBias + 32));
3780 3806
3781 // Save the original sign for later comparison. 3807 // Save the original sign for later comparison.
3782 __ And(scratch, result, Operand(HeapNumber::kSignMask)); 3808 __ And(scratch, result, Operand(HeapNumber::kSignMask));
3783 3809
3784 __ Move(double_scratch0(), 0.5); 3810 __ Move(double_scratch0(), 0.5);
3785 __ add_d(double_scratch0(), input, double_scratch0()); 3811 __ add_d(double_scratch0(), input, double_scratch0());
3786 3812
3787 // Check sign of the result: if the sign changed, the input 3813 // Check sign of the result: if the sign changed, the input
3788 // value was in ]0.5, 0[ and the result should be -0. 3814 // value was in ]0.5, 0[ and the result should be -0.
3789 __ Mfhc1(result, double_scratch0()); 3815 __ Mfhc1(result, double_scratch0());
3790 __ Xor(result, result, Operand(scratch)); 3816 __ Xor(result, result, Operand(scratch));
3791 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 3817 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
3792 // ARM uses 'mi' here, which is 'lt' 3818 // ARM uses 'mi' here, which is 'lt'
3793 DeoptimizeIf(lt, instr, "minus zero", result, Operand(zero_reg)); 3819 DeoptimizeIf(lt, instr, Deoptimizer::kMinusZero, result, Operand(zero_reg));
3794 } else { 3820 } else {
3795 Label skip2; 3821 Label skip2;
3796 // ARM uses 'mi' here, which is 'lt' 3822 // ARM uses 'mi' here, which is 'lt'
3797 // Negating it results in 'ge' 3823 // Negating it results in 'ge'
3798 __ Branch(&skip2, ge, result, Operand(zero_reg)); 3824 __ Branch(&skip2, ge, result, Operand(zero_reg));
3799 __ mov(result, zero_reg); 3825 __ mov(result, zero_reg);
3800 __ Branch(&done); 3826 __ Branch(&done);
3801 __ bind(&skip2); 3827 __ bind(&skip2);
3802 } 3828 }
3803 3829
3804 Register except_flag = scratch; 3830 Register except_flag = scratch;
3805 __ EmitFPUTruncate(kRoundToMinusInf, 3831 __ EmitFPUTruncate(kRoundToMinusInf,
3806 result, 3832 result,
3807 double_scratch0(), 3833 double_scratch0(),
3808 at, 3834 at,
3809 double_scratch1, 3835 double_scratch1,
3810 except_flag); 3836 except_flag);
3811 3837
3812 DeoptimizeIf(ne, instr, "lost precision or NaN", except_flag, 3838 DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecisionOrNaN, except_flag,
3813 Operand(zero_reg)); 3839 Operand(zero_reg));
3814 3840
3815 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 3841 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
3816 // Test for -0. 3842 // Test for -0.
3817 __ Branch(&done, ne, result, Operand(zero_reg)); 3843 __ Branch(&done, ne, result, Operand(zero_reg));
3818 __ bind(&check_sign_on_zero); 3844 __ bind(&check_sign_on_zero);
3819 __ Mfhc1(scratch, input); 3845 __ Mfhc1(scratch, input);
3820 __ And(scratch, scratch, Operand(HeapNumber::kSignMask)); 3846 __ And(scratch, scratch, Operand(HeapNumber::kSignMask));
3821 DeoptimizeIf(ne, instr, "minus zero", scratch, Operand(zero_reg)); 3847 DeoptimizeIf(ne, instr, Deoptimizer::kMinusZero, scratch,
3848 Operand(zero_reg));
3822 } 3849 }
3823 __ bind(&done); 3850 __ bind(&done);
3824 } 3851 }
3825 3852
3826 3853
3827 void LCodeGen::DoMathFround(LMathFround* instr) { 3854 void LCodeGen::DoMathFround(LMathFround* instr) {
3828 DoubleRegister input = ToDoubleRegister(instr->value()); 3855 DoubleRegister input = ToDoubleRegister(instr->value());
3829 DoubleRegister result = ToDoubleRegister(instr->result()); 3856 DoubleRegister result = ToDoubleRegister(instr->result());
3830 __ cvt_s_d(result.low(), input); 3857 __ cvt_s_d(result.low(), input);
3831 __ cvt_d_s(result, result.low()); 3858 __ cvt_d_s(result, result.low());
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
3877 3904
3878 if (exponent_type.IsSmi()) { 3905 if (exponent_type.IsSmi()) {
3879 MathPowStub stub(isolate(), MathPowStub::TAGGED); 3906 MathPowStub stub(isolate(), MathPowStub::TAGGED);
3880 __ CallStub(&stub); 3907 __ CallStub(&stub);
3881 } else if (exponent_type.IsTagged()) { 3908 } else if (exponent_type.IsTagged()) {
3882 Label no_deopt; 3909 Label no_deopt;
3883 __ JumpIfSmi(tagged_exponent, &no_deopt); 3910 __ JumpIfSmi(tagged_exponent, &no_deopt);
3884 DCHECK(!t3.is(tagged_exponent)); 3911 DCHECK(!t3.is(tagged_exponent));
3885 __ lw(t3, FieldMemOperand(tagged_exponent, HeapObject::kMapOffset)); 3912 __ lw(t3, FieldMemOperand(tagged_exponent, HeapObject::kMapOffset));
3886 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); 3913 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex);
3887 DeoptimizeIf(ne, instr, "not a heap number", t3, Operand(at)); 3914 DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumber, t3, Operand(at));
3888 __ bind(&no_deopt); 3915 __ bind(&no_deopt);
3889 MathPowStub stub(isolate(), MathPowStub::TAGGED); 3916 MathPowStub stub(isolate(), MathPowStub::TAGGED);
3890 __ CallStub(&stub); 3917 __ CallStub(&stub);
3891 } else if (exponent_type.IsInteger32()) { 3918 } else if (exponent_type.IsInteger32()) {
3892 MathPowStub stub(isolate(), MathPowStub::INTEGER); 3919 MathPowStub stub(isolate(), MathPowStub::INTEGER);
3893 __ CallStub(&stub); 3920 __ CallStub(&stub);
3894 } else { 3921 } else {
3895 DCHECK(exponent_type.IsDouble()); 3922 DCHECK(exponent_type.IsDouble());
3896 MathPowStub stub(isolate(), MathPowStub::DOUBLE); 3923 MathPowStub stub(isolate(), MathPowStub::DOUBLE);
3897 __ CallStub(&stub); 3924 __ CallStub(&stub);
(...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after
4269 } else { 4296 } else {
4270 reg = ToRegister(instr->index()); 4297 reg = ToRegister(instr->index());
4271 operand = ToOperand(instr->length()); 4298 operand = ToOperand(instr->length());
4272 } 4299 }
4273 if (FLAG_debug_code && instr->hydrogen()->skip_check()) { 4300 if (FLAG_debug_code && instr->hydrogen()->skip_check()) {
4274 Label done; 4301 Label done;
4275 __ Branch(&done, NegateCondition(cc), reg, operand); 4302 __ Branch(&done, NegateCondition(cc), reg, operand);
4276 __ stop("eliminated bounds check failed"); 4303 __ stop("eliminated bounds check failed");
4277 __ bind(&done); 4304 __ bind(&done);
4278 } else { 4305 } else {
4279 DeoptimizeIf(cc, instr, "out of bounds", reg, operand); 4306 DeoptimizeIf(cc, instr, Deoptimizer::kOutOfBounds, reg, operand);
4280 } 4307 }
4281 } 4308 }
4282 4309
4283 4310
4284 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) { 4311 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
4285 Register external_pointer = ToRegister(instr->elements()); 4312 Register external_pointer = ToRegister(instr->elements());
4286 Register key = no_reg; 4313 Register key = no_reg;
4287 ElementsKind elements_kind = instr->elements_kind(); 4314 ElementsKind elements_kind = instr->elements_kind();
4288 bool key_is_constant = instr->key()->IsConstantOperand(); 4315 bool key_is_constant = instr->key()->IsConstantOperand();
4289 int constant_key = 0; 4316 int constant_key = 0;
(...skipping 573 matching lines...) Expand 10 before | Expand all | Expand 10 after
4863 } 4890 }
4864 4891
4865 4892
4866 void LCodeGen::DoSmiTag(LSmiTag* instr) { 4893 void LCodeGen::DoSmiTag(LSmiTag* instr) {
4867 HChange* hchange = instr->hydrogen(); 4894 HChange* hchange = instr->hydrogen();
4868 Register input = ToRegister(instr->value()); 4895 Register input = ToRegister(instr->value());
4869 Register output = ToRegister(instr->result()); 4896 Register output = ToRegister(instr->result());
4870 if (hchange->CheckFlag(HValue::kCanOverflow) && 4897 if (hchange->CheckFlag(HValue::kCanOverflow) &&
4871 hchange->value()->CheckFlag(HValue::kUint32)) { 4898 hchange->value()->CheckFlag(HValue::kUint32)) {
4872 __ And(at, input, Operand(0xc0000000)); 4899 __ And(at, input, Operand(0xc0000000));
4873 DeoptimizeIf(ne, instr, "overflow", at, Operand(zero_reg)); 4900 DeoptimizeIf(ne, instr, Deoptimizer::kOverflow, at, Operand(zero_reg));
4874 } 4901 }
4875 if (hchange->CheckFlag(HValue::kCanOverflow) && 4902 if (hchange->CheckFlag(HValue::kCanOverflow) &&
4876 !hchange->value()->CheckFlag(HValue::kUint32)) { 4903 !hchange->value()->CheckFlag(HValue::kUint32)) {
4877 __ SmiTagCheckOverflow(output, input, at); 4904 __ SmiTagCheckOverflow(output, input, at);
4878 DeoptimizeIf(lt, instr, "overflow", at, Operand(zero_reg)); 4905 DeoptimizeIf(lt, instr, Deoptimizer::kOverflow, at, Operand(zero_reg));
4879 } else { 4906 } else {
4880 __ SmiTag(output, input); 4907 __ SmiTag(output, input);
4881 } 4908 }
4882 } 4909 }
4883 4910
4884 4911
4885 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { 4912 void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
4886 Register scratch = scratch0(); 4913 Register scratch = scratch0();
4887 Register input = ToRegister(instr->value()); 4914 Register input = ToRegister(instr->value());
4888 Register result = ToRegister(instr->result()); 4915 Register result = ToRegister(instr->result());
4889 if (instr->needs_check()) { 4916 if (instr->needs_check()) {
4890 STATIC_ASSERT(kHeapObjectTag == 1); 4917 STATIC_ASSERT(kHeapObjectTag == 1);
4891 // If the input is a HeapObject, value of scratch won't be zero. 4918 // If the input is a HeapObject, value of scratch won't be zero.
4892 __ And(scratch, input, Operand(kHeapObjectTag)); 4919 __ And(scratch, input, Operand(kHeapObjectTag));
4893 __ SmiUntag(result, input); 4920 __ SmiUntag(result, input);
4894 DeoptimizeIf(ne, instr, "not a Smi", scratch, Operand(zero_reg)); 4921 DeoptimizeIf(ne, instr, Deoptimizer::kNotASmi, scratch, Operand(zero_reg));
4895 } else { 4922 } else {
4896 __ SmiUntag(result, input); 4923 __ SmiUntag(result, input);
4897 } 4924 }
4898 } 4925 }
4899 4926
4900 4927
4901 void LCodeGen::EmitNumberUntagD(LNumberUntagD* instr, Register input_reg, 4928 void LCodeGen::EmitNumberUntagD(LNumberUntagD* instr, Register input_reg,
4902 DoubleRegister result_reg, 4929 DoubleRegister result_reg,
4903 NumberUntagDMode mode) { 4930 NumberUntagDMode mode) {
4904 bool can_convert_undefined_to_nan = 4931 bool can_convert_undefined_to_nan =
4905 instr->hydrogen()->can_convert_undefined_to_nan(); 4932 instr->hydrogen()->can_convert_undefined_to_nan();
4906 bool deoptimize_on_minus_zero = instr->hydrogen()->deoptimize_on_minus_zero(); 4933 bool deoptimize_on_minus_zero = instr->hydrogen()->deoptimize_on_minus_zero();
4907 4934
4908 Register scratch = scratch0(); 4935 Register scratch = scratch0();
4909 Label convert, load_smi, done; 4936 Label convert, load_smi, done;
4910 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) { 4937 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) {
4911 // Smi check. 4938 // Smi check.
4912 __ UntagAndJumpIfSmi(scratch, input_reg, &load_smi); 4939 __ UntagAndJumpIfSmi(scratch, input_reg, &load_smi);
4913 // Heap number map check. 4940 // Heap number map check.
4914 __ lw(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); 4941 __ lw(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset));
4915 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); 4942 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex);
4916 if (can_convert_undefined_to_nan) { 4943 if (can_convert_undefined_to_nan) {
4917 __ Branch(&convert, ne, scratch, Operand(at)); 4944 __ Branch(&convert, ne, scratch, Operand(at));
4918 } else { 4945 } else {
4919 DeoptimizeIf(ne, instr, "not a heap number", scratch, Operand(at)); 4946 DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumber, scratch,
4947 Operand(at));
4920 } 4948 }
4921 // Load heap number. 4949 // Load heap number.
4922 __ ldc1(result_reg, FieldMemOperand(input_reg, HeapNumber::kValueOffset)); 4950 __ ldc1(result_reg, FieldMemOperand(input_reg, HeapNumber::kValueOffset));
4923 if (deoptimize_on_minus_zero) { 4951 if (deoptimize_on_minus_zero) {
4924 __ mfc1(at, result_reg.low()); 4952 __ mfc1(at, result_reg.low());
4925 __ Branch(&done, ne, at, Operand(zero_reg)); 4953 __ Branch(&done, ne, at, Operand(zero_reg));
4926 __ Mfhc1(scratch, result_reg); 4954 __ Mfhc1(scratch, result_reg);
4927 DeoptimizeIf(eq, instr, "minus zero", scratch, 4955 DeoptimizeIf(eq, instr, Deoptimizer::kMinusZero, scratch,
4928 Operand(HeapNumber::kSignMask)); 4956 Operand(HeapNumber::kSignMask));
4929 } 4957 }
4930 __ Branch(&done); 4958 __ Branch(&done);
4931 if (can_convert_undefined_to_nan) { 4959 if (can_convert_undefined_to_nan) {
4932 __ bind(&convert); 4960 __ bind(&convert);
4933 // Convert undefined (and hole) to NaN. 4961 // Convert undefined (and hole) to NaN.
4934 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); 4962 __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
4935 DeoptimizeIf(ne, instr, "not a heap number/undefined", input_reg, 4963 DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumberUndefined, input_reg,
4936 Operand(at)); 4964 Operand(at));
4937 __ LoadRoot(scratch, Heap::kNanValueRootIndex); 4965 __ LoadRoot(scratch, Heap::kNanValueRootIndex);
4938 __ ldc1(result_reg, FieldMemOperand(scratch, HeapNumber::kValueOffset)); 4966 __ ldc1(result_reg, FieldMemOperand(scratch, HeapNumber::kValueOffset));
4939 __ Branch(&done); 4967 __ Branch(&done);
4940 } 4968 }
4941 } else { 4969 } else {
4942 __ SmiUntag(scratch, input_reg); 4970 __ SmiUntag(scratch, input_reg);
4943 DCHECK(mode == NUMBER_CANDIDATE_IS_SMI); 4971 DCHECK(mode == NUMBER_CANDIDATE_IS_SMI);
4944 } 4972 }
4945 // Smi to double register conversion 4973 // Smi to double register conversion
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
4990 __ mov(input_reg, zero_reg); // In delay slot. 5018 __ mov(input_reg, zero_reg); // In delay slot.
4991 5019
4992 __ bind(&check_bools); 5020 __ bind(&check_bools);
4993 __ LoadRoot(at, Heap::kTrueValueRootIndex); 5021 __ LoadRoot(at, Heap::kTrueValueRootIndex);
4994 __ Branch(&check_false, ne, scratch2, Operand(at)); 5022 __ Branch(&check_false, ne, scratch2, Operand(at));
4995 __ Branch(USE_DELAY_SLOT, &done); 5023 __ Branch(USE_DELAY_SLOT, &done);
4996 __ li(input_reg, Operand(1)); // In delay slot. 5024 __ li(input_reg, Operand(1)); // In delay slot.
4997 5025
4998 __ bind(&check_false); 5026 __ bind(&check_false);
4999 __ LoadRoot(at, Heap::kFalseValueRootIndex); 5027 __ LoadRoot(at, Heap::kFalseValueRootIndex);
5000 DeoptimizeIf(ne, instr, "not a heap number/undefined/true/false", scratch2, 5028 DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumberUndefinedBoolean,
5001 Operand(at)); 5029 scratch2, Operand(at));
5002 __ Branch(USE_DELAY_SLOT, &done); 5030 __ Branch(USE_DELAY_SLOT, &done);
5003 __ mov(input_reg, zero_reg); // In delay slot. 5031 __ mov(input_reg, zero_reg); // In delay slot.
5004 } else { 5032 } else {
5005 DeoptimizeIf(ne, instr, "not a heap number", scratch1, Operand(at)); 5033 DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumber, scratch1,
5034 Operand(at));
5006 5035
5007 // Load the double value. 5036 // Load the double value.
5008 __ ldc1(double_scratch, 5037 __ ldc1(double_scratch,
5009 FieldMemOperand(input_reg, HeapNumber::kValueOffset)); 5038 FieldMemOperand(input_reg, HeapNumber::kValueOffset));
5010 5039
5011 Register except_flag = scratch2; 5040 Register except_flag = scratch2;
5012 __ EmitFPUTruncate(kRoundToZero, 5041 __ EmitFPUTruncate(kRoundToZero,
5013 input_reg, 5042 input_reg,
5014 double_scratch, 5043 double_scratch,
5015 scratch1, 5044 scratch1,
5016 double_scratch2, 5045 double_scratch2,
5017 except_flag, 5046 except_flag,
5018 kCheckForInexactConversion); 5047 kCheckForInexactConversion);
5019 5048
5020 DeoptimizeIf(ne, instr, "lost precision or NaN", except_flag, 5049 DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecisionOrNaN, except_flag,
5021 Operand(zero_reg)); 5050 Operand(zero_reg));
5022 5051
5023 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 5052 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
5024 __ Branch(&done, ne, input_reg, Operand(zero_reg)); 5053 __ Branch(&done, ne, input_reg, Operand(zero_reg));
5025 5054
5026 __ Mfhc1(scratch1, double_scratch); 5055 __ Mfhc1(scratch1, double_scratch);
5027 __ And(scratch1, scratch1, Operand(HeapNumber::kSignMask)); 5056 __ And(scratch1, scratch1, Operand(HeapNumber::kSignMask));
5028 DeoptimizeIf(ne, instr, "minus zero", scratch1, Operand(zero_reg)); 5057 DeoptimizeIf(ne, instr, Deoptimizer::kMinusZero, scratch1,
5058 Operand(zero_reg));
5029 } 5059 }
5030 } 5060 }
5031 __ bind(&done); 5061 __ bind(&done);
5032 } 5062 }
5033 5063
5034 5064
5035 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { 5065 void LCodeGen::DoTaggedToI(LTaggedToI* instr) {
5036 class DeferredTaggedToI FINAL : public LDeferredCode { 5066 class DeferredTaggedToI FINAL : public LDeferredCode {
5037 public: 5067 public:
5038 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) 5068 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr)
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
5094 5124
5095 __ EmitFPUTruncate(kRoundToMinusInf, 5125 __ EmitFPUTruncate(kRoundToMinusInf,
5096 result_reg, 5126 result_reg,
5097 double_input, 5127 double_input,
5098 scratch1, 5128 scratch1,
5099 double_scratch0(), 5129 double_scratch0(),
5100 except_flag, 5130 except_flag,
5101 kCheckForInexactConversion); 5131 kCheckForInexactConversion);
5102 5132
5103 // Deopt if the operation did not succeed (except_flag != 0). 5133 // Deopt if the operation did not succeed (except_flag != 0).
5104 DeoptimizeIf(ne, instr, "lost precision or NaN", except_flag, 5134 DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecisionOrNaN, except_flag,
5105 Operand(zero_reg)); 5135 Operand(zero_reg));
5106 5136
5107 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 5137 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
5108 Label done; 5138 Label done;
5109 __ Branch(&done, ne, result_reg, Operand(zero_reg)); 5139 __ Branch(&done, ne, result_reg, Operand(zero_reg));
5110 __ Mfhc1(scratch1, double_input); 5140 __ Mfhc1(scratch1, double_input);
5111 __ And(scratch1, scratch1, Operand(HeapNumber::kSignMask)); 5141 __ And(scratch1, scratch1, Operand(HeapNumber::kSignMask));
5112 DeoptimizeIf(ne, instr, "minus zero", scratch1, Operand(zero_reg)); 5142 DeoptimizeIf(ne, instr, Deoptimizer::kMinusZero, scratch1,
5143 Operand(zero_reg));
5113 __ bind(&done); 5144 __ bind(&done);
5114 } 5145 }
5115 } 5146 }
5116 } 5147 }
5117 5148
5118 5149
5119 void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) { 5150 void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) {
5120 Register result_reg = ToRegister(instr->result()); 5151 Register result_reg = ToRegister(instr->result());
5121 Register scratch1 = LCodeGen::scratch0(); 5152 Register scratch1 = LCodeGen::scratch0();
5122 DoubleRegister double_input = ToDoubleRegister(instr->value()); 5153 DoubleRegister double_input = ToDoubleRegister(instr->value());
5123 5154
5124 if (instr->truncating()) { 5155 if (instr->truncating()) {
5125 __ TruncateDoubleToI(result_reg, double_input); 5156 __ TruncateDoubleToI(result_reg, double_input);
5126 } else { 5157 } else {
5127 Register except_flag = LCodeGen::scratch1(); 5158 Register except_flag = LCodeGen::scratch1();
5128 5159
5129 __ EmitFPUTruncate(kRoundToMinusInf, 5160 __ EmitFPUTruncate(kRoundToMinusInf,
5130 result_reg, 5161 result_reg,
5131 double_input, 5162 double_input,
5132 scratch1, 5163 scratch1,
5133 double_scratch0(), 5164 double_scratch0(),
5134 except_flag, 5165 except_flag,
5135 kCheckForInexactConversion); 5166 kCheckForInexactConversion);
5136 5167
5137 // Deopt if the operation did not succeed (except_flag != 0). 5168 // Deopt if the operation did not succeed (except_flag != 0).
5138 DeoptimizeIf(ne, instr, "lost precision or NaN", except_flag, 5169 DeoptimizeIf(ne, instr, Deoptimizer::kLostPrecisionOrNaN, except_flag,
5139 Operand(zero_reg)); 5170 Operand(zero_reg));
5140 5171
5141 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 5172 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
5142 Label done; 5173 Label done;
5143 __ Branch(&done, ne, result_reg, Operand(zero_reg)); 5174 __ Branch(&done, ne, result_reg, Operand(zero_reg));
5144 __ Mfhc1(scratch1, double_input); 5175 __ Mfhc1(scratch1, double_input);
5145 __ And(scratch1, scratch1, Operand(HeapNumber::kSignMask)); 5176 __ And(scratch1, scratch1, Operand(HeapNumber::kSignMask));
5146 DeoptimizeIf(ne, instr, "minus zero", scratch1, Operand(zero_reg)); 5177 DeoptimizeIf(ne, instr, Deoptimizer::kMinusZero, scratch1,
5178 Operand(zero_reg));
5147 __ bind(&done); 5179 __ bind(&done);
5148 } 5180 }
5149 } 5181 }
5150 __ SmiTagCheckOverflow(result_reg, result_reg, scratch1); 5182 __ SmiTagCheckOverflow(result_reg, result_reg, scratch1);
5151 DeoptimizeIf(lt, instr, "overflow", scratch1, Operand(zero_reg)); 5183 DeoptimizeIf(lt, instr, Deoptimizer::kOverflow, scratch1, Operand(zero_reg));
5152 } 5184 }
5153 5185
5154 5186
5155 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { 5187 void LCodeGen::DoCheckSmi(LCheckSmi* instr) {
5156 LOperand* input = instr->value(); 5188 LOperand* input = instr->value();
5157 __ SmiTst(ToRegister(input), at); 5189 __ SmiTst(ToRegister(input), at);
5158 DeoptimizeIf(ne, instr, "not a Smi", at, Operand(zero_reg)); 5190 DeoptimizeIf(ne, instr, Deoptimizer::kNotASmi, at, Operand(zero_reg));
5159 } 5191 }
5160 5192
5161 5193
5162 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { 5194 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) {
5163 if (!instr->hydrogen()->value()->type().IsHeapObject()) { 5195 if (!instr->hydrogen()->value()->type().IsHeapObject()) {
5164 LOperand* input = instr->value(); 5196 LOperand* input = instr->value();
5165 __ SmiTst(ToRegister(input), at); 5197 __ SmiTst(ToRegister(input), at);
5166 DeoptimizeIf(eq, instr, "Smi", at, Operand(zero_reg)); 5198 DeoptimizeIf(eq, instr, Deoptimizer::kSmi, at, Operand(zero_reg));
5167 } 5199 }
5168 } 5200 }
5169 5201
5170 5202
5171 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { 5203 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
5172 Register input = ToRegister(instr->value()); 5204 Register input = ToRegister(instr->value());
5173 Register scratch = scratch0(); 5205 Register scratch = scratch0();
5174 5206
5175 __ GetObjectType(input, scratch, scratch); 5207 __ GetObjectType(input, scratch, scratch);
5176 5208
5177 if (instr->hydrogen()->is_interval_check()) { 5209 if (instr->hydrogen()->is_interval_check()) {
5178 InstanceType first; 5210 InstanceType first;
5179 InstanceType last; 5211 InstanceType last;
5180 instr->hydrogen()->GetCheckInterval(&first, &last); 5212 instr->hydrogen()->GetCheckInterval(&first, &last);
5181 5213
5182 // If there is only one type in the interval check for equality. 5214 // If there is only one type in the interval check for equality.
5183 if (first == last) { 5215 if (first == last) {
5184 DeoptimizeIf(ne, instr, "wrong instance type", scratch, Operand(first)); 5216 DeoptimizeIf(ne, instr, Deoptimizer::kWrongInstanceType, scratch,
5217 Operand(first));
5185 } else { 5218 } else {
5186 DeoptimizeIf(lo, instr, "wrong instance type", scratch, Operand(first)); 5219 DeoptimizeIf(lo, instr, Deoptimizer::kWrongInstanceType, scratch,
5220 Operand(first));
5187 // Omit check for the last type. 5221 // Omit check for the last type.
5188 if (last != LAST_TYPE) { 5222 if (last != LAST_TYPE) {
5189 DeoptimizeIf(hi, instr, "wrong instance type", scratch, Operand(last)); 5223 DeoptimizeIf(hi, instr, Deoptimizer::kWrongInstanceType, scratch,
5224 Operand(last));
5190 } 5225 }
5191 } 5226 }
5192 } else { 5227 } else {
5193 uint8_t mask; 5228 uint8_t mask;
5194 uint8_t tag; 5229 uint8_t tag;
5195 instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag); 5230 instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag);
5196 5231
5197 if (base::bits::IsPowerOfTwo32(mask)) { 5232 if (base::bits::IsPowerOfTwo32(mask)) {
5198 DCHECK(tag == 0 || base::bits::IsPowerOfTwo32(tag)); 5233 DCHECK(tag == 0 || base::bits::IsPowerOfTwo32(tag));
5199 __ And(at, scratch, mask); 5234 __ And(at, scratch, mask);
5200 DeoptimizeIf(tag == 0 ? ne : eq, instr, "wrong instance type", at, 5235 DeoptimizeIf(tag == 0 ? ne : eq, instr, Deoptimizer::kWrongInstanceType,
5201 Operand(zero_reg)); 5236 at, Operand(zero_reg));
5202 } else { 5237 } else {
5203 __ And(scratch, scratch, Operand(mask)); 5238 __ And(scratch, scratch, Operand(mask));
5204 DeoptimizeIf(ne, instr, "wrong instance type", scratch, Operand(tag)); 5239 DeoptimizeIf(ne, instr, Deoptimizer::kWrongInstanceType, scratch,
5240 Operand(tag));
5205 } 5241 }
5206 } 5242 }
5207 } 5243 }
5208 5244
5209 5245
5210 void LCodeGen::DoCheckValue(LCheckValue* instr) { 5246 void LCodeGen::DoCheckValue(LCheckValue* instr) {
5211 Register reg = ToRegister(instr->value()); 5247 Register reg = ToRegister(instr->value());
5212 Handle<HeapObject> object = instr->hydrogen()->object().handle(); 5248 Handle<HeapObject> object = instr->hydrogen()->object().handle();
5213 AllowDeferredHandleDereference smi_check; 5249 AllowDeferredHandleDereference smi_check;
5214 if (isolate()->heap()->InNewSpace(*object)) { 5250 if (isolate()->heap()->InNewSpace(*object)) {
5215 Register reg = ToRegister(instr->value()); 5251 Register reg = ToRegister(instr->value());
5216 Handle<Cell> cell = isolate()->factory()->NewCell(object); 5252 Handle<Cell> cell = isolate()->factory()->NewCell(object);
5217 __ li(at, Operand(Handle<Object>(cell))); 5253 __ li(at, Operand(Handle<Object>(cell)));
5218 __ lw(at, FieldMemOperand(at, Cell::kValueOffset)); 5254 __ lw(at, FieldMemOperand(at, Cell::kValueOffset));
5219 DeoptimizeIf(ne, instr, "value mismatch", reg, Operand(at)); 5255 DeoptimizeIf(ne, instr, Deoptimizer::kValueMismatch, reg, Operand(at));
5220 } else { 5256 } else {
5221 DeoptimizeIf(ne, instr, "value mismatch", reg, Operand(object)); 5257 DeoptimizeIf(ne, instr, Deoptimizer::kValueMismatch, reg, Operand(object));
5222 } 5258 }
5223 } 5259 }
5224 5260
5225 5261
5226 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) { 5262 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) {
5227 { 5263 {
5228 PushSafepointRegistersScope scope(this); 5264 PushSafepointRegistersScope scope(this);
5229 __ push(object); 5265 __ push(object);
5230 __ mov(cp, zero_reg); 5266 __ mov(cp, zero_reg);
5231 __ CallRuntimeSaveDoubles(Runtime::kTryMigrateInstance); 5267 __ CallRuntimeSaveDoubles(Runtime::kTryMigrateInstance);
5232 RecordSafepointWithRegisters( 5268 RecordSafepointWithRegisters(
5233 instr->pointer_map(), 1, Safepoint::kNoLazyDeopt); 5269 instr->pointer_map(), 1, Safepoint::kNoLazyDeopt);
5234 __ StoreToSafepointRegisterSlot(v0, scratch0()); 5270 __ StoreToSafepointRegisterSlot(v0, scratch0());
5235 } 5271 }
5236 __ SmiTst(scratch0(), at); 5272 __ SmiTst(scratch0(), at);
5237 DeoptimizeIf(eq, instr, "instance migration failed", at, Operand(zero_reg)); 5273 DeoptimizeIf(eq, instr, Deoptimizer::kInstanceMigrationFailed, at,
5274 Operand(zero_reg));
5238 } 5275 }
5239 5276
5240 5277
5241 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { 5278 void LCodeGen::DoCheckMaps(LCheckMaps* instr) {
5242 class DeferredCheckMaps FINAL : public LDeferredCode { 5279 class DeferredCheckMaps FINAL : public LDeferredCode {
5243 public: 5280 public:
5244 DeferredCheckMaps(LCodeGen* codegen, LCheckMaps* instr, Register object) 5281 DeferredCheckMaps(LCodeGen* codegen, LCheckMaps* instr, Register object)
5245 : LDeferredCode(codegen), instr_(instr), object_(object) { 5282 : LDeferredCode(codegen), instr_(instr), object_(object) {
5246 SetExit(check_maps()); 5283 SetExit(check_maps());
5247 } 5284 }
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
5281 Label success; 5318 Label success;
5282 for (int i = 0; i < maps->size() - 1; i++) { 5319 for (int i = 0; i < maps->size() - 1; i++) {
5283 Handle<Map> map = maps->at(i).handle(); 5320 Handle<Map> map = maps->at(i).handle();
5284 __ CompareMapAndBranch(map_reg, map, &success, eq, &success); 5321 __ CompareMapAndBranch(map_reg, map, &success, eq, &success);
5285 } 5322 }
5286 Handle<Map> map = maps->at(maps->size() - 1).handle(); 5323 Handle<Map> map = maps->at(maps->size() - 1).handle();
5287 // Do the CompareMap() directly within the Branch() and DeoptimizeIf(). 5324 // Do the CompareMap() directly within the Branch() and DeoptimizeIf().
5288 if (instr->hydrogen()->HasMigrationTarget()) { 5325 if (instr->hydrogen()->HasMigrationTarget()) {
5289 __ Branch(deferred->entry(), ne, map_reg, Operand(map)); 5326 __ Branch(deferred->entry(), ne, map_reg, Operand(map));
5290 } else { 5327 } else {
5291 DeoptimizeIf(ne, instr, "wrong map", map_reg, Operand(map)); 5328 DeoptimizeIf(ne, instr, Deoptimizer::kWrongMap, map_reg, Operand(map));
5292 } 5329 }
5293 5330
5294 __ bind(&success); 5331 __ bind(&success);
5295 } 5332 }
5296 5333
5297 5334
5298 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { 5335 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) {
5299 DoubleRegister value_reg = ToDoubleRegister(instr->unclamped()); 5336 DoubleRegister value_reg = ToDoubleRegister(instr->unclamped());
5300 Register result_reg = ToRegister(instr->result()); 5337 Register result_reg = ToRegister(instr->result());
5301 DoubleRegister temp_reg = ToDoubleRegister(instr->temp()); 5338 DoubleRegister temp_reg = ToDoubleRegister(instr->temp());
(...skipping 17 matching lines...) Expand all
5319 5356
5320 // Both smi and heap number cases are handled. 5357 // Both smi and heap number cases are handled.
5321 __ UntagAndJumpIfSmi(scratch, input_reg, &is_smi); 5358 __ UntagAndJumpIfSmi(scratch, input_reg, &is_smi);
5322 5359
5323 // Check for heap number 5360 // Check for heap number
5324 __ lw(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); 5361 __ lw(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset));
5325 __ Branch(&heap_number, eq, scratch, Operand(factory()->heap_number_map())); 5362 __ Branch(&heap_number, eq, scratch, Operand(factory()->heap_number_map()));
5326 5363
5327 // Check for undefined. Undefined is converted to zero for clamping 5364 // Check for undefined. Undefined is converted to zero for clamping
5328 // conversions. 5365 // conversions.
5329 DeoptimizeIf(ne, instr, "not a heap number/undefined", input_reg, 5366 DeoptimizeIf(ne, instr, Deoptimizer::kNotAHeapNumberUndefined, input_reg,
5330 Operand(factory()->undefined_value())); 5367 Operand(factory()->undefined_value()));
5331 __ mov(result_reg, zero_reg); 5368 __ mov(result_reg, zero_reg);
5332 __ jmp(&done); 5369 __ jmp(&done);
5333 5370
5334 // Heap number 5371 // Heap number
5335 __ bind(&heap_number); 5372 __ bind(&heap_number);
5336 __ ldc1(double_scratch0(), FieldMemOperand(input_reg, 5373 __ ldc1(double_scratch0(), FieldMemOperand(input_reg,
5337 HeapNumber::kValueOffset)); 5374 HeapNumber::kValueOffset));
5338 __ ClampDoubleToUint8(result_reg, double_scratch0(), temp_reg); 5375 __ ClampDoubleToUint8(result_reg, double_scratch0(), temp_reg);
5339 __ jmp(&done); 5376 __ jmp(&done);
(...skipping 402 matching lines...) Expand 10 before | Expand all | Expand 10 after
5742 void LCodeGen::DoDeoptimize(LDeoptimize* instr) { 5779 void LCodeGen::DoDeoptimize(LDeoptimize* instr) {
5743 Deoptimizer::BailoutType type = instr->hydrogen()->type(); 5780 Deoptimizer::BailoutType type = instr->hydrogen()->type();
5744 // TODO(danno): Stubs expect all deopts to be lazy for historical reasons (the 5781 // TODO(danno): Stubs expect all deopts to be lazy for historical reasons (the
5745 // needed return address), even though the implementation of LAZY and EAGER is 5782 // needed return address), even though the implementation of LAZY and EAGER is
5746 // now identical. When LAZY is eventually completely folded into EAGER, remove 5783 // now identical. When LAZY is eventually completely folded into EAGER, remove
5747 // the special case below. 5784 // the special case below.
5748 if (info()->IsStub() && type == Deoptimizer::EAGER) { 5785 if (info()->IsStub() && type == Deoptimizer::EAGER) {
5749 type = Deoptimizer::LAZY; 5786 type = Deoptimizer::LAZY;
5750 } 5787 }
5751 5788
5752 DeoptimizeIf(al, instr, type, instr->hydrogen()->reason(), zero_reg, 5789 DeoptimizeIf(al, instr, instr->hydrogen()->reason(), type, zero_reg,
5753 Operand(zero_reg)); 5790 Operand(zero_reg));
5754 } 5791 }
5755 5792
5756 5793
5757 void LCodeGen::DoDummy(LDummy* instr) { 5794 void LCodeGen::DoDummy(LDummy* instr) {
5758 // Nothing to see here, move on! 5795 // Nothing to see here, move on!
5759 } 5796 }
5760 5797
5761 5798
5762 void LCodeGen::DoDummyUse(LDummyUse* instr) { 5799 void LCodeGen::DoDummyUse(LDummyUse* instr) {
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
5833 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); 5870 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
5834 5871
5835 GenerateOsrPrologue(); 5872 GenerateOsrPrologue();
5836 } 5873 }
5837 5874
5838 5875
5839 void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) { 5876 void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) {
5840 Register result = ToRegister(instr->result()); 5877 Register result = ToRegister(instr->result());
5841 Register object = ToRegister(instr->object()); 5878 Register object = ToRegister(instr->object());
5842 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); 5879 __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
5843 DeoptimizeIf(eq, instr, "undefined", object, Operand(at)); 5880 DeoptimizeIf(eq, instr, Deoptimizer::kUndefined, object, Operand(at));
5844 5881
5845 Register null_value = t1; 5882 Register null_value = t1;
5846 __ LoadRoot(null_value, Heap::kNullValueRootIndex); 5883 __ LoadRoot(null_value, Heap::kNullValueRootIndex);
5847 DeoptimizeIf(eq, instr, "null", object, Operand(null_value)); 5884 DeoptimizeIf(eq, instr, Deoptimizer::kNull, object, Operand(null_value));
5848 5885
5849 __ And(at, object, kSmiTagMask); 5886 __ And(at, object, kSmiTagMask);
5850 DeoptimizeIf(eq, instr, "Smi", at, Operand(zero_reg)); 5887 DeoptimizeIf(eq, instr, Deoptimizer::kSmi, at, Operand(zero_reg));
5851 5888
5852 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); 5889 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
5853 __ GetObjectType(object, a1, a1); 5890 __ GetObjectType(object, a1, a1);
5854 DeoptimizeIf(le, instr, "not a JavaScript object", a1, 5891 DeoptimizeIf(le, instr, Deoptimizer::kNotAJavaScriptObject, a1,
5855 Operand(LAST_JS_PROXY_TYPE)); 5892 Operand(LAST_JS_PROXY_TYPE));
5856 5893
5857 Label use_cache, call_runtime; 5894 Label use_cache, call_runtime;
5858 DCHECK(object.is(a0)); 5895 DCHECK(object.is(a0));
5859 __ CheckEnumCache(null_value, &call_runtime); 5896 __ CheckEnumCache(null_value, &call_runtime);
5860 5897
5861 __ lw(result, FieldMemOperand(object, HeapObject::kMapOffset)); 5898 __ lw(result, FieldMemOperand(object, HeapObject::kMapOffset));
5862 __ Branch(&use_cache); 5899 __ Branch(&use_cache);
5863 5900
5864 // Get the set of properties to enumerate. 5901 // Get the set of properties to enumerate.
5865 __ bind(&call_runtime); 5902 __ bind(&call_runtime);
5866 __ push(object); 5903 __ push(object);
5867 CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr); 5904 CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr);
5868 5905
5869 __ lw(a1, FieldMemOperand(v0, HeapObject::kMapOffset)); 5906 __ lw(a1, FieldMemOperand(v0, HeapObject::kMapOffset));
5870 DCHECK(result.is(v0)); 5907 DCHECK(result.is(v0));
5871 __ LoadRoot(at, Heap::kMetaMapRootIndex); 5908 __ LoadRoot(at, Heap::kMetaMapRootIndex);
5872 DeoptimizeIf(ne, instr, "wrong map", a1, Operand(at)); 5909 DeoptimizeIf(ne, instr, Deoptimizer::kWrongMap, a1, Operand(at));
5873 __ bind(&use_cache); 5910 __ bind(&use_cache);
5874 } 5911 }
5875 5912
5876 5913
5877 void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) { 5914 void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) {
5878 Register map = ToRegister(instr->map()); 5915 Register map = ToRegister(instr->map());
5879 Register result = ToRegister(instr->result()); 5916 Register result = ToRegister(instr->result());
5880 Label load_cache, done; 5917 Label load_cache, done;
5881 __ EnumLength(result, map); 5918 __ EnumLength(result, map);
5882 __ Branch(&load_cache, ne, result, Operand(Smi::FromInt(0))); 5919 __ Branch(&load_cache, ne, result, Operand(Smi::FromInt(0)));
5883 __ li(result, Operand(isolate()->factory()->empty_fixed_array())); 5920 __ li(result, Operand(isolate()->factory()->empty_fixed_array()));
5884 __ jmp(&done); 5921 __ jmp(&done);
5885 5922
5886 __ bind(&load_cache); 5923 __ bind(&load_cache);
5887 __ LoadInstanceDescriptors(map, result); 5924 __ LoadInstanceDescriptors(map, result);
5888 __ lw(result, 5925 __ lw(result,
5889 FieldMemOperand(result, DescriptorArray::kEnumCacheOffset)); 5926 FieldMemOperand(result, DescriptorArray::kEnumCacheOffset));
5890 __ lw(result, 5927 __ lw(result,
5891 FieldMemOperand(result, FixedArray::SizeFor(instr->idx()))); 5928 FieldMemOperand(result, FixedArray::SizeFor(instr->idx())));
5892 DeoptimizeIf(eq, instr, "no cache", result, Operand(zero_reg)); 5929 DeoptimizeIf(eq, instr, Deoptimizer::kNoCache, result, Operand(zero_reg));
5893 5930
5894 __ bind(&done); 5931 __ bind(&done);
5895 } 5932 }
5896 5933
5897 5934
5898 void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) { 5935 void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) {
5899 Register object = ToRegister(instr->value()); 5936 Register object = ToRegister(instr->value());
5900 Register map = ToRegister(instr->map()); 5937 Register map = ToRegister(instr->map());
5901 __ lw(scratch0(), FieldMemOperand(object, HeapObject::kMapOffset)); 5938 __ lw(scratch0(), FieldMemOperand(object, HeapObject::kMapOffset));
5902 DeoptimizeIf(ne, instr, "wrong map", map, Operand(scratch0())); 5939 DeoptimizeIf(ne, instr, Deoptimizer::kWrongMap, map, Operand(scratch0()));
5903 } 5940 }
5904 5941
5905 5942
5906 void LCodeGen::DoDeferredLoadMutableDouble(LLoadFieldByIndex* instr, 5943 void LCodeGen::DoDeferredLoadMutableDouble(LLoadFieldByIndex* instr,
5907 Register result, 5944 Register result,
5908 Register object, 5945 Register object,
5909 Register index) { 5946 Register index) {
5910 PushSafepointRegistersScope scope(this); 5947 PushSafepointRegistersScope scope(this);
5911 __ Push(object, index); 5948 __ Push(object, index);
5912 __ mov(cp, zero_reg); 5949 __ mov(cp, zero_reg);
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
5989 __ li(at, scope_info); 6026 __ li(at, scope_info);
5990 __ Push(at, ToRegister(instr->function())); 6027 __ Push(at, ToRegister(instr->function()));
5991 CallRuntime(Runtime::kPushBlockContext, 2, instr); 6028 CallRuntime(Runtime::kPushBlockContext, 2, instr);
5992 RecordSafepoint(Safepoint::kNoLazyDeopt); 6029 RecordSafepoint(Safepoint::kNoLazyDeopt);
5993 } 6030 }
5994 6031
5995 6032
5996 #undef __ 6033 #undef __
5997 6034
5998 } } // namespace v8::internal 6035 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/mips/lithium-codegen-mips.h ('k') | src/mips64/lithium-codegen-mips64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698