| 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 |