OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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(÷nd_is_not_negative, ge, dividend, Operand(zero_reg)); | 1114 __ Branch(÷nd_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(÷nd_is_not_negative); | 1126 __ bind(÷nd_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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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(¬_heap_number); | 2267 __ bind(¬_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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |