| 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 801 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 812 int deoptimization_index = deoptimizations_.length(); | 812 int deoptimization_index = deoptimizations_.length(); |
| 813 int pc_offset = masm()->pc_offset(); | 813 int pc_offset = masm()->pc_offset(); |
| 814 environment->Register(deoptimization_index, | 814 environment->Register(deoptimization_index, |
| 815 translation.index(), | 815 translation.index(), |
| 816 (mode == Safepoint::kLazyDeopt) ? pc_offset : -1); | 816 (mode == Safepoint::kLazyDeopt) ? pc_offset : -1); |
| 817 deoptimizations_.Add(environment, zone()); | 817 deoptimizations_.Add(environment, zone()); |
| 818 } | 818 } |
| 819 } | 819 } |
| 820 | 820 |
| 821 | 821 |
| 822 void LCodeGen::DeoptimizeIf(Condition condition, | 822 void LCodeGen::DeoptimizeIf(Condition condition, LInstruction* instr, |
| 823 LEnvironment* environment, | |
| 824 Deoptimizer::BailoutType bailout_type, | 823 Deoptimizer::BailoutType bailout_type, |
| 825 Register src1, | 824 Register src1, const Operand& src2) { |
| 826 const Operand& src2) { | 825 LEnvironment* environment = instr->environment(); |
| 827 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); | 826 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); |
| 828 DCHECK(environment->HasBeenRegistered()); | 827 DCHECK(environment->HasBeenRegistered()); |
| 829 int id = environment->deoptimization_index(); | 828 int id = environment->deoptimization_index(); |
| 830 DCHECK(info()->IsOptimizing() || info()->IsStub()); | 829 DCHECK(info()->IsOptimizing() || info()->IsStub()); |
| 831 Address entry = | 830 Address entry = |
| 832 Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type); | 831 Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type); |
| 833 if (entry == NULL) { | 832 if (entry == NULL) { |
| 834 Abort(kBailoutWasNotPrepared); | 833 Abort(kBailoutWasNotPrepared); |
| 835 return; | 834 return; |
| 836 } | 835 } |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 879 Deoptimizer::JumpTableEntry table_entry(entry, | 878 Deoptimizer::JumpTableEntry table_entry(entry, |
| 880 bailout_type, | 879 bailout_type, |
| 881 !frame_is_built_); | 880 !frame_is_built_); |
| 882 deopt_jump_table_.Add(table_entry, zone()); | 881 deopt_jump_table_.Add(table_entry, zone()); |
| 883 } | 882 } |
| 884 __ Branch(&deopt_jump_table_.last().label, condition, src1, src2); | 883 __ Branch(&deopt_jump_table_.last().label, condition, src1, src2); |
| 885 } | 884 } |
| 886 } | 885 } |
| 887 | 886 |
| 888 | 887 |
| 889 void LCodeGen::DeoptimizeIf(Condition condition, | 888 void LCodeGen::DeoptimizeIf(Condition condition, LInstruction* instr, |
| 890 LEnvironment* environment, | 889 Register src1, const Operand& src2) { |
| 891 Register src1, | |
| 892 const Operand& src2) { | |
| 893 Deoptimizer::BailoutType bailout_type = info()->IsStub() | 890 Deoptimizer::BailoutType bailout_type = info()->IsStub() |
| 894 ? Deoptimizer::LAZY | 891 ? Deoptimizer::LAZY |
| 895 : Deoptimizer::EAGER; | 892 : Deoptimizer::EAGER; |
| 896 DeoptimizeIf(condition, environment, bailout_type, src1, src2); | 893 DeoptimizeIf(condition, instr, bailout_type, src1, src2); |
| 897 } | 894 } |
| 898 | 895 |
| 899 | 896 |
| 900 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { | 897 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { |
| 901 int length = deoptimizations_.length(); | 898 int length = deoptimizations_.length(); |
| 902 if (length == 0) return; | 899 if (length == 0) return; |
| 903 Handle<DeoptimizationInputData> data = | 900 Handle<DeoptimizationInputData> data = |
| 904 DeoptimizationInputData::New(isolate(), length, TENURED); | 901 DeoptimizationInputData::New(isolate(), length, TENURED); |
| 905 | 902 |
| 906 Handle<ByteArray> translations = | 903 Handle<ByteArray> translations = |
| (...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1116 HMod* hmod = instr->hydrogen(); | 1113 HMod* hmod = instr->hydrogen(); |
| 1117 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); | 1114 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); |
| 1118 Label dividend_is_not_negative, done; | 1115 Label dividend_is_not_negative, done; |
| 1119 | 1116 |
| 1120 if (hmod->CheckFlag(HValue::kLeftCanBeNegative)) { | 1117 if (hmod->CheckFlag(HValue::kLeftCanBeNegative)) { |
| 1121 __ Branch(÷nd_is_not_negative, ge, dividend, Operand(zero_reg)); | 1118 __ Branch(÷nd_is_not_negative, ge, dividend, Operand(zero_reg)); |
| 1122 // Note: The code below even works when right contains kMinInt. | 1119 // Note: The code below even works when right contains kMinInt. |
| 1123 __ subu(dividend, zero_reg, dividend); | 1120 __ subu(dividend, zero_reg, dividend); |
| 1124 __ And(dividend, dividend, Operand(mask)); | 1121 __ And(dividend, dividend, Operand(mask)); |
| 1125 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1122 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1126 DeoptimizeIf(eq, instr->environment(), dividend, Operand(zero_reg)); | 1123 DeoptimizeIf(eq, instr, dividend, Operand(zero_reg)); |
| 1127 } | 1124 } |
| 1128 __ Branch(USE_DELAY_SLOT, &done); | 1125 __ Branch(USE_DELAY_SLOT, &done); |
| 1129 __ subu(dividend, zero_reg, dividend); | 1126 __ subu(dividend, zero_reg, dividend); |
| 1130 } | 1127 } |
| 1131 | 1128 |
| 1132 __ bind(÷nd_is_not_negative); | 1129 __ bind(÷nd_is_not_negative); |
| 1133 __ And(dividend, dividend, Operand(mask)); | 1130 __ And(dividend, dividend, Operand(mask)); |
| 1134 __ bind(&done); | 1131 __ bind(&done); |
| 1135 } | 1132 } |
| 1136 | 1133 |
| 1137 | 1134 |
| 1138 void LCodeGen::DoModByConstI(LModByConstI* instr) { | 1135 void LCodeGen::DoModByConstI(LModByConstI* instr) { |
| 1139 Register dividend = ToRegister(instr->dividend()); | 1136 Register dividend = ToRegister(instr->dividend()); |
| 1140 int32_t divisor = instr->divisor(); | 1137 int32_t divisor = instr->divisor(); |
| 1141 Register result = ToRegister(instr->result()); | 1138 Register result = ToRegister(instr->result()); |
| 1142 DCHECK(!dividend.is(result)); | 1139 DCHECK(!dividend.is(result)); |
| 1143 | 1140 |
| 1144 if (divisor == 0) { | 1141 if (divisor == 0) { |
| 1145 DeoptimizeIf(al, instr->environment()); | 1142 DeoptimizeIf(al, instr); |
| 1146 return; | 1143 return; |
| 1147 } | 1144 } |
| 1148 | 1145 |
| 1149 __ TruncatingDiv(result, dividend, Abs(divisor)); | 1146 __ TruncatingDiv(result, dividend, Abs(divisor)); |
| 1150 __ Mul(result, result, Operand(Abs(divisor))); | 1147 __ Mul(result, result, Operand(Abs(divisor))); |
| 1151 __ Subu(result, dividend, Operand(result)); | 1148 __ Subu(result, dividend, Operand(result)); |
| 1152 | 1149 |
| 1153 // Check for negative zero. | 1150 // Check for negative zero. |
| 1154 HMod* hmod = instr->hydrogen(); | 1151 HMod* hmod = instr->hydrogen(); |
| 1155 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1152 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1156 Label remainder_not_zero; | 1153 Label remainder_not_zero; |
| 1157 __ Branch(&remainder_not_zero, ne, result, Operand(zero_reg)); | 1154 __ Branch(&remainder_not_zero, ne, result, Operand(zero_reg)); |
| 1158 DeoptimizeIf(lt, instr->environment(), dividend, Operand(zero_reg)); | 1155 DeoptimizeIf(lt, instr, dividend, Operand(zero_reg)); |
| 1159 __ bind(&remainder_not_zero); | 1156 __ bind(&remainder_not_zero); |
| 1160 } | 1157 } |
| 1161 } | 1158 } |
| 1162 | 1159 |
| 1163 | 1160 |
| 1164 void LCodeGen::DoModI(LModI* instr) { | 1161 void LCodeGen::DoModI(LModI* instr) { |
| 1165 HMod* hmod = instr->hydrogen(); | 1162 HMod* hmod = instr->hydrogen(); |
| 1166 const Register left_reg = ToRegister(instr->left()); | 1163 const Register left_reg = ToRegister(instr->left()); |
| 1167 const Register right_reg = ToRegister(instr->right()); | 1164 const Register right_reg = ToRegister(instr->right()); |
| 1168 const Register result_reg = ToRegister(instr->result()); | 1165 const Register result_reg = ToRegister(instr->result()); |
| 1169 | 1166 |
| 1170 // div runs in the background while we check for special cases. | 1167 // div runs in the background while we check for special cases. |
| 1171 __ Mod(result_reg, left_reg, right_reg); | 1168 __ Mod(result_reg, left_reg, right_reg); |
| 1172 | 1169 |
| 1173 Label done; | 1170 Label done; |
| 1174 // Check for x % 0, we have to deopt in this case because we can't return a | 1171 // Check for x % 0, we have to deopt in this case because we can't return a |
| 1175 // NaN. | 1172 // NaN. |
| 1176 if (hmod->CheckFlag(HValue::kCanBeDivByZero)) { | 1173 if (hmod->CheckFlag(HValue::kCanBeDivByZero)) { |
| 1177 DeoptimizeIf(eq, instr->environment(), right_reg, Operand(zero_reg)); | 1174 DeoptimizeIf(eq, instr, right_reg, Operand(zero_reg)); |
| 1178 } | 1175 } |
| 1179 | 1176 |
| 1180 // Check for kMinInt % -1, div will return kMinInt, which is not what we | 1177 // Check for kMinInt % -1, div will return kMinInt, which is not what we |
| 1181 // want. We have to deopt if we care about -0, because we can't return that. | 1178 // want. We have to deopt if we care about -0, because we can't return that. |
| 1182 if (hmod->CheckFlag(HValue::kCanOverflow)) { | 1179 if (hmod->CheckFlag(HValue::kCanOverflow)) { |
| 1183 Label no_overflow_possible; | 1180 Label no_overflow_possible; |
| 1184 __ Branch(&no_overflow_possible, ne, left_reg, Operand(kMinInt)); | 1181 __ Branch(&no_overflow_possible, ne, left_reg, Operand(kMinInt)); |
| 1185 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1182 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1186 DeoptimizeIf(eq, instr->environment(), right_reg, Operand(-1)); | 1183 DeoptimizeIf(eq, instr, right_reg, Operand(-1)); |
| 1187 } else { | 1184 } else { |
| 1188 __ Branch(&no_overflow_possible, ne, right_reg, Operand(-1)); | 1185 __ Branch(&no_overflow_possible, ne, right_reg, Operand(-1)); |
| 1189 __ Branch(USE_DELAY_SLOT, &done); | 1186 __ Branch(USE_DELAY_SLOT, &done); |
| 1190 __ mov(result_reg, zero_reg); | 1187 __ mov(result_reg, zero_reg); |
| 1191 } | 1188 } |
| 1192 __ bind(&no_overflow_possible); | 1189 __ bind(&no_overflow_possible); |
| 1193 } | 1190 } |
| 1194 | 1191 |
| 1195 // If we care about -0, test if the dividend is <0 and the result is 0. | 1192 // If we care about -0, test if the dividend is <0 and the result is 0. |
| 1196 __ Branch(&done, ge, left_reg, Operand(zero_reg)); | 1193 __ Branch(&done, ge, left_reg, Operand(zero_reg)); |
| 1197 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1194 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1198 DeoptimizeIf(eq, instr->environment(), result_reg, Operand(zero_reg)); | 1195 DeoptimizeIf(eq, instr, result_reg, Operand(zero_reg)); |
| 1199 } | 1196 } |
| 1200 __ bind(&done); | 1197 __ bind(&done); |
| 1201 } | 1198 } |
| 1202 | 1199 |
| 1203 | 1200 |
| 1204 void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) { | 1201 void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) { |
| 1205 Register dividend = ToRegister(instr->dividend()); | 1202 Register dividend = ToRegister(instr->dividend()); |
| 1206 int32_t divisor = instr->divisor(); | 1203 int32_t divisor = instr->divisor(); |
| 1207 Register result = ToRegister(instr->result()); | 1204 Register result = ToRegister(instr->result()); |
| 1208 DCHECK(divisor == kMinInt || base::bits::IsPowerOfTwo32(Abs(divisor))); | 1205 DCHECK(divisor == kMinInt || base::bits::IsPowerOfTwo32(Abs(divisor))); |
| 1209 DCHECK(!result.is(dividend)); | 1206 DCHECK(!result.is(dividend)); |
| 1210 | 1207 |
| 1211 // Check for (0 / -x) that will produce negative zero. | 1208 // Check for (0 / -x) that will produce negative zero. |
| 1212 HDiv* hdiv = instr->hydrogen(); | 1209 HDiv* hdiv = instr->hydrogen(); |
| 1213 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { | 1210 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { |
| 1214 DeoptimizeIf(eq, instr->environment(), dividend, Operand(zero_reg)); | 1211 DeoptimizeIf(eq, instr, dividend, Operand(zero_reg)); |
| 1215 } | 1212 } |
| 1216 // Check for (kMinInt / -1). | 1213 // Check for (kMinInt / -1). |
| 1217 if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) { | 1214 if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) { |
| 1218 DeoptimizeIf(eq, instr->environment(), dividend, Operand(kMinInt)); | 1215 DeoptimizeIf(eq, instr, dividend, Operand(kMinInt)); |
| 1219 } | 1216 } |
| 1220 // Deoptimize if remainder will not be 0. | 1217 // Deoptimize if remainder will not be 0. |
| 1221 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) && | 1218 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) && |
| 1222 divisor != 1 && divisor != -1) { | 1219 divisor != 1 && divisor != -1) { |
| 1223 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); | 1220 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); |
| 1224 __ And(at, dividend, Operand(mask)); | 1221 __ And(at, dividend, Operand(mask)); |
| 1225 DeoptimizeIf(ne, instr->environment(), at, Operand(zero_reg)); | 1222 DeoptimizeIf(ne, instr, at, Operand(zero_reg)); |
| 1226 } | 1223 } |
| 1227 | 1224 |
| 1228 if (divisor == -1) { // Nice shortcut, not needed for correctness. | 1225 if (divisor == -1) { // Nice shortcut, not needed for correctness. |
| 1229 __ Subu(result, zero_reg, dividend); | 1226 __ Subu(result, zero_reg, dividend); |
| 1230 return; | 1227 return; |
| 1231 } | 1228 } |
| 1232 uint16_t shift = WhichPowerOf2Abs(divisor); | 1229 uint16_t shift = WhichPowerOf2Abs(divisor); |
| 1233 if (shift == 0) { | 1230 if (shift == 0) { |
| 1234 __ Move(result, dividend); | 1231 __ Move(result, dividend); |
| 1235 } else if (shift == 1) { | 1232 } else if (shift == 1) { |
| 1236 __ srl(result, dividend, 31); | 1233 __ srl(result, dividend, 31); |
| 1237 __ Addu(result, dividend, Operand(result)); | 1234 __ Addu(result, dividend, Operand(result)); |
| 1238 } else { | 1235 } else { |
| 1239 __ sra(result, dividend, 31); | 1236 __ sra(result, dividend, 31); |
| 1240 __ srl(result, result, 32 - shift); | 1237 __ srl(result, result, 32 - shift); |
| 1241 __ Addu(result, dividend, Operand(result)); | 1238 __ Addu(result, dividend, Operand(result)); |
| 1242 } | 1239 } |
| 1243 if (shift > 0) __ sra(result, result, shift); | 1240 if (shift > 0) __ sra(result, result, shift); |
| 1244 if (divisor < 0) __ Subu(result, zero_reg, result); | 1241 if (divisor < 0) __ Subu(result, zero_reg, result); |
| 1245 } | 1242 } |
| 1246 | 1243 |
| 1247 | 1244 |
| 1248 void LCodeGen::DoDivByConstI(LDivByConstI* instr) { | 1245 void LCodeGen::DoDivByConstI(LDivByConstI* instr) { |
| 1249 Register dividend = ToRegister(instr->dividend()); | 1246 Register dividend = ToRegister(instr->dividend()); |
| 1250 int32_t divisor = instr->divisor(); | 1247 int32_t divisor = instr->divisor(); |
| 1251 Register result = ToRegister(instr->result()); | 1248 Register result = ToRegister(instr->result()); |
| 1252 DCHECK(!dividend.is(result)); | 1249 DCHECK(!dividend.is(result)); |
| 1253 | 1250 |
| 1254 if (divisor == 0) { | 1251 if (divisor == 0) { |
| 1255 DeoptimizeIf(al, instr->environment()); | 1252 DeoptimizeIf(al, instr); |
| 1256 return; | 1253 return; |
| 1257 } | 1254 } |
| 1258 | 1255 |
| 1259 // Check for (0 / -x) that will produce negative zero. | 1256 // Check for (0 / -x) that will produce negative zero. |
| 1260 HDiv* hdiv = instr->hydrogen(); | 1257 HDiv* hdiv = instr->hydrogen(); |
| 1261 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { | 1258 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { |
| 1262 DeoptimizeIf(eq, instr->environment(), dividend, Operand(zero_reg)); | 1259 DeoptimizeIf(eq, instr, dividend, Operand(zero_reg)); |
| 1263 } | 1260 } |
| 1264 | 1261 |
| 1265 __ TruncatingDiv(result, dividend, Abs(divisor)); | 1262 __ TruncatingDiv(result, dividend, Abs(divisor)); |
| 1266 if (divisor < 0) __ Subu(result, zero_reg, result); | 1263 if (divisor < 0) __ Subu(result, zero_reg, result); |
| 1267 | 1264 |
| 1268 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) { | 1265 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) { |
| 1269 __ Mul(scratch0(), result, Operand(divisor)); | 1266 __ Mul(scratch0(), result, Operand(divisor)); |
| 1270 __ Subu(scratch0(), scratch0(), dividend); | 1267 __ Subu(scratch0(), scratch0(), dividend); |
| 1271 DeoptimizeIf(ne, instr->environment(), scratch0(), Operand(zero_reg)); | 1268 DeoptimizeIf(ne, instr, scratch0(), Operand(zero_reg)); |
| 1272 } | 1269 } |
| 1273 } | 1270 } |
| 1274 | 1271 |
| 1275 | 1272 |
| 1276 // TODO(svenpanne) Refactor this to avoid code duplication with DoFlooringDivI. | 1273 // TODO(svenpanne) Refactor this to avoid code duplication with DoFlooringDivI. |
| 1277 void LCodeGen::DoDivI(LDivI* instr) { | 1274 void LCodeGen::DoDivI(LDivI* instr) { |
| 1278 HBinaryOperation* hdiv = instr->hydrogen(); | 1275 HBinaryOperation* hdiv = instr->hydrogen(); |
| 1279 Register dividend = ToRegister(instr->dividend()); | 1276 Register dividend = ToRegister(instr->dividend()); |
| 1280 Register divisor = ToRegister(instr->divisor()); | 1277 Register divisor = ToRegister(instr->divisor()); |
| 1281 const Register result = ToRegister(instr->result()); | 1278 const Register result = ToRegister(instr->result()); |
| 1282 Register remainder = ToRegister(instr->temp()); | 1279 Register remainder = ToRegister(instr->temp()); |
| 1283 | 1280 |
| 1284 // On MIPS div is asynchronous - it will run in the background while we | 1281 // On MIPS div is asynchronous - it will run in the background while we |
| 1285 // check for special cases. | 1282 // check for special cases. |
| 1286 __ Div(remainder, result, dividend, divisor); | 1283 __ Div(remainder, result, dividend, divisor); |
| 1287 | 1284 |
| 1288 // Check for x / 0. | 1285 // Check for x / 0. |
| 1289 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { | 1286 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { |
| 1290 DeoptimizeIf(eq, instr->environment(), divisor, Operand(zero_reg)); | 1287 DeoptimizeIf(eq, instr, divisor, Operand(zero_reg)); |
| 1291 } | 1288 } |
| 1292 | 1289 |
| 1293 // Check for (0 / -x) that will produce negative zero. | 1290 // Check for (0 / -x) that will produce negative zero. |
| 1294 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1291 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1295 Label left_not_zero; | 1292 Label left_not_zero; |
| 1296 __ Branch(&left_not_zero, ne, dividend, Operand(zero_reg)); | 1293 __ Branch(&left_not_zero, ne, dividend, Operand(zero_reg)); |
| 1297 DeoptimizeIf(lt, instr->environment(), divisor, Operand(zero_reg)); | 1294 DeoptimizeIf(lt, instr, divisor, Operand(zero_reg)); |
| 1298 __ bind(&left_not_zero); | 1295 __ bind(&left_not_zero); |
| 1299 } | 1296 } |
| 1300 | 1297 |
| 1301 // Check for (kMinInt / -1). | 1298 // Check for (kMinInt / -1). |
| 1302 if (hdiv->CheckFlag(HValue::kCanOverflow) && | 1299 if (hdiv->CheckFlag(HValue::kCanOverflow) && |
| 1303 !hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { | 1300 !hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { |
| 1304 Label left_not_min_int; | 1301 Label left_not_min_int; |
| 1305 __ Branch(&left_not_min_int, ne, dividend, Operand(kMinInt)); | 1302 __ Branch(&left_not_min_int, ne, dividend, Operand(kMinInt)); |
| 1306 DeoptimizeIf(eq, instr->environment(), divisor, Operand(-1)); | 1303 DeoptimizeIf(eq, instr, divisor, Operand(-1)); |
| 1307 __ bind(&left_not_min_int); | 1304 __ bind(&left_not_min_int); |
| 1308 } | 1305 } |
| 1309 | 1306 |
| 1310 if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { | 1307 if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { |
| 1311 DeoptimizeIf(ne, instr->environment(), remainder, Operand(zero_reg)); | 1308 DeoptimizeIf(ne, instr, remainder, Operand(zero_reg)); |
| 1312 } | 1309 } |
| 1313 } | 1310 } |
| 1314 | 1311 |
| 1315 | 1312 |
| 1316 void LCodeGen::DoMultiplyAddD(LMultiplyAddD* instr) { | 1313 void LCodeGen::DoMultiplyAddD(LMultiplyAddD* instr) { |
| 1317 DoubleRegister addend = ToDoubleRegister(instr->addend()); | 1314 DoubleRegister addend = ToDoubleRegister(instr->addend()); |
| 1318 DoubleRegister multiplier = ToDoubleRegister(instr->multiplier()); | 1315 DoubleRegister multiplier = ToDoubleRegister(instr->multiplier()); |
| 1319 DoubleRegister multiplicand = ToDoubleRegister(instr->multiplicand()); | 1316 DoubleRegister multiplicand = ToDoubleRegister(instr->multiplicand()); |
| 1320 | 1317 |
| 1321 // This is computed in-place. | 1318 // This is computed in-place. |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1347 } | 1344 } |
| 1348 | 1345 |
| 1349 // If the divisor is negative, we have to negate and handle edge cases. | 1346 // If the divisor is negative, we have to negate and handle edge cases. |
| 1350 | 1347 |
| 1351 // dividend can be the same register as result so save the value of it | 1348 // dividend can be the same register as result so save the value of it |
| 1352 // for checking overflow. | 1349 // for checking overflow. |
| 1353 __ Move(scratch, dividend); | 1350 __ Move(scratch, dividend); |
| 1354 | 1351 |
| 1355 __ Subu(result, zero_reg, dividend); | 1352 __ Subu(result, zero_reg, dividend); |
| 1356 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1353 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1357 DeoptimizeIf(eq, instr->environment(), result, Operand(zero_reg)); | 1354 DeoptimizeIf(eq, instr, result, Operand(zero_reg)); |
| 1358 } | 1355 } |
| 1359 | 1356 |
| 1360 // Dividing by -1 is basically negation, unless we overflow. | 1357 // Dividing by -1 is basically negation, unless we overflow. |
| 1361 __ Xor(scratch, scratch, result); | 1358 __ Xor(scratch, scratch, result); |
| 1362 if (divisor == -1) { | 1359 if (divisor == -1) { |
| 1363 if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { | 1360 if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { |
| 1364 DeoptimizeIf(ge, instr->environment(), scratch, Operand(zero_reg)); | 1361 DeoptimizeIf(ge, instr, scratch, Operand(zero_reg)); |
| 1365 } | 1362 } |
| 1366 return; | 1363 return; |
| 1367 } | 1364 } |
| 1368 | 1365 |
| 1369 // If the negation could not overflow, simply shifting is OK. | 1366 // If the negation could not overflow, simply shifting is OK. |
| 1370 if (!instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { | 1367 if (!instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { |
| 1371 __ sra(result, result, shift); | 1368 __ sra(result, result, shift); |
| 1372 return; | 1369 return; |
| 1373 } | 1370 } |
| 1374 | 1371 |
| 1375 Label no_overflow, done; | 1372 Label no_overflow, done; |
| 1376 __ Branch(&no_overflow, lt, scratch, Operand(zero_reg)); | 1373 __ Branch(&no_overflow, lt, scratch, Operand(zero_reg)); |
| 1377 __ li(result, Operand(kMinInt / divisor)); | 1374 __ li(result, Operand(kMinInt / divisor)); |
| 1378 __ Branch(&done); | 1375 __ Branch(&done); |
| 1379 __ bind(&no_overflow); | 1376 __ bind(&no_overflow); |
| 1380 __ sra(result, result, shift); | 1377 __ sra(result, result, shift); |
| 1381 __ bind(&done); | 1378 __ bind(&done); |
| 1382 } | 1379 } |
| 1383 | 1380 |
| 1384 | 1381 |
| 1385 void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) { | 1382 void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) { |
| 1386 Register dividend = ToRegister(instr->dividend()); | 1383 Register dividend = ToRegister(instr->dividend()); |
| 1387 int32_t divisor = instr->divisor(); | 1384 int32_t divisor = instr->divisor(); |
| 1388 Register result = ToRegister(instr->result()); | 1385 Register result = ToRegister(instr->result()); |
| 1389 DCHECK(!dividend.is(result)); | 1386 DCHECK(!dividend.is(result)); |
| 1390 | 1387 |
| 1391 if (divisor == 0) { | 1388 if (divisor == 0) { |
| 1392 DeoptimizeIf(al, instr->environment()); | 1389 DeoptimizeIf(al, instr); |
| 1393 return; | 1390 return; |
| 1394 } | 1391 } |
| 1395 | 1392 |
| 1396 // Check for (0 / -x) that will produce negative zero. | 1393 // Check for (0 / -x) that will produce negative zero. |
| 1397 HMathFloorOfDiv* hdiv = instr->hydrogen(); | 1394 HMathFloorOfDiv* hdiv = instr->hydrogen(); |
| 1398 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { | 1395 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { |
| 1399 DeoptimizeIf(eq, instr->environment(), dividend, Operand(zero_reg)); | 1396 DeoptimizeIf(eq, instr, dividend, Operand(zero_reg)); |
| 1400 } | 1397 } |
| 1401 | 1398 |
| 1402 // Easy case: We need no dynamic check for the dividend and the flooring | 1399 // Easy case: We need no dynamic check for the dividend and the flooring |
| 1403 // division is the same as the truncating division. | 1400 // division is the same as the truncating division. |
| 1404 if ((divisor > 0 && !hdiv->CheckFlag(HValue::kLeftCanBeNegative)) || | 1401 if ((divisor > 0 && !hdiv->CheckFlag(HValue::kLeftCanBeNegative)) || |
| 1405 (divisor < 0 && !hdiv->CheckFlag(HValue::kLeftCanBePositive))) { | 1402 (divisor < 0 && !hdiv->CheckFlag(HValue::kLeftCanBePositive))) { |
| 1406 __ TruncatingDiv(result, dividend, Abs(divisor)); | 1403 __ TruncatingDiv(result, dividend, Abs(divisor)); |
| 1407 if (divisor < 0) __ Subu(result, zero_reg, result); | 1404 if (divisor < 0) __ Subu(result, zero_reg, result); |
| 1408 return; | 1405 return; |
| 1409 } | 1406 } |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1433 Register dividend = ToRegister(instr->dividend()); | 1430 Register dividend = ToRegister(instr->dividend()); |
| 1434 Register divisor = ToRegister(instr->divisor()); | 1431 Register divisor = ToRegister(instr->divisor()); |
| 1435 const Register result = ToRegister(instr->result()); | 1432 const Register result = ToRegister(instr->result()); |
| 1436 Register remainder = scratch0(); | 1433 Register remainder = scratch0(); |
| 1437 // On MIPS div is asynchronous - it will run in the background while we | 1434 // On MIPS div is asynchronous - it will run in the background while we |
| 1438 // check for special cases. | 1435 // check for special cases. |
| 1439 __ Div(remainder, result, dividend, divisor); | 1436 __ Div(remainder, result, dividend, divisor); |
| 1440 | 1437 |
| 1441 // Check for x / 0. | 1438 // Check for x / 0. |
| 1442 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { | 1439 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { |
| 1443 DeoptimizeIf(eq, instr->environment(), divisor, Operand(zero_reg)); | 1440 DeoptimizeIf(eq, instr, divisor, Operand(zero_reg)); |
| 1444 } | 1441 } |
| 1445 | 1442 |
| 1446 // Check for (0 / -x) that will produce negative zero. | 1443 // Check for (0 / -x) that will produce negative zero. |
| 1447 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1444 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1448 Label left_not_zero; | 1445 Label left_not_zero; |
| 1449 __ Branch(&left_not_zero, ne, dividend, Operand(zero_reg)); | 1446 __ Branch(&left_not_zero, ne, dividend, Operand(zero_reg)); |
| 1450 DeoptimizeIf(lt, instr->environment(), divisor, Operand(zero_reg)); | 1447 DeoptimizeIf(lt, instr, divisor, Operand(zero_reg)); |
| 1451 __ bind(&left_not_zero); | 1448 __ bind(&left_not_zero); |
| 1452 } | 1449 } |
| 1453 | 1450 |
| 1454 // Check for (kMinInt / -1). | 1451 // Check for (kMinInt / -1). |
| 1455 if (hdiv->CheckFlag(HValue::kCanOverflow) && | 1452 if (hdiv->CheckFlag(HValue::kCanOverflow) && |
| 1456 !hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { | 1453 !hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { |
| 1457 Label left_not_min_int; | 1454 Label left_not_min_int; |
| 1458 __ Branch(&left_not_min_int, ne, dividend, Operand(kMinInt)); | 1455 __ Branch(&left_not_min_int, ne, dividend, Operand(kMinInt)); |
| 1459 DeoptimizeIf(eq, instr->environment(), divisor, Operand(-1)); | 1456 DeoptimizeIf(eq, instr, divisor, Operand(-1)); |
| 1460 __ bind(&left_not_min_int); | 1457 __ bind(&left_not_min_int); |
| 1461 } | 1458 } |
| 1462 | 1459 |
| 1463 // We performed a truncating division. Correct the result if necessary. | 1460 // We performed a truncating division. Correct the result if necessary. |
| 1464 Label done; | 1461 Label done; |
| 1465 __ Branch(&done, eq, remainder, Operand(zero_reg), USE_DELAY_SLOT); | 1462 __ Branch(&done, eq, remainder, Operand(zero_reg), USE_DELAY_SLOT); |
| 1466 __ Xor(remainder, remainder, Operand(divisor)); | 1463 __ Xor(remainder, remainder, Operand(divisor)); |
| 1467 __ Branch(&done, ge, remainder, Operand(zero_reg)); | 1464 __ Branch(&done, ge, remainder, Operand(zero_reg)); |
| 1468 __ Subu(result, result, Operand(1)); | 1465 __ Subu(result, result, Operand(1)); |
| 1469 __ bind(&done); | 1466 __ bind(&done); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1480 bool bailout_on_minus_zero = | 1477 bool bailout_on_minus_zero = |
| 1481 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero); | 1478 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero); |
| 1482 bool overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); | 1479 bool overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); |
| 1483 | 1480 |
| 1484 if (right_op->IsConstantOperand()) { | 1481 if (right_op->IsConstantOperand()) { |
| 1485 int32_t constant = ToInteger32(LConstantOperand::cast(right_op)); | 1482 int32_t constant = ToInteger32(LConstantOperand::cast(right_op)); |
| 1486 | 1483 |
| 1487 if (bailout_on_minus_zero && (constant < 0)) { | 1484 if (bailout_on_minus_zero && (constant < 0)) { |
| 1488 // The case of a null constant will be handled separately. | 1485 // The case of a null constant will be handled separately. |
| 1489 // If constant is negative and left is null, the result should be -0. | 1486 // If constant is negative and left is null, the result should be -0. |
| 1490 DeoptimizeIf(eq, instr->environment(), left, Operand(zero_reg)); | 1487 DeoptimizeIf(eq, instr, left, Operand(zero_reg)); |
| 1491 } | 1488 } |
| 1492 | 1489 |
| 1493 switch (constant) { | 1490 switch (constant) { |
| 1494 case -1: | 1491 case -1: |
| 1495 if (overflow) { | 1492 if (overflow) { |
| 1496 __ SubuAndCheckForOverflow(result, zero_reg, left, scratch); | 1493 __ SubuAndCheckForOverflow(result, zero_reg, left, scratch); |
| 1497 DeoptimizeIf(lt, instr->environment(), scratch, Operand(zero_reg)); | 1494 DeoptimizeIf(lt, instr, scratch, Operand(zero_reg)); |
| 1498 } else { | 1495 } else { |
| 1499 __ Subu(result, zero_reg, left); | 1496 __ Subu(result, zero_reg, left); |
| 1500 } | 1497 } |
| 1501 break; | 1498 break; |
| 1502 case 0: | 1499 case 0: |
| 1503 if (bailout_on_minus_zero) { | 1500 if (bailout_on_minus_zero) { |
| 1504 // If left is strictly negative and the constant is null, the | 1501 // If left is strictly negative and the constant is null, the |
| 1505 // result is -0. Deoptimize if required, otherwise return 0. | 1502 // result is -0. Deoptimize if required, otherwise return 0. |
| 1506 DeoptimizeIf(lt, instr->environment(), left, Operand(zero_reg)); | 1503 DeoptimizeIf(lt, instr, left, Operand(zero_reg)); |
| 1507 } | 1504 } |
| 1508 __ mov(result, zero_reg); | 1505 __ mov(result, zero_reg); |
| 1509 break; | 1506 break; |
| 1510 case 1: | 1507 case 1: |
| 1511 // Nothing to do. | 1508 // Nothing to do. |
| 1512 __ Move(result, left); | 1509 __ Move(result, left); |
| 1513 break; | 1510 break; |
| 1514 default: | 1511 default: |
| 1515 // Multiplying by powers of two and powers of two plus or minus | 1512 // Multiplying by powers of two and powers of two plus or minus |
| 1516 // one can be done faster with shifted operands. | 1513 // one can be done faster with shifted operands. |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1548 | 1545 |
| 1549 if (overflow) { | 1546 if (overflow) { |
| 1550 // hi:lo = left * right. | 1547 // hi:lo = left * right. |
| 1551 if (instr->hydrogen()->representation().IsSmi()) { | 1548 if (instr->hydrogen()->representation().IsSmi()) { |
| 1552 __ SmiUntag(result, left); | 1549 __ SmiUntag(result, left); |
| 1553 __ Mul(scratch, result, result, right); | 1550 __ Mul(scratch, result, result, right); |
| 1554 } else { | 1551 } else { |
| 1555 __ Mul(scratch, result, left, right); | 1552 __ Mul(scratch, result, left, right); |
| 1556 } | 1553 } |
| 1557 __ sra(at, result, 31); | 1554 __ sra(at, result, 31); |
| 1558 DeoptimizeIf(ne, instr->environment(), scratch, Operand(at)); | 1555 DeoptimizeIf(ne, instr, scratch, Operand(at)); |
| 1559 } else { | 1556 } else { |
| 1560 if (instr->hydrogen()->representation().IsSmi()) { | 1557 if (instr->hydrogen()->representation().IsSmi()) { |
| 1561 __ SmiUntag(result, left); | 1558 __ SmiUntag(result, left); |
| 1562 __ Mul(result, result, right); | 1559 __ Mul(result, result, right); |
| 1563 } else { | 1560 } else { |
| 1564 __ Mul(result, left, right); | 1561 __ Mul(result, left, right); |
| 1565 } | 1562 } |
| 1566 } | 1563 } |
| 1567 | 1564 |
| 1568 if (bailout_on_minus_zero) { | 1565 if (bailout_on_minus_zero) { |
| 1569 Label done; | 1566 Label done; |
| 1570 __ Xor(at, left, right); | 1567 __ Xor(at, left, right); |
| 1571 __ Branch(&done, ge, at, Operand(zero_reg)); | 1568 __ Branch(&done, ge, at, Operand(zero_reg)); |
| 1572 // Bail out if the result is minus zero. | 1569 // Bail out if the result is minus zero. |
| 1573 DeoptimizeIf(eq, | 1570 DeoptimizeIf(eq, instr, result, Operand(zero_reg)); |
| 1574 instr->environment(), | |
| 1575 result, | |
| 1576 Operand(zero_reg)); | |
| 1577 __ bind(&done); | 1571 __ bind(&done); |
| 1578 } | 1572 } |
| 1579 } | 1573 } |
| 1580 } | 1574 } |
| 1581 | 1575 |
| 1582 | 1576 |
| 1583 void LCodeGen::DoBitI(LBitI* instr) { | 1577 void LCodeGen::DoBitI(LBitI* instr) { |
| 1584 LOperand* left_op = instr->left(); | 1578 LOperand* left_op = instr->left(); |
| 1585 LOperand* right_op = instr->right(); | 1579 LOperand* right_op = instr->right(); |
| 1586 DCHECK(left_op->IsRegister()); | 1580 DCHECK(left_op->IsRegister()); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1630 switch (instr->op()) { | 1624 switch (instr->op()) { |
| 1631 case Token::ROR: | 1625 case Token::ROR: |
| 1632 __ Ror(result, left, Operand(ToRegister(right_op))); | 1626 __ Ror(result, left, Operand(ToRegister(right_op))); |
| 1633 break; | 1627 break; |
| 1634 case Token::SAR: | 1628 case Token::SAR: |
| 1635 __ srav(result, left, ToRegister(right_op)); | 1629 __ srav(result, left, ToRegister(right_op)); |
| 1636 break; | 1630 break; |
| 1637 case Token::SHR: | 1631 case Token::SHR: |
| 1638 __ srlv(result, left, ToRegister(right_op)); | 1632 __ srlv(result, left, ToRegister(right_op)); |
| 1639 if (instr->can_deopt()) { | 1633 if (instr->can_deopt()) { |
| 1640 DeoptimizeIf(lt, instr->environment(), result, Operand(zero_reg)); | 1634 DeoptimizeIf(lt, instr, result, Operand(zero_reg)); |
| 1641 } | 1635 } |
| 1642 break; | 1636 break; |
| 1643 case Token::SHL: | 1637 case Token::SHL: |
| 1644 __ sllv(result, left, ToRegister(right_op)); | 1638 __ sllv(result, left, ToRegister(right_op)); |
| 1645 break; | 1639 break; |
| 1646 default: | 1640 default: |
| 1647 UNREACHABLE(); | 1641 UNREACHABLE(); |
| 1648 break; | 1642 break; |
| 1649 } | 1643 } |
| 1650 } else { | 1644 } else { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1665 } else { | 1659 } else { |
| 1666 __ Move(result, left); | 1660 __ Move(result, left); |
| 1667 } | 1661 } |
| 1668 break; | 1662 break; |
| 1669 case Token::SHR: | 1663 case Token::SHR: |
| 1670 if (shift_count != 0) { | 1664 if (shift_count != 0) { |
| 1671 __ srl(result, left, shift_count); | 1665 __ srl(result, left, shift_count); |
| 1672 } else { | 1666 } else { |
| 1673 if (instr->can_deopt()) { | 1667 if (instr->can_deopt()) { |
| 1674 __ And(at, left, Operand(0x80000000)); | 1668 __ And(at, left, Operand(0x80000000)); |
| 1675 DeoptimizeIf(ne, instr->environment(), at, Operand(zero_reg)); | 1669 DeoptimizeIf(ne, instr, at, Operand(zero_reg)); |
| 1676 } | 1670 } |
| 1677 __ Move(result, left); | 1671 __ Move(result, left); |
| 1678 } | 1672 } |
| 1679 break; | 1673 break; |
| 1680 case Token::SHL: | 1674 case Token::SHL: |
| 1681 if (shift_count != 0) { | 1675 if (shift_count != 0) { |
| 1682 if (instr->hydrogen_value()->representation().IsSmi() && | 1676 if (instr->hydrogen_value()->representation().IsSmi() && |
| 1683 instr->can_deopt()) { | 1677 instr->can_deopt()) { |
| 1684 if (shift_count != 1) { | 1678 if (shift_count != 1) { |
| 1685 __ sll(result, left, shift_count - 1); | 1679 __ sll(result, left, shift_count - 1); |
| 1686 __ SmiTagCheckOverflow(result, result, scratch); | 1680 __ SmiTagCheckOverflow(result, result, scratch); |
| 1687 } else { | 1681 } else { |
| 1688 __ SmiTagCheckOverflow(result, left, scratch); | 1682 __ SmiTagCheckOverflow(result, left, scratch); |
| 1689 } | 1683 } |
| 1690 DeoptimizeIf(lt, instr->environment(), scratch, Operand(zero_reg)); | 1684 DeoptimizeIf(lt, instr, scratch, Operand(zero_reg)); |
| 1691 } else { | 1685 } else { |
| 1692 __ sll(result, left, shift_count); | 1686 __ sll(result, left, shift_count); |
| 1693 } | 1687 } |
| 1694 } else { | 1688 } else { |
| 1695 __ Move(result, left); | 1689 __ Move(result, left); |
| 1696 } | 1690 } |
| 1697 break; | 1691 break; |
| 1698 default: | 1692 default: |
| 1699 UNREACHABLE(); | 1693 UNREACHABLE(); |
| 1700 break; | 1694 break; |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1728 overflow); // Reg at also used as scratch. | 1722 overflow); // Reg at also used as scratch. |
| 1729 } else { | 1723 } else { |
| 1730 DCHECK(right->IsRegister()); | 1724 DCHECK(right->IsRegister()); |
| 1731 // Due to overflow check macros not supporting constant operands, | 1725 // Due to overflow check macros not supporting constant operands, |
| 1732 // handling the IsConstantOperand case was moved to prev if clause. | 1726 // handling the IsConstantOperand case was moved to prev if clause. |
| 1733 __ SubuAndCheckForOverflow(ToRegister(result), | 1727 __ SubuAndCheckForOverflow(ToRegister(result), |
| 1734 ToRegister(left), | 1728 ToRegister(left), |
| 1735 ToRegister(right), | 1729 ToRegister(right), |
| 1736 overflow); // Reg at also used as scratch. | 1730 overflow); // Reg at also used as scratch. |
| 1737 } | 1731 } |
| 1738 DeoptimizeIf(lt, instr->environment(), overflow, Operand(zero_reg)); | 1732 DeoptimizeIf(lt, instr, overflow, Operand(zero_reg)); |
| 1739 } | 1733 } |
| 1740 } | 1734 } |
| 1741 | 1735 |
| 1742 | 1736 |
| 1743 void LCodeGen::DoConstantI(LConstantI* instr) { | 1737 void LCodeGen::DoConstantI(LConstantI* instr) { |
| 1744 __ li(ToRegister(instr->result()), Operand(instr->value())); | 1738 __ li(ToRegister(instr->result()), Operand(instr->value())); |
| 1745 } | 1739 } |
| 1746 | 1740 |
| 1747 | 1741 |
| 1748 void LCodeGen::DoConstantS(LConstantS* instr) { | 1742 void LCodeGen::DoConstantS(LConstantS* instr) { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1782 Register result = ToRegister(instr->result()); | 1776 Register result = ToRegister(instr->result()); |
| 1783 Register scratch = ToRegister(instr->temp()); | 1777 Register scratch = ToRegister(instr->temp()); |
| 1784 Smi* index = instr->index(); | 1778 Smi* index = instr->index(); |
| 1785 Label runtime, done; | 1779 Label runtime, done; |
| 1786 DCHECK(object.is(a0)); | 1780 DCHECK(object.is(a0)); |
| 1787 DCHECK(result.is(v0)); | 1781 DCHECK(result.is(v0)); |
| 1788 DCHECK(!scratch.is(scratch0())); | 1782 DCHECK(!scratch.is(scratch0())); |
| 1789 DCHECK(!scratch.is(object)); | 1783 DCHECK(!scratch.is(object)); |
| 1790 | 1784 |
| 1791 __ SmiTst(object, at); | 1785 __ SmiTst(object, at); |
| 1792 DeoptimizeIf(eq, instr->environment(), at, Operand(zero_reg)); | 1786 DeoptimizeIf(eq, instr, at, Operand(zero_reg)); |
| 1793 __ GetObjectType(object, scratch, scratch); | 1787 __ GetObjectType(object, scratch, scratch); |
| 1794 DeoptimizeIf(ne, instr->environment(), scratch, Operand(JS_DATE_TYPE)); | 1788 DeoptimizeIf(ne, instr, scratch, Operand(JS_DATE_TYPE)); |
| 1795 | 1789 |
| 1796 if (index->value() == 0) { | 1790 if (index->value() == 0) { |
| 1797 __ lw(result, FieldMemOperand(object, JSDate::kValueOffset)); | 1791 __ lw(result, FieldMemOperand(object, JSDate::kValueOffset)); |
| 1798 } else { | 1792 } else { |
| 1799 if (index->value() < JSDate::kFirstUncachedField) { | 1793 if (index->value() < JSDate::kFirstUncachedField) { |
| 1800 ExternalReference stamp = ExternalReference::date_cache_stamp(isolate()); | 1794 ExternalReference stamp = ExternalReference::date_cache_stamp(isolate()); |
| 1801 __ li(scratch, Operand(stamp)); | 1795 __ li(scratch, Operand(stamp)); |
| 1802 __ lw(scratch, MemOperand(scratch)); | 1796 __ lw(scratch, MemOperand(scratch)); |
| 1803 __ lw(scratch0(), FieldMemOperand(object, JSDate::kCacheStampOffset)); | 1797 __ lw(scratch0(), FieldMemOperand(object, JSDate::kCacheStampOffset)); |
| 1804 __ Branch(&runtime, ne, scratch, Operand(scratch0())); | 1798 __ Branch(&runtime, ne, scratch, Operand(scratch0())); |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1919 overflow); // Reg at also used as scratch. | 1913 overflow); // Reg at also used as scratch. |
| 1920 } else { | 1914 } else { |
| 1921 DCHECK(right->IsRegister()); | 1915 DCHECK(right->IsRegister()); |
| 1922 // Due to overflow check macros not supporting constant operands, | 1916 // Due to overflow check macros not supporting constant operands, |
| 1923 // handling the IsConstantOperand case was moved to prev if clause. | 1917 // handling the IsConstantOperand case was moved to prev if clause. |
| 1924 __ AdduAndCheckForOverflow(ToRegister(result), | 1918 __ AdduAndCheckForOverflow(ToRegister(result), |
| 1925 ToRegister(left), | 1919 ToRegister(left), |
| 1926 ToRegister(right), | 1920 ToRegister(right), |
| 1927 overflow); // Reg at also used as scratch. | 1921 overflow); // Reg at also used as scratch. |
| 1928 } | 1922 } |
| 1929 DeoptimizeIf(lt, instr->environment(), overflow, Operand(zero_reg)); | 1923 DeoptimizeIf(lt, instr, overflow, Operand(zero_reg)); |
| 1930 } | 1924 } |
| 1931 } | 1925 } |
| 1932 | 1926 |
| 1933 | 1927 |
| 1934 void LCodeGen::DoMathMinMax(LMathMinMax* instr) { | 1928 void LCodeGen::DoMathMinMax(LMathMinMax* instr) { |
| 1935 LOperand* left = instr->left(); | 1929 LOperand* left = instr->left(); |
| 1936 LOperand* right = instr->right(); | 1930 LOperand* right = instr->right(); |
| 1937 HMathMinMax::Operation operation = instr->hydrogen()->operation(); | 1931 HMathMinMax::Operation operation = instr->hydrogen()->operation(); |
| 1938 Condition condition = (operation == HMathMinMax::kMathMin) ? le : ge; | 1932 Condition condition = (operation == HMathMinMax::kMathMin) ? le : ge; |
| 1939 if (instr->hydrogen()->representation().IsSmiOrInteger32()) { | 1933 if (instr->hydrogen()->representation().IsSmiOrInteger32()) { |
| (...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2180 __ Branch(instr->FalseLabel(chunk_), eq, reg, Operand(at)); | 2174 __ Branch(instr->FalseLabel(chunk_), eq, reg, Operand(at)); |
| 2181 } | 2175 } |
| 2182 | 2176 |
| 2183 if (expected.Contains(ToBooleanStub::SMI)) { | 2177 if (expected.Contains(ToBooleanStub::SMI)) { |
| 2184 // Smis: 0 -> false, all other -> true. | 2178 // Smis: 0 -> false, all other -> true. |
| 2185 __ Branch(instr->FalseLabel(chunk_), eq, reg, Operand(zero_reg)); | 2179 __ Branch(instr->FalseLabel(chunk_), eq, reg, Operand(zero_reg)); |
| 2186 __ JumpIfSmi(reg, instr->TrueLabel(chunk_)); | 2180 __ JumpIfSmi(reg, instr->TrueLabel(chunk_)); |
| 2187 } else if (expected.NeedsMap()) { | 2181 } else if (expected.NeedsMap()) { |
| 2188 // If we need a map later and have a Smi -> deopt. | 2182 // If we need a map later and have a Smi -> deopt. |
| 2189 __ SmiTst(reg, at); | 2183 __ SmiTst(reg, at); |
| 2190 DeoptimizeIf(eq, instr->environment(), at, Operand(zero_reg)); | 2184 DeoptimizeIf(eq, instr, at, Operand(zero_reg)); |
| 2191 } | 2185 } |
| 2192 | 2186 |
| 2193 const Register map = scratch0(); | 2187 const Register map = scratch0(); |
| 2194 if (expected.NeedsMap()) { | 2188 if (expected.NeedsMap()) { |
| 2195 __ lw(map, FieldMemOperand(reg, HeapObject::kMapOffset)); | 2189 __ lw(map, FieldMemOperand(reg, HeapObject::kMapOffset)); |
| 2196 if (expected.CanBeUndetectable()) { | 2190 if (expected.CanBeUndetectable()) { |
| 2197 // Undetectable -> false. | 2191 // Undetectable -> false. |
| 2198 __ lbu(at, FieldMemOperand(map, Map::kBitFieldOffset)); | 2192 __ lbu(at, FieldMemOperand(map, Map::kBitFieldOffset)); |
| 2199 __ And(at, at, Operand(1 << Map::kIsUndetectable)); | 2193 __ And(at, at, Operand(1 << Map::kIsUndetectable)); |
| 2200 __ Branch(instr->FalseLabel(chunk_), ne, at, Operand(zero_reg)); | 2194 __ Branch(instr->FalseLabel(chunk_), ne, at, Operand(zero_reg)); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2236 __ BranchF(instr->TrueLabel(chunk_), instr->FalseLabel(chunk_), | 2230 __ BranchF(instr->TrueLabel(chunk_), instr->FalseLabel(chunk_), |
| 2237 ne, dbl_scratch, kDoubleRegZero); | 2231 ne, dbl_scratch, kDoubleRegZero); |
| 2238 // Falls through if dbl_scratch == 0. | 2232 // Falls through if dbl_scratch == 0. |
| 2239 __ Branch(instr->FalseLabel(chunk_)); | 2233 __ Branch(instr->FalseLabel(chunk_)); |
| 2240 __ bind(¬_heap_number); | 2234 __ bind(¬_heap_number); |
| 2241 } | 2235 } |
| 2242 | 2236 |
| 2243 if (!expected.IsGeneric()) { | 2237 if (!expected.IsGeneric()) { |
| 2244 // We've seen something for the first time -> deopt. | 2238 // We've seen something for the first time -> deopt. |
| 2245 // This can only happen if we are not generic already. | 2239 // This can only happen if we are not generic already. |
| 2246 DeoptimizeIf(al, instr->environment(), zero_reg, Operand(zero_reg)); | 2240 DeoptimizeIf(al, instr, zero_reg, Operand(zero_reg)); |
| 2247 } | 2241 } |
| 2248 } | 2242 } |
| 2249 } | 2243 } |
| 2250 } | 2244 } |
| 2251 | 2245 |
| 2252 | 2246 |
| 2253 void LCodeGen::EmitGoto(int block) { | 2247 void LCodeGen::EmitGoto(int block) { |
| 2254 if (!IsNextEmittedBlock(block)) { | 2248 if (!IsNextEmittedBlock(block)) { |
| 2255 __ jmp(chunk_->GetAssemblyLabel(LookupDestination(block))); | 2249 __ jmp(chunk_->GetAssemblyLabel(LookupDestination(block))); |
| 2256 } | 2250 } |
| (...skipping 623 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2880 } | 2874 } |
| 2881 } | 2875 } |
| 2882 | 2876 |
| 2883 | 2877 |
| 2884 void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) { | 2878 void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) { |
| 2885 Register result = ToRegister(instr->result()); | 2879 Register result = ToRegister(instr->result()); |
| 2886 __ li(at, Operand(Handle<Object>(instr->hydrogen()->cell().handle()))); | 2880 __ li(at, Operand(Handle<Object>(instr->hydrogen()->cell().handle()))); |
| 2887 __ lw(result, FieldMemOperand(at, Cell::kValueOffset)); | 2881 __ lw(result, FieldMemOperand(at, Cell::kValueOffset)); |
| 2888 if (instr->hydrogen()->RequiresHoleCheck()) { | 2882 if (instr->hydrogen()->RequiresHoleCheck()) { |
| 2889 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | 2883 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
| 2890 DeoptimizeIf(eq, instr->environment(), result, Operand(at)); | 2884 DeoptimizeIf(eq, instr, result, Operand(at)); |
| 2891 } | 2885 } |
| 2892 } | 2886 } |
| 2893 | 2887 |
| 2894 | 2888 |
| 2895 template <class T> | 2889 template <class T> |
| 2896 void LCodeGen::EmitVectorLoadICRegisters(T* instr) { | 2890 void LCodeGen::EmitVectorLoadICRegisters(T* instr) { |
| 2897 DCHECK(FLAG_vector_ics); | 2891 DCHECK(FLAG_vector_ics); |
| 2898 Register vector = ToRegister(instr->temp_vector()); | 2892 Register vector = ToRegister(instr->temp_vector()); |
| 2899 DCHECK(vector.is(VectorLoadICDescriptor::VectorRegister())); | 2893 DCHECK(vector.is(VectorLoadICDescriptor::VectorRegister())); |
| 2900 __ li(vector, instr->hydrogen()->feedback_vector()); | 2894 __ li(vector, instr->hydrogen()->feedback_vector()); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 2930 | 2924 |
| 2931 // If the cell we are storing to contains the hole it could have | 2925 // If the cell we are storing to contains the hole it could have |
| 2932 // been deleted from the property dictionary. In that case, we need | 2926 // been deleted from the property dictionary. In that case, we need |
| 2933 // to update the property details in the property dictionary to mark | 2927 // to update the property details in the property dictionary to mark |
| 2934 // it as no longer deleted. | 2928 // it as no longer deleted. |
| 2935 if (instr->hydrogen()->RequiresHoleCheck()) { | 2929 if (instr->hydrogen()->RequiresHoleCheck()) { |
| 2936 // We use a temp to check the payload. | 2930 // We use a temp to check the payload. |
| 2937 Register payload = ToRegister(instr->temp()); | 2931 Register payload = ToRegister(instr->temp()); |
| 2938 __ lw(payload, FieldMemOperand(cell, Cell::kValueOffset)); | 2932 __ lw(payload, FieldMemOperand(cell, Cell::kValueOffset)); |
| 2939 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | 2933 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
| 2940 DeoptimizeIf(eq, instr->environment(), payload, Operand(at)); | 2934 DeoptimizeIf(eq, instr, payload, Operand(at)); |
| 2941 } | 2935 } |
| 2942 | 2936 |
| 2943 // Store the value. | 2937 // Store the value. |
| 2944 __ sw(value, FieldMemOperand(cell, Cell::kValueOffset)); | 2938 __ sw(value, FieldMemOperand(cell, Cell::kValueOffset)); |
| 2945 // Cells are always rescanned, so no write barrier here. | 2939 // Cells are always rescanned, so no write barrier here. |
| 2946 } | 2940 } |
| 2947 | 2941 |
| 2948 | 2942 |
| 2949 | 2943 |
| 2950 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { | 2944 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { |
| 2951 Register context = ToRegister(instr->context()); | 2945 Register context = ToRegister(instr->context()); |
| 2952 Register result = ToRegister(instr->result()); | 2946 Register result = ToRegister(instr->result()); |
| 2953 | 2947 |
| 2954 __ lw(result, ContextOperand(context, instr->slot_index())); | 2948 __ lw(result, ContextOperand(context, instr->slot_index())); |
| 2955 if (instr->hydrogen()->RequiresHoleCheck()) { | 2949 if (instr->hydrogen()->RequiresHoleCheck()) { |
| 2956 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | 2950 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
| 2957 | 2951 |
| 2958 if (instr->hydrogen()->DeoptimizesOnHole()) { | 2952 if (instr->hydrogen()->DeoptimizesOnHole()) { |
| 2959 DeoptimizeIf(eq, instr->environment(), result, Operand(at)); | 2953 DeoptimizeIf(eq, instr, result, Operand(at)); |
| 2960 } else { | 2954 } else { |
| 2961 Label is_not_hole; | 2955 Label is_not_hole; |
| 2962 __ Branch(&is_not_hole, ne, result, Operand(at)); | 2956 __ Branch(&is_not_hole, ne, result, Operand(at)); |
| 2963 __ LoadRoot(result, Heap::kUndefinedValueRootIndex); | 2957 __ LoadRoot(result, Heap::kUndefinedValueRootIndex); |
| 2964 __ bind(&is_not_hole); | 2958 __ bind(&is_not_hole); |
| 2965 } | 2959 } |
| 2966 } | 2960 } |
| 2967 } | 2961 } |
| 2968 | 2962 |
| 2969 | 2963 |
| 2970 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { | 2964 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { |
| 2971 Register context = ToRegister(instr->context()); | 2965 Register context = ToRegister(instr->context()); |
| 2972 Register value = ToRegister(instr->value()); | 2966 Register value = ToRegister(instr->value()); |
| 2973 Register scratch = scratch0(); | 2967 Register scratch = scratch0(); |
| 2974 MemOperand target = ContextOperand(context, instr->slot_index()); | 2968 MemOperand target = ContextOperand(context, instr->slot_index()); |
| 2975 | 2969 |
| 2976 Label skip_assignment; | 2970 Label skip_assignment; |
| 2977 | 2971 |
| 2978 if (instr->hydrogen()->RequiresHoleCheck()) { | 2972 if (instr->hydrogen()->RequiresHoleCheck()) { |
| 2979 __ lw(scratch, target); | 2973 __ lw(scratch, target); |
| 2980 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | 2974 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
| 2981 | 2975 |
| 2982 if (instr->hydrogen()->DeoptimizesOnHole()) { | 2976 if (instr->hydrogen()->DeoptimizesOnHole()) { |
| 2983 DeoptimizeIf(eq, instr->environment(), scratch, Operand(at)); | 2977 DeoptimizeIf(eq, instr, scratch, Operand(at)); |
| 2984 } else { | 2978 } else { |
| 2985 __ Branch(&skip_assignment, ne, scratch, Operand(at)); | 2979 __ Branch(&skip_assignment, ne, scratch, Operand(at)); |
| 2986 } | 2980 } |
| 2987 } | 2981 } |
| 2988 | 2982 |
| 2989 __ sw(value, target); | 2983 __ sw(value, target); |
| 2990 if (instr->hydrogen()->NeedsWriteBarrier()) { | 2984 if (instr->hydrogen()->NeedsWriteBarrier()) { |
| 2991 SmiCheck check_needed = | 2985 SmiCheck check_needed = |
| 2992 instr->hydrogen()->value()->type().IsHeapObject() | 2986 instr->hydrogen()->value()->type().IsHeapObject() |
| 2993 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; | 2987 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3052 Register scratch = scratch0(); | 3046 Register scratch = scratch0(); |
| 3053 Register function = ToRegister(instr->function()); | 3047 Register function = ToRegister(instr->function()); |
| 3054 Register result = ToRegister(instr->result()); | 3048 Register result = ToRegister(instr->result()); |
| 3055 | 3049 |
| 3056 // Get the prototype or initial map from the function. | 3050 // Get the prototype or initial map from the function. |
| 3057 __ lw(result, | 3051 __ lw(result, |
| 3058 FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); | 3052 FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); |
| 3059 | 3053 |
| 3060 // Check that the function has a prototype or an initial map. | 3054 // Check that the function has a prototype or an initial map. |
| 3061 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | 3055 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
| 3062 DeoptimizeIf(eq, instr->environment(), result, Operand(at)); | 3056 DeoptimizeIf(eq, instr, result, Operand(at)); |
| 3063 | 3057 |
| 3064 // If the function does not have an initial map, we're done. | 3058 // If the function does not have an initial map, we're done. |
| 3065 Label done; | 3059 Label done; |
| 3066 __ GetObjectType(result, scratch, scratch); | 3060 __ GetObjectType(result, scratch, scratch); |
| 3067 __ Branch(&done, ne, scratch, Operand(MAP_TYPE)); | 3061 __ Branch(&done, ne, scratch, Operand(MAP_TYPE)); |
| 3068 | 3062 |
| 3069 // Get the prototype from the initial map. | 3063 // Get the prototype from the initial map. |
| 3070 __ lw(result, FieldMemOperand(result, Map::kPrototypeOffset)); | 3064 __ lw(result, FieldMemOperand(result, Map::kPrototypeOffset)); |
| 3071 | 3065 |
| 3072 // All done. | 3066 // All done. |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3188 __ lhu(result, mem_operand); | 3182 __ lhu(result, mem_operand); |
| 3189 break; | 3183 break; |
| 3190 case EXTERNAL_INT32_ELEMENTS: | 3184 case EXTERNAL_INT32_ELEMENTS: |
| 3191 case INT32_ELEMENTS: | 3185 case INT32_ELEMENTS: |
| 3192 __ lw(result, mem_operand); | 3186 __ lw(result, mem_operand); |
| 3193 break; | 3187 break; |
| 3194 case EXTERNAL_UINT32_ELEMENTS: | 3188 case EXTERNAL_UINT32_ELEMENTS: |
| 3195 case UINT32_ELEMENTS: | 3189 case UINT32_ELEMENTS: |
| 3196 __ lw(result, mem_operand); | 3190 __ lw(result, mem_operand); |
| 3197 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) { | 3191 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) { |
| 3198 DeoptimizeIf(Ugreater_equal, instr->environment(), | 3192 DeoptimizeIf(Ugreater_equal, instr, result, Operand(0x80000000)); |
| 3199 result, Operand(0x80000000)); | |
| 3200 } | 3193 } |
| 3201 break; | 3194 break; |
| 3202 case FLOAT32_ELEMENTS: | 3195 case FLOAT32_ELEMENTS: |
| 3203 case FLOAT64_ELEMENTS: | 3196 case FLOAT64_ELEMENTS: |
| 3204 case EXTERNAL_FLOAT32_ELEMENTS: | 3197 case EXTERNAL_FLOAT32_ELEMENTS: |
| 3205 case EXTERNAL_FLOAT64_ELEMENTS: | 3198 case EXTERNAL_FLOAT64_ELEMENTS: |
| 3206 case FAST_DOUBLE_ELEMENTS: | 3199 case FAST_DOUBLE_ELEMENTS: |
| 3207 case FAST_ELEMENTS: | 3200 case FAST_ELEMENTS: |
| 3208 case FAST_SMI_ELEMENTS: | 3201 case FAST_SMI_ELEMENTS: |
| 3209 case FAST_HOLEY_DOUBLE_ELEMENTS: | 3202 case FAST_HOLEY_DOUBLE_ELEMENTS: |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3242 int shift_size = (instr->hydrogen()->key()->representation().IsSmi()) | 3235 int shift_size = (instr->hydrogen()->key()->representation().IsSmi()) |
| 3243 ? (element_size_shift - kSmiTagSize) : element_size_shift; | 3236 ? (element_size_shift - kSmiTagSize) : element_size_shift; |
| 3244 __ sll(at, key, shift_size); | 3237 __ sll(at, key, shift_size); |
| 3245 __ Addu(scratch, scratch, at); | 3238 __ Addu(scratch, scratch, at); |
| 3246 } | 3239 } |
| 3247 | 3240 |
| 3248 __ ldc1(result, MemOperand(scratch)); | 3241 __ ldc1(result, MemOperand(scratch)); |
| 3249 | 3242 |
| 3250 if (instr->hydrogen()->RequiresHoleCheck()) { | 3243 if (instr->hydrogen()->RequiresHoleCheck()) { |
| 3251 __ lw(scratch, MemOperand(scratch, kHoleNanUpper32Offset)); | 3244 __ lw(scratch, MemOperand(scratch, kHoleNanUpper32Offset)); |
| 3252 DeoptimizeIf(eq, instr->environment(), scratch, Operand(kHoleNanUpper32)); | 3245 DeoptimizeIf(eq, instr, scratch, Operand(kHoleNanUpper32)); |
| 3253 } | 3246 } |
| 3254 } | 3247 } |
| 3255 | 3248 |
| 3256 | 3249 |
| 3257 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { | 3250 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { |
| 3258 Register elements = ToRegister(instr->elements()); | 3251 Register elements = ToRegister(instr->elements()); |
| 3259 Register result = ToRegister(instr->result()); | 3252 Register result = ToRegister(instr->result()); |
| 3260 Register scratch = scratch0(); | 3253 Register scratch = scratch0(); |
| 3261 Register store_base = scratch; | 3254 Register store_base = scratch; |
| 3262 int offset = instr->base_offset(); | 3255 int offset = instr->base_offset(); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 3278 __ sll(scratch, key, kPointerSizeLog2); | 3271 __ sll(scratch, key, kPointerSizeLog2); |
| 3279 __ addu(scratch, elements, scratch); | 3272 __ addu(scratch, elements, scratch); |
| 3280 } | 3273 } |
| 3281 } | 3274 } |
| 3282 __ lw(result, MemOperand(store_base, offset)); | 3275 __ lw(result, MemOperand(store_base, offset)); |
| 3283 | 3276 |
| 3284 // Check for the hole value. | 3277 // Check for the hole value. |
| 3285 if (instr->hydrogen()->RequiresHoleCheck()) { | 3278 if (instr->hydrogen()->RequiresHoleCheck()) { |
| 3286 if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) { | 3279 if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) { |
| 3287 __ SmiTst(result, scratch); | 3280 __ SmiTst(result, scratch); |
| 3288 DeoptimizeIf(ne, instr->environment(), scratch, Operand(zero_reg)); | 3281 DeoptimizeIf(ne, instr, scratch, Operand(zero_reg)); |
| 3289 } else { | 3282 } else { |
| 3290 __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex); | 3283 __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex); |
| 3291 DeoptimizeIf(eq, instr->environment(), result, Operand(scratch)); | 3284 DeoptimizeIf(eq, instr, result, Operand(scratch)); |
| 3292 } | 3285 } |
| 3293 } | 3286 } |
| 3294 } | 3287 } |
| 3295 | 3288 |
| 3296 | 3289 |
| 3297 void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) { | 3290 void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) { |
| 3298 if (instr->is_typed_elements()) { | 3291 if (instr->is_typed_elements()) { |
| 3299 DoLoadKeyedExternalArray(instr); | 3292 DoLoadKeyedExternalArray(instr); |
| 3300 } else if (instr->hydrogen()->representation().IsDouble()) { | 3293 } else if (instr->hydrogen()->representation().IsDouble()) { |
| 3301 DoLoadKeyedFixedDoubleArray(instr); | 3294 DoLoadKeyedFixedDoubleArray(instr); |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3427 } | 3420 } |
| 3428 | 3421 |
| 3429 // Normal function. Replace undefined or null with global receiver. | 3422 // Normal function. Replace undefined or null with global receiver. |
| 3430 __ LoadRoot(scratch, Heap::kNullValueRootIndex); | 3423 __ LoadRoot(scratch, Heap::kNullValueRootIndex); |
| 3431 __ Branch(&global_object, eq, receiver, Operand(scratch)); | 3424 __ Branch(&global_object, eq, receiver, Operand(scratch)); |
| 3432 __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex); | 3425 __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex); |
| 3433 __ Branch(&global_object, eq, receiver, Operand(scratch)); | 3426 __ Branch(&global_object, eq, receiver, Operand(scratch)); |
| 3434 | 3427 |
| 3435 // Deoptimize if the receiver is not a JS object. | 3428 // Deoptimize if the receiver is not a JS object. |
| 3436 __ SmiTst(receiver, scratch); | 3429 __ SmiTst(receiver, scratch); |
| 3437 DeoptimizeIf(eq, instr->environment(), scratch, Operand(zero_reg)); | 3430 DeoptimizeIf(eq, instr, scratch, Operand(zero_reg)); |
| 3438 | 3431 |
| 3439 __ GetObjectType(receiver, scratch, scratch); | 3432 __ GetObjectType(receiver, scratch, scratch); |
| 3440 DeoptimizeIf(lt, instr->environment(), | 3433 DeoptimizeIf(lt, instr, scratch, Operand(FIRST_SPEC_OBJECT_TYPE)); |
| 3441 scratch, Operand(FIRST_SPEC_OBJECT_TYPE)); | |
| 3442 | 3434 |
| 3443 __ Branch(&result_in_receiver); | 3435 __ Branch(&result_in_receiver); |
| 3444 __ bind(&global_object); | 3436 __ bind(&global_object); |
| 3445 __ lw(result, FieldMemOperand(function, JSFunction::kContextOffset)); | 3437 __ lw(result, FieldMemOperand(function, JSFunction::kContextOffset)); |
| 3446 __ lw(result, | 3438 __ lw(result, |
| 3447 ContextOperand(result, Context::GLOBAL_OBJECT_INDEX)); | 3439 ContextOperand(result, Context::GLOBAL_OBJECT_INDEX)); |
| 3448 __ lw(result, | 3440 __ lw(result, |
| 3449 FieldMemOperand(result, GlobalObject::kGlobalProxyOffset)); | 3441 FieldMemOperand(result, GlobalObject::kGlobalProxyOffset)); |
| 3450 | 3442 |
| 3451 if (result.is(receiver)) { | 3443 if (result.is(receiver)) { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 3466 Register length = ToRegister(instr->length()); | 3458 Register length = ToRegister(instr->length()); |
| 3467 Register elements = ToRegister(instr->elements()); | 3459 Register elements = ToRegister(instr->elements()); |
| 3468 Register scratch = scratch0(); | 3460 Register scratch = scratch0(); |
| 3469 DCHECK(receiver.is(a0)); // Used for parameter count. | 3461 DCHECK(receiver.is(a0)); // Used for parameter count. |
| 3470 DCHECK(function.is(a1)); // Required by InvokeFunction. | 3462 DCHECK(function.is(a1)); // Required by InvokeFunction. |
| 3471 DCHECK(ToRegister(instr->result()).is(v0)); | 3463 DCHECK(ToRegister(instr->result()).is(v0)); |
| 3472 | 3464 |
| 3473 // Copy the arguments to this function possibly from the | 3465 // Copy the arguments to this function possibly from the |
| 3474 // adaptor frame below it. | 3466 // adaptor frame below it. |
| 3475 const uint32_t kArgumentsLimit = 1 * KB; | 3467 const uint32_t kArgumentsLimit = 1 * KB; |
| 3476 DeoptimizeIf(hi, instr->environment(), length, Operand(kArgumentsLimit)); | 3468 DeoptimizeIf(hi, instr, length, Operand(kArgumentsLimit)); |
| 3477 | 3469 |
| 3478 // Push the receiver and use the register to keep the original | 3470 // Push the receiver and use the register to keep the original |
| 3479 // number of arguments. | 3471 // number of arguments. |
| 3480 __ push(receiver); | 3472 __ push(receiver); |
| 3481 __ Move(receiver, length); | 3473 __ Move(receiver, length); |
| 3482 // The arguments are at a one pointer size offset from elements. | 3474 // The arguments are at a one pointer size offset from elements. |
| 3483 __ Addu(elements, elements, Operand(1 * kPointerSize)); | 3475 __ Addu(elements, elements, Operand(1 * kPointerSize)); |
| 3484 | 3476 |
| 3485 // Loop through the arguments pushing them onto the execution | 3477 // Loop through the arguments pushing them onto the execution |
| 3486 // stack. | 3478 // stack. |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3596 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { | 3588 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { |
| 3597 DCHECK(instr->context() != NULL); | 3589 DCHECK(instr->context() != NULL); |
| 3598 DCHECK(ToRegister(instr->context()).is(cp)); | 3590 DCHECK(ToRegister(instr->context()).is(cp)); |
| 3599 Register input = ToRegister(instr->value()); | 3591 Register input = ToRegister(instr->value()); |
| 3600 Register result = ToRegister(instr->result()); | 3592 Register result = ToRegister(instr->result()); |
| 3601 Register scratch = scratch0(); | 3593 Register scratch = scratch0(); |
| 3602 | 3594 |
| 3603 // Deoptimize if not a heap number. | 3595 // Deoptimize if not a heap number. |
| 3604 __ lw(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); | 3596 __ lw(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); |
| 3605 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); | 3597 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); |
| 3606 DeoptimizeIf(ne, instr->environment(), scratch, Operand(at)); | 3598 DeoptimizeIf(ne, instr, scratch, Operand(at)); |
| 3607 | 3599 |
| 3608 Label done; | 3600 Label done; |
| 3609 Register exponent = scratch0(); | 3601 Register exponent = scratch0(); |
| 3610 scratch = no_reg; | 3602 scratch = no_reg; |
| 3611 __ lw(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset)); | 3603 __ lw(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset)); |
| 3612 // Check the sign of the argument. If the argument is positive, just | 3604 // Check the sign of the argument. If the argument is positive, just |
| 3613 // return it. | 3605 // return it. |
| 3614 __ Move(result, input); | 3606 __ Move(result, input); |
| 3615 __ And(at, exponent, Operand(HeapNumber::kSignMask)); | 3607 __ And(at, exponent, Operand(HeapNumber::kSignMask)); |
| 3616 __ Branch(&done, eq, at, Operand(zero_reg)); | 3608 __ Branch(&done, eq, at, Operand(zero_reg)); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3663 | 3655 |
| 3664 void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) { | 3656 void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) { |
| 3665 Register input = ToRegister(instr->value()); | 3657 Register input = ToRegister(instr->value()); |
| 3666 Register result = ToRegister(instr->result()); | 3658 Register result = ToRegister(instr->result()); |
| 3667 Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_); | 3659 Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_); |
| 3668 Label done; | 3660 Label done; |
| 3669 __ Branch(USE_DELAY_SLOT, &done, ge, input, Operand(zero_reg)); | 3661 __ Branch(USE_DELAY_SLOT, &done, ge, input, Operand(zero_reg)); |
| 3670 __ mov(result, input); | 3662 __ mov(result, input); |
| 3671 __ subu(result, zero_reg, input); | 3663 __ subu(result, zero_reg, input); |
| 3672 // Overflow if result is still negative, i.e. 0x80000000. | 3664 // Overflow if result is still negative, i.e. 0x80000000. |
| 3673 DeoptimizeIf(lt, instr->environment(), result, Operand(zero_reg)); | 3665 DeoptimizeIf(lt, instr, result, Operand(zero_reg)); |
| 3674 __ bind(&done); | 3666 __ bind(&done); |
| 3675 } | 3667 } |
| 3676 | 3668 |
| 3677 | 3669 |
| 3678 void LCodeGen::DoMathAbs(LMathAbs* instr) { | 3670 void LCodeGen::DoMathAbs(LMathAbs* instr) { |
| 3679 // Class for deferred case. | 3671 // Class for deferred case. |
| 3680 class DeferredMathAbsTaggedHeapNumber FINAL : public LDeferredCode { | 3672 class DeferredMathAbsTaggedHeapNumber FINAL : public LDeferredCode { |
| 3681 public: | 3673 public: |
| 3682 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, LMathAbs* instr) | 3674 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, LMathAbs* instr) |
| 3683 : LDeferredCode(codegen), instr_(instr) { } | 3675 : LDeferredCode(codegen), instr_(instr) { } |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3717 Register except_flag = ToRegister(instr->temp()); | 3709 Register except_flag = ToRegister(instr->temp()); |
| 3718 | 3710 |
| 3719 __ EmitFPUTruncate(kRoundToMinusInf, | 3711 __ EmitFPUTruncate(kRoundToMinusInf, |
| 3720 result, | 3712 result, |
| 3721 input, | 3713 input, |
| 3722 scratch1, | 3714 scratch1, |
| 3723 double_scratch0(), | 3715 double_scratch0(), |
| 3724 except_flag); | 3716 except_flag); |
| 3725 | 3717 |
| 3726 // Deopt if the operation did not succeed. | 3718 // Deopt if the operation did not succeed. |
| 3727 DeoptimizeIf(ne, instr->environment(), except_flag, Operand(zero_reg)); | 3719 DeoptimizeIf(ne, instr, except_flag, Operand(zero_reg)); |
| 3728 | 3720 |
| 3729 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3721 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 3730 // Test for -0. | 3722 // Test for -0. |
| 3731 Label done; | 3723 Label done; |
| 3732 __ Branch(&done, ne, result, Operand(zero_reg)); | 3724 __ Branch(&done, ne, result, Operand(zero_reg)); |
| 3733 __ Mfhc1(scratch1, input); | 3725 __ Mfhc1(scratch1, input); |
| 3734 __ And(scratch1, scratch1, Operand(HeapNumber::kSignMask)); | 3726 __ And(scratch1, scratch1, Operand(HeapNumber::kSignMask)); |
| 3735 DeoptimizeIf(ne, instr->environment(), scratch1, Operand(zero_reg)); | 3727 DeoptimizeIf(ne, instr, scratch1, Operand(zero_reg)); |
| 3736 __ bind(&done); | 3728 __ bind(&done); |
| 3737 } | 3729 } |
| 3738 } | 3730 } |
| 3739 | 3731 |
| 3740 | 3732 |
| 3741 void LCodeGen::DoMathRound(LMathRound* instr) { | 3733 void LCodeGen::DoMathRound(LMathRound* instr) { |
| 3742 DoubleRegister input = ToDoubleRegister(instr->value()); | 3734 DoubleRegister input = ToDoubleRegister(instr->value()); |
| 3743 Register result = ToRegister(instr->result()); | 3735 Register result = ToRegister(instr->result()); |
| 3744 DoubleRegister double_scratch1 = ToDoubleRegister(instr->temp()); | 3736 DoubleRegister double_scratch1 = ToDoubleRegister(instr->temp()); |
| 3745 Register scratch = scratch0(); | 3737 Register scratch = scratch0(); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 3758 __ mov(result, zero_reg); | 3750 __ mov(result, zero_reg); |
| 3759 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3751 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 3760 __ Branch(&check_sign_on_zero); | 3752 __ Branch(&check_sign_on_zero); |
| 3761 } else { | 3753 } else { |
| 3762 __ Branch(&done); | 3754 __ Branch(&done); |
| 3763 } | 3755 } |
| 3764 __ bind(&skip1); | 3756 __ bind(&skip1); |
| 3765 | 3757 |
| 3766 // The following conversion will not work with numbers | 3758 // The following conversion will not work with numbers |
| 3767 // outside of ]-2^32, 2^32[. | 3759 // outside of ]-2^32, 2^32[. |
| 3768 DeoptimizeIf(ge, instr->environment(), scratch, | 3760 DeoptimizeIf(ge, instr, scratch, Operand(HeapNumber::kExponentBias + 32)); |
| 3769 Operand(HeapNumber::kExponentBias + 32)); | |
| 3770 | 3761 |
| 3771 // Save the original sign for later comparison. | 3762 // Save the original sign for later comparison. |
| 3772 __ And(scratch, result, Operand(HeapNumber::kSignMask)); | 3763 __ And(scratch, result, Operand(HeapNumber::kSignMask)); |
| 3773 | 3764 |
| 3774 __ Move(double_scratch0(), 0.5); | 3765 __ Move(double_scratch0(), 0.5); |
| 3775 __ add_d(double_scratch0(), input, double_scratch0()); | 3766 __ add_d(double_scratch0(), input, double_scratch0()); |
| 3776 | 3767 |
| 3777 // Check sign of the result: if the sign changed, the input | 3768 // Check sign of the result: if the sign changed, the input |
| 3778 // value was in ]0.5, 0[ and the result should be -0. | 3769 // value was in ]0.5, 0[ and the result should be -0. |
| 3779 __ Mfhc1(result, double_scratch0()); | 3770 __ Mfhc1(result, double_scratch0()); |
| 3780 __ Xor(result, result, Operand(scratch)); | 3771 __ Xor(result, result, Operand(scratch)); |
| 3781 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3772 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 3782 // ARM uses 'mi' here, which is 'lt' | 3773 // ARM uses 'mi' here, which is 'lt' |
| 3783 DeoptimizeIf(lt, instr->environment(), result, | 3774 DeoptimizeIf(lt, instr, result, Operand(zero_reg)); |
| 3784 Operand(zero_reg)); | |
| 3785 } else { | 3775 } else { |
| 3786 Label skip2; | 3776 Label skip2; |
| 3787 // ARM uses 'mi' here, which is 'lt' | 3777 // ARM uses 'mi' here, which is 'lt' |
| 3788 // Negating it results in 'ge' | 3778 // Negating it results in 'ge' |
| 3789 __ Branch(&skip2, ge, result, Operand(zero_reg)); | 3779 __ Branch(&skip2, ge, result, Operand(zero_reg)); |
| 3790 __ mov(result, zero_reg); | 3780 __ mov(result, zero_reg); |
| 3791 __ Branch(&done); | 3781 __ Branch(&done); |
| 3792 __ bind(&skip2); | 3782 __ bind(&skip2); |
| 3793 } | 3783 } |
| 3794 | 3784 |
| 3795 Register except_flag = scratch; | 3785 Register except_flag = scratch; |
| 3796 __ EmitFPUTruncate(kRoundToMinusInf, | 3786 __ EmitFPUTruncate(kRoundToMinusInf, |
| 3797 result, | 3787 result, |
| 3798 double_scratch0(), | 3788 double_scratch0(), |
| 3799 at, | 3789 at, |
| 3800 double_scratch1, | 3790 double_scratch1, |
| 3801 except_flag); | 3791 except_flag); |
| 3802 | 3792 |
| 3803 DeoptimizeIf(ne, instr->environment(), except_flag, Operand(zero_reg)); | 3793 DeoptimizeIf(ne, instr, except_flag, Operand(zero_reg)); |
| 3804 | 3794 |
| 3805 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3795 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 3806 // Test for -0. | 3796 // Test for -0. |
| 3807 __ Branch(&done, ne, result, Operand(zero_reg)); | 3797 __ Branch(&done, ne, result, Operand(zero_reg)); |
| 3808 __ bind(&check_sign_on_zero); | 3798 __ bind(&check_sign_on_zero); |
| 3809 __ Mfhc1(scratch, input); | 3799 __ Mfhc1(scratch, input); |
| 3810 __ And(scratch, scratch, Operand(HeapNumber::kSignMask)); | 3800 __ And(scratch, scratch, Operand(HeapNumber::kSignMask)); |
| 3811 DeoptimizeIf(ne, instr->environment(), scratch, Operand(zero_reg)); | 3801 DeoptimizeIf(ne, instr, scratch, Operand(zero_reg)); |
| 3812 } | 3802 } |
| 3813 __ bind(&done); | 3803 __ bind(&done); |
| 3814 } | 3804 } |
| 3815 | 3805 |
| 3816 | 3806 |
| 3817 void LCodeGen::DoMathFround(LMathFround* instr) { | 3807 void LCodeGen::DoMathFround(LMathFround* instr) { |
| 3818 DoubleRegister input = ToDoubleRegister(instr->value()); | 3808 DoubleRegister input = ToDoubleRegister(instr->value()); |
| 3819 DoubleRegister result = ToDoubleRegister(instr->result()); | 3809 DoubleRegister result = ToDoubleRegister(instr->result()); |
| 3820 __ cvt_s_d(result.low(), input); | 3810 __ cvt_s_d(result.low(), input); |
| 3821 __ cvt_d_s(result, result.low()); | 3811 __ cvt_d_s(result, result.low()); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3867 | 3857 |
| 3868 if (exponent_type.IsSmi()) { | 3858 if (exponent_type.IsSmi()) { |
| 3869 MathPowStub stub(isolate(), MathPowStub::TAGGED); | 3859 MathPowStub stub(isolate(), MathPowStub::TAGGED); |
| 3870 __ CallStub(&stub); | 3860 __ CallStub(&stub); |
| 3871 } else if (exponent_type.IsTagged()) { | 3861 } else if (exponent_type.IsTagged()) { |
| 3872 Label no_deopt; | 3862 Label no_deopt; |
| 3873 __ JumpIfSmi(tagged_exponent, &no_deopt); | 3863 __ JumpIfSmi(tagged_exponent, &no_deopt); |
| 3874 DCHECK(!t3.is(tagged_exponent)); | 3864 DCHECK(!t3.is(tagged_exponent)); |
| 3875 __ lw(t3, FieldMemOperand(tagged_exponent, HeapObject::kMapOffset)); | 3865 __ lw(t3, FieldMemOperand(tagged_exponent, HeapObject::kMapOffset)); |
| 3876 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); | 3866 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); |
| 3877 DeoptimizeIf(ne, instr->environment(), t3, Operand(at)); | 3867 DeoptimizeIf(ne, instr, t3, Operand(at)); |
| 3878 __ bind(&no_deopt); | 3868 __ bind(&no_deopt); |
| 3879 MathPowStub stub(isolate(), MathPowStub::TAGGED); | 3869 MathPowStub stub(isolate(), MathPowStub::TAGGED); |
| 3880 __ CallStub(&stub); | 3870 __ CallStub(&stub); |
| 3881 } else if (exponent_type.IsInteger32()) { | 3871 } else if (exponent_type.IsInteger32()) { |
| 3882 MathPowStub stub(isolate(), MathPowStub::INTEGER); | 3872 MathPowStub stub(isolate(), MathPowStub::INTEGER); |
| 3883 __ CallStub(&stub); | 3873 __ CallStub(&stub); |
| 3884 } else { | 3874 } else { |
| 3885 DCHECK(exponent_type.IsDouble()); | 3875 DCHECK(exponent_type.IsDouble()); |
| 3886 MathPowStub stub(isolate(), MathPowStub::DOUBLE); | 3876 MathPowStub stub(isolate(), MathPowStub::DOUBLE); |
| 3887 __ CallStub(&stub); | 3877 __ CallStub(&stub); |
| (...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4210 } else { | 4200 } else { |
| 4211 reg = ToRegister(instr->index()); | 4201 reg = ToRegister(instr->index()); |
| 4212 operand = ToOperand(instr->length()); | 4202 operand = ToOperand(instr->length()); |
| 4213 } | 4203 } |
| 4214 if (FLAG_debug_code && instr->hydrogen()->skip_check()) { | 4204 if (FLAG_debug_code && instr->hydrogen()->skip_check()) { |
| 4215 Label done; | 4205 Label done; |
| 4216 __ Branch(&done, NegateCondition(cc), reg, operand); | 4206 __ Branch(&done, NegateCondition(cc), reg, operand); |
| 4217 __ stop("eliminated bounds check failed"); | 4207 __ stop("eliminated bounds check failed"); |
| 4218 __ bind(&done); | 4208 __ bind(&done); |
| 4219 } else { | 4209 } else { |
| 4220 DeoptimizeIf(cc, instr->environment(), reg, operand); | 4210 DeoptimizeIf(cc, instr, reg, operand); |
| 4221 } | 4211 } |
| 4222 } | 4212 } |
| 4223 | 4213 |
| 4224 | 4214 |
| 4225 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) { | 4215 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) { |
| 4226 Register external_pointer = ToRegister(instr->elements()); | 4216 Register external_pointer = ToRegister(instr->elements()); |
| 4227 Register key = no_reg; | 4217 Register key = no_reg; |
| 4228 ElementsKind elements_kind = instr->elements_kind(); | 4218 ElementsKind elements_kind = instr->elements_kind(); |
| 4229 bool key_is_constant = instr->key()->IsConstantOperand(); | 4219 bool key_is_constant = instr->key()->IsConstantOperand(); |
| 4230 int constant_key = 0; | 4220 int constant_key = 0; |
| (...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4468 __ bind(¬_applicable); | 4458 __ bind(¬_applicable); |
| 4469 } | 4459 } |
| 4470 | 4460 |
| 4471 | 4461 |
| 4472 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) { | 4462 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) { |
| 4473 Register object = ToRegister(instr->object()); | 4463 Register object = ToRegister(instr->object()); |
| 4474 Register temp = ToRegister(instr->temp()); | 4464 Register temp = ToRegister(instr->temp()); |
| 4475 Label no_memento_found; | 4465 Label no_memento_found; |
| 4476 __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found, | 4466 __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found, |
| 4477 ne, &no_memento_found); | 4467 ne, &no_memento_found); |
| 4478 DeoptimizeIf(al, instr->environment()); | 4468 DeoptimizeIf(al, instr); |
| 4479 __ bind(&no_memento_found); | 4469 __ bind(&no_memento_found); |
| 4480 } | 4470 } |
| 4481 | 4471 |
| 4482 | 4472 |
| 4483 void LCodeGen::DoStringAdd(LStringAdd* instr) { | 4473 void LCodeGen::DoStringAdd(LStringAdd* instr) { |
| 4484 DCHECK(ToRegister(instr->context()).is(cp)); | 4474 DCHECK(ToRegister(instr->context()).is(cp)); |
| 4485 DCHECK(ToRegister(instr->left()).is(a1)); | 4475 DCHECK(ToRegister(instr->left()).is(a1)); |
| 4486 DCHECK(ToRegister(instr->right()).is(a0)); | 4476 DCHECK(ToRegister(instr->right()).is(a0)); |
| 4487 StringAddStub stub(isolate(), | 4477 StringAddStub stub(isolate(), |
| 4488 instr->hydrogen()->flags(), | 4478 instr->hydrogen()->flags(), |
| (...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4803 } | 4793 } |
| 4804 | 4794 |
| 4805 | 4795 |
| 4806 void LCodeGen::DoSmiTag(LSmiTag* instr) { | 4796 void LCodeGen::DoSmiTag(LSmiTag* instr) { |
| 4807 HChange* hchange = instr->hydrogen(); | 4797 HChange* hchange = instr->hydrogen(); |
| 4808 Register input = ToRegister(instr->value()); | 4798 Register input = ToRegister(instr->value()); |
| 4809 Register output = ToRegister(instr->result()); | 4799 Register output = ToRegister(instr->result()); |
| 4810 if (hchange->CheckFlag(HValue::kCanOverflow) && | 4800 if (hchange->CheckFlag(HValue::kCanOverflow) && |
| 4811 hchange->value()->CheckFlag(HValue::kUint32)) { | 4801 hchange->value()->CheckFlag(HValue::kUint32)) { |
| 4812 __ And(at, input, Operand(0xc0000000)); | 4802 __ And(at, input, Operand(0xc0000000)); |
| 4813 DeoptimizeIf(ne, instr->environment(), at, Operand(zero_reg)); | 4803 DeoptimizeIf(ne, instr, at, Operand(zero_reg)); |
| 4814 } | 4804 } |
| 4815 if (hchange->CheckFlag(HValue::kCanOverflow) && | 4805 if (hchange->CheckFlag(HValue::kCanOverflow) && |
| 4816 !hchange->value()->CheckFlag(HValue::kUint32)) { | 4806 !hchange->value()->CheckFlag(HValue::kUint32)) { |
| 4817 __ SmiTagCheckOverflow(output, input, at); | 4807 __ SmiTagCheckOverflow(output, input, at); |
| 4818 DeoptimizeIf(lt, instr->environment(), at, Operand(zero_reg)); | 4808 DeoptimizeIf(lt, instr, at, Operand(zero_reg)); |
| 4819 } else { | 4809 } else { |
| 4820 __ SmiTag(output, input); | 4810 __ SmiTag(output, input); |
| 4821 } | 4811 } |
| 4822 } | 4812 } |
| 4823 | 4813 |
| 4824 | 4814 |
| 4825 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { | 4815 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { |
| 4826 Register scratch = scratch0(); | 4816 Register scratch = scratch0(); |
| 4827 Register input = ToRegister(instr->value()); | 4817 Register input = ToRegister(instr->value()); |
| 4828 Register result = ToRegister(instr->result()); | 4818 Register result = ToRegister(instr->result()); |
| 4829 if (instr->needs_check()) { | 4819 if (instr->needs_check()) { |
| 4830 STATIC_ASSERT(kHeapObjectTag == 1); | 4820 STATIC_ASSERT(kHeapObjectTag == 1); |
| 4831 // If the input is a HeapObject, value of scratch won't be zero. | 4821 // If the input is a HeapObject, value of scratch won't be zero. |
| 4832 __ And(scratch, input, Operand(kHeapObjectTag)); | 4822 __ And(scratch, input, Operand(kHeapObjectTag)); |
| 4833 __ SmiUntag(result, input); | 4823 __ SmiUntag(result, input); |
| 4834 DeoptimizeIf(ne, instr->environment(), scratch, Operand(zero_reg)); | 4824 DeoptimizeIf(ne, instr, scratch, Operand(zero_reg)); |
| 4835 } else { | 4825 } else { |
| 4836 __ SmiUntag(result, input); | 4826 __ SmiUntag(result, input); |
| 4837 } | 4827 } |
| 4838 } | 4828 } |
| 4839 | 4829 |
| 4840 | 4830 |
| 4841 void LCodeGen::EmitNumberUntagD(Register input_reg, | 4831 void LCodeGen::EmitNumberUntagD(LNumberUntagD* instr, Register input_reg, |
| 4842 DoubleRegister result_reg, | 4832 DoubleRegister result_reg, |
| 4843 bool can_convert_undefined_to_nan, | |
| 4844 bool deoptimize_on_minus_zero, | |
| 4845 LEnvironment* env, | |
| 4846 NumberUntagDMode mode) { | 4833 NumberUntagDMode mode) { |
| 4834 bool can_convert_undefined_to_nan = |
| 4835 instr->hydrogen()->can_convert_undefined_to_nan(); |
| 4836 bool deoptimize_on_minus_zero = instr->hydrogen()->deoptimize_on_minus_zero(); |
| 4837 |
| 4847 Register scratch = scratch0(); | 4838 Register scratch = scratch0(); |
| 4848 Label convert, load_smi, done; | 4839 Label convert, load_smi, done; |
| 4849 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) { | 4840 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) { |
| 4850 // Smi check. | 4841 // Smi check. |
| 4851 __ UntagAndJumpIfSmi(scratch, input_reg, &load_smi); | 4842 __ UntagAndJumpIfSmi(scratch, input_reg, &load_smi); |
| 4852 // Heap number map check. | 4843 // Heap number map check. |
| 4853 __ lw(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); | 4844 __ lw(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); |
| 4854 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); | 4845 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); |
| 4855 if (can_convert_undefined_to_nan) { | 4846 if (can_convert_undefined_to_nan) { |
| 4856 __ Branch(&convert, ne, scratch, Operand(at)); | 4847 __ Branch(&convert, ne, scratch, Operand(at)); |
| 4857 } else { | 4848 } else { |
| 4858 DeoptimizeIf(ne, env, scratch, Operand(at)); | 4849 DeoptimizeIf(ne, instr, scratch, Operand(at)); |
| 4859 } | 4850 } |
| 4860 // Load heap number. | 4851 // Load heap number. |
| 4861 __ ldc1(result_reg, FieldMemOperand(input_reg, HeapNumber::kValueOffset)); | 4852 __ ldc1(result_reg, FieldMemOperand(input_reg, HeapNumber::kValueOffset)); |
| 4862 if (deoptimize_on_minus_zero) { | 4853 if (deoptimize_on_minus_zero) { |
| 4863 __ mfc1(at, result_reg.low()); | 4854 __ mfc1(at, result_reg.low()); |
| 4864 __ Branch(&done, ne, at, Operand(zero_reg)); | 4855 __ Branch(&done, ne, at, Operand(zero_reg)); |
| 4865 __ Mfhc1(scratch, result_reg); | 4856 __ Mfhc1(scratch, result_reg); |
| 4866 DeoptimizeIf(eq, env, scratch, Operand(HeapNumber::kSignMask)); | 4857 DeoptimizeIf(eq, instr, scratch, Operand(HeapNumber::kSignMask)); |
| 4867 } | 4858 } |
| 4868 __ Branch(&done); | 4859 __ Branch(&done); |
| 4869 if (can_convert_undefined_to_nan) { | 4860 if (can_convert_undefined_to_nan) { |
| 4870 __ bind(&convert); | 4861 __ bind(&convert); |
| 4871 // Convert undefined (and hole) to NaN. | 4862 // Convert undefined (and hole) to NaN. |
| 4872 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); | 4863 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); |
| 4873 DeoptimizeIf(ne, env, input_reg, Operand(at)); | 4864 DeoptimizeIf(ne, instr, input_reg, Operand(at)); |
| 4874 __ LoadRoot(scratch, Heap::kNanValueRootIndex); | 4865 __ LoadRoot(scratch, Heap::kNanValueRootIndex); |
| 4875 __ ldc1(result_reg, FieldMemOperand(scratch, HeapNumber::kValueOffset)); | 4866 __ ldc1(result_reg, FieldMemOperand(scratch, HeapNumber::kValueOffset)); |
| 4876 __ Branch(&done); | 4867 __ Branch(&done); |
| 4877 } | 4868 } |
| 4878 } else { | 4869 } else { |
| 4879 __ SmiUntag(scratch, input_reg); | 4870 __ SmiUntag(scratch, input_reg); |
| 4880 DCHECK(mode == NUMBER_CANDIDATE_IS_SMI); | 4871 DCHECK(mode == NUMBER_CANDIDATE_IS_SMI); |
| 4881 } | 4872 } |
| 4882 // Smi to double register conversion | 4873 // Smi to double register conversion |
| 4883 __ bind(&load_smi); | 4874 __ bind(&load_smi); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4928 | 4919 |
| 4929 __ bind(&check_bools); | 4920 __ bind(&check_bools); |
| 4930 __ LoadRoot(at, Heap::kTrueValueRootIndex); | 4921 __ LoadRoot(at, Heap::kTrueValueRootIndex); |
| 4931 __ Branch(&check_false, ne, scratch2, Operand(at)); | 4922 __ Branch(&check_false, ne, scratch2, Operand(at)); |
| 4932 __ Branch(USE_DELAY_SLOT, &done); | 4923 __ Branch(USE_DELAY_SLOT, &done); |
| 4933 __ li(input_reg, Operand(1)); // In delay slot. | 4924 __ li(input_reg, Operand(1)); // In delay slot. |
| 4934 | 4925 |
| 4935 __ bind(&check_false); | 4926 __ bind(&check_false); |
| 4936 __ LoadRoot(at, Heap::kFalseValueRootIndex); | 4927 __ LoadRoot(at, Heap::kFalseValueRootIndex); |
| 4937 __ RecordComment("Deferred TaggedToI: cannot truncate"); | 4928 __ RecordComment("Deferred TaggedToI: cannot truncate"); |
| 4938 DeoptimizeIf(ne, instr->environment(), scratch2, Operand(at)); | 4929 DeoptimizeIf(ne, instr, scratch2, Operand(at)); |
| 4939 __ Branch(USE_DELAY_SLOT, &done); | 4930 __ Branch(USE_DELAY_SLOT, &done); |
| 4940 __ mov(input_reg, zero_reg); // In delay slot. | 4931 __ mov(input_reg, zero_reg); // In delay slot. |
| 4941 } else { | 4932 } else { |
| 4942 __ RecordComment("Deferred TaggedToI: not a heap number"); | 4933 __ RecordComment("Deferred TaggedToI: not a heap number"); |
| 4943 DeoptimizeIf(ne, instr->environment(), scratch1, Operand(at)); | 4934 DeoptimizeIf(ne, instr, scratch1, Operand(at)); |
| 4944 | 4935 |
| 4945 // Load the double value. | 4936 // Load the double value. |
| 4946 __ ldc1(double_scratch, | 4937 __ ldc1(double_scratch, |
| 4947 FieldMemOperand(input_reg, HeapNumber::kValueOffset)); | 4938 FieldMemOperand(input_reg, HeapNumber::kValueOffset)); |
| 4948 | 4939 |
| 4949 Register except_flag = scratch2; | 4940 Register except_flag = scratch2; |
| 4950 __ EmitFPUTruncate(kRoundToZero, | 4941 __ EmitFPUTruncate(kRoundToZero, |
| 4951 input_reg, | 4942 input_reg, |
| 4952 double_scratch, | 4943 double_scratch, |
| 4953 scratch1, | 4944 scratch1, |
| 4954 double_scratch2, | 4945 double_scratch2, |
| 4955 except_flag, | 4946 except_flag, |
| 4956 kCheckForInexactConversion); | 4947 kCheckForInexactConversion); |
| 4957 | 4948 |
| 4958 __ RecordComment("Deferred TaggedToI: lost precision or NaN"); | 4949 __ RecordComment("Deferred TaggedToI: lost precision or NaN"); |
| 4959 DeoptimizeIf(ne, instr->environment(), except_flag, Operand(zero_reg)); | 4950 DeoptimizeIf(ne, instr, except_flag, Operand(zero_reg)); |
| 4960 | 4951 |
| 4961 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 4952 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 4962 __ Branch(&done, ne, input_reg, Operand(zero_reg)); | 4953 __ Branch(&done, ne, input_reg, Operand(zero_reg)); |
| 4963 | 4954 |
| 4964 __ Mfhc1(scratch1, double_scratch); | 4955 __ Mfhc1(scratch1, double_scratch); |
| 4965 __ And(scratch1, scratch1, Operand(HeapNumber::kSignMask)); | 4956 __ And(scratch1, scratch1, Operand(HeapNumber::kSignMask)); |
| 4966 __ RecordComment("Deferred TaggedToI: minus zero"); | 4957 __ RecordComment("Deferred TaggedToI: minus zero"); |
| 4967 DeoptimizeIf(ne, instr->environment(), scratch1, Operand(zero_reg)); | 4958 DeoptimizeIf(ne, instr, scratch1, Operand(zero_reg)); |
| 4968 } | 4959 } |
| 4969 } | 4960 } |
| 4970 __ bind(&done); | 4961 __ bind(&done); |
| 4971 } | 4962 } |
| 4972 | 4963 |
| 4973 | 4964 |
| 4974 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { | 4965 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { |
| 4975 class DeferredTaggedToI FINAL : public LDeferredCode { | 4966 class DeferredTaggedToI FINAL : public LDeferredCode { |
| 4976 public: | 4967 public: |
| 4977 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) | 4968 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5011 LOperand* result = instr->result(); | 5002 LOperand* result = instr->result(); |
| 5012 DCHECK(result->IsDoubleRegister()); | 5003 DCHECK(result->IsDoubleRegister()); |
| 5013 | 5004 |
| 5014 Register input_reg = ToRegister(input); | 5005 Register input_reg = ToRegister(input); |
| 5015 DoubleRegister result_reg = ToDoubleRegister(result); | 5006 DoubleRegister result_reg = ToDoubleRegister(result); |
| 5016 | 5007 |
| 5017 HValue* value = instr->hydrogen()->value(); | 5008 HValue* value = instr->hydrogen()->value(); |
| 5018 NumberUntagDMode mode = value->representation().IsSmi() | 5009 NumberUntagDMode mode = value->representation().IsSmi() |
| 5019 ? NUMBER_CANDIDATE_IS_SMI : NUMBER_CANDIDATE_IS_ANY_TAGGED; | 5010 ? NUMBER_CANDIDATE_IS_SMI : NUMBER_CANDIDATE_IS_ANY_TAGGED; |
| 5020 | 5011 |
| 5021 EmitNumberUntagD(input_reg, result_reg, | 5012 EmitNumberUntagD(instr, input_reg, result_reg, mode); |
| 5022 instr->hydrogen()->can_convert_undefined_to_nan(), | |
| 5023 instr->hydrogen()->deoptimize_on_minus_zero(), | |
| 5024 instr->environment(), | |
| 5025 mode); | |
| 5026 } | 5013 } |
| 5027 | 5014 |
| 5028 | 5015 |
| 5029 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { | 5016 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { |
| 5030 Register result_reg = ToRegister(instr->result()); | 5017 Register result_reg = ToRegister(instr->result()); |
| 5031 Register scratch1 = scratch0(); | 5018 Register scratch1 = scratch0(); |
| 5032 DoubleRegister double_input = ToDoubleRegister(instr->value()); | 5019 DoubleRegister double_input = ToDoubleRegister(instr->value()); |
| 5033 | 5020 |
| 5034 if (instr->truncating()) { | 5021 if (instr->truncating()) { |
| 5035 __ TruncateDoubleToI(result_reg, double_input); | 5022 __ TruncateDoubleToI(result_reg, double_input); |
| 5036 } else { | 5023 } else { |
| 5037 Register except_flag = LCodeGen::scratch1(); | 5024 Register except_flag = LCodeGen::scratch1(); |
| 5038 | 5025 |
| 5039 __ EmitFPUTruncate(kRoundToMinusInf, | 5026 __ EmitFPUTruncate(kRoundToMinusInf, |
| 5040 result_reg, | 5027 result_reg, |
| 5041 double_input, | 5028 double_input, |
| 5042 scratch1, | 5029 scratch1, |
| 5043 double_scratch0(), | 5030 double_scratch0(), |
| 5044 except_flag, | 5031 except_flag, |
| 5045 kCheckForInexactConversion); | 5032 kCheckForInexactConversion); |
| 5046 | 5033 |
| 5047 // Deopt if the operation did not succeed (except_flag != 0). | 5034 // Deopt if the operation did not succeed (except_flag != 0). |
| 5048 DeoptimizeIf(ne, instr->environment(), except_flag, Operand(zero_reg)); | 5035 DeoptimizeIf(ne, instr, except_flag, Operand(zero_reg)); |
| 5049 | 5036 |
| 5050 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 5037 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 5051 Label done; | 5038 Label done; |
| 5052 __ Branch(&done, ne, result_reg, Operand(zero_reg)); | 5039 __ Branch(&done, ne, result_reg, Operand(zero_reg)); |
| 5053 __ Mfhc1(scratch1, double_input); | 5040 __ Mfhc1(scratch1, double_input); |
| 5054 __ And(scratch1, scratch1, Operand(HeapNumber::kSignMask)); | 5041 __ And(scratch1, scratch1, Operand(HeapNumber::kSignMask)); |
| 5055 DeoptimizeIf(ne, instr->environment(), scratch1, Operand(zero_reg)); | 5042 DeoptimizeIf(ne, instr, scratch1, Operand(zero_reg)); |
| 5056 __ bind(&done); | 5043 __ bind(&done); |
| 5057 } | 5044 } |
| 5058 } | 5045 } |
| 5059 } | 5046 } |
| 5060 | 5047 |
| 5061 | 5048 |
| 5062 void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) { | 5049 void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) { |
| 5063 Register result_reg = ToRegister(instr->result()); | 5050 Register result_reg = ToRegister(instr->result()); |
| 5064 Register scratch1 = LCodeGen::scratch0(); | 5051 Register scratch1 = LCodeGen::scratch0(); |
| 5065 DoubleRegister double_input = ToDoubleRegister(instr->value()); | 5052 DoubleRegister double_input = ToDoubleRegister(instr->value()); |
| 5066 | 5053 |
| 5067 if (instr->truncating()) { | 5054 if (instr->truncating()) { |
| 5068 __ TruncateDoubleToI(result_reg, double_input); | 5055 __ TruncateDoubleToI(result_reg, double_input); |
| 5069 } else { | 5056 } else { |
| 5070 Register except_flag = LCodeGen::scratch1(); | 5057 Register except_flag = LCodeGen::scratch1(); |
| 5071 | 5058 |
| 5072 __ EmitFPUTruncate(kRoundToMinusInf, | 5059 __ EmitFPUTruncate(kRoundToMinusInf, |
| 5073 result_reg, | 5060 result_reg, |
| 5074 double_input, | 5061 double_input, |
| 5075 scratch1, | 5062 scratch1, |
| 5076 double_scratch0(), | 5063 double_scratch0(), |
| 5077 except_flag, | 5064 except_flag, |
| 5078 kCheckForInexactConversion); | 5065 kCheckForInexactConversion); |
| 5079 | 5066 |
| 5080 // Deopt if the operation did not succeed (except_flag != 0). | 5067 // Deopt if the operation did not succeed (except_flag != 0). |
| 5081 DeoptimizeIf(ne, instr->environment(), except_flag, Operand(zero_reg)); | 5068 DeoptimizeIf(ne, instr, except_flag, Operand(zero_reg)); |
| 5082 | 5069 |
| 5083 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 5070 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 5084 Label done; | 5071 Label done; |
| 5085 __ Branch(&done, ne, result_reg, Operand(zero_reg)); | 5072 __ Branch(&done, ne, result_reg, Operand(zero_reg)); |
| 5086 __ Mfhc1(scratch1, double_input); | 5073 __ Mfhc1(scratch1, double_input); |
| 5087 __ And(scratch1, scratch1, Operand(HeapNumber::kSignMask)); | 5074 __ And(scratch1, scratch1, Operand(HeapNumber::kSignMask)); |
| 5088 DeoptimizeIf(ne, instr->environment(), scratch1, Operand(zero_reg)); | 5075 DeoptimizeIf(ne, instr, scratch1, Operand(zero_reg)); |
| 5089 __ bind(&done); | 5076 __ bind(&done); |
| 5090 } | 5077 } |
| 5091 } | 5078 } |
| 5092 __ SmiTagCheckOverflow(result_reg, result_reg, scratch1); | 5079 __ SmiTagCheckOverflow(result_reg, result_reg, scratch1); |
| 5093 DeoptimizeIf(lt, instr->environment(), scratch1, Operand(zero_reg)); | 5080 DeoptimizeIf(lt, instr, scratch1, Operand(zero_reg)); |
| 5094 } | 5081 } |
| 5095 | 5082 |
| 5096 | 5083 |
| 5097 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { | 5084 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { |
| 5098 LOperand* input = instr->value(); | 5085 LOperand* input = instr->value(); |
| 5099 __ SmiTst(ToRegister(input), at); | 5086 __ SmiTst(ToRegister(input), at); |
| 5100 DeoptimizeIf(ne, instr->environment(), at, Operand(zero_reg)); | 5087 DeoptimizeIf(ne, instr, at, Operand(zero_reg)); |
| 5101 } | 5088 } |
| 5102 | 5089 |
| 5103 | 5090 |
| 5104 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { | 5091 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { |
| 5105 if (!instr->hydrogen()->value()->type().IsHeapObject()) { | 5092 if (!instr->hydrogen()->value()->type().IsHeapObject()) { |
| 5106 LOperand* input = instr->value(); | 5093 LOperand* input = instr->value(); |
| 5107 __ SmiTst(ToRegister(input), at); | 5094 __ SmiTst(ToRegister(input), at); |
| 5108 DeoptimizeIf(eq, instr->environment(), at, Operand(zero_reg)); | 5095 DeoptimizeIf(eq, instr, at, Operand(zero_reg)); |
| 5109 } | 5096 } |
| 5110 } | 5097 } |
| 5111 | 5098 |
| 5112 | 5099 |
| 5113 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { | 5100 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { |
| 5114 Register input = ToRegister(instr->value()); | 5101 Register input = ToRegister(instr->value()); |
| 5115 Register scratch = scratch0(); | 5102 Register scratch = scratch0(); |
| 5116 | 5103 |
| 5117 __ GetObjectType(input, scratch, scratch); | 5104 __ GetObjectType(input, scratch, scratch); |
| 5118 | 5105 |
| 5119 if (instr->hydrogen()->is_interval_check()) { | 5106 if (instr->hydrogen()->is_interval_check()) { |
| 5120 InstanceType first; | 5107 InstanceType first; |
| 5121 InstanceType last; | 5108 InstanceType last; |
| 5122 instr->hydrogen()->GetCheckInterval(&first, &last); | 5109 instr->hydrogen()->GetCheckInterval(&first, &last); |
| 5123 | 5110 |
| 5124 // If there is only one type in the interval check for equality. | 5111 // If there is only one type in the interval check for equality. |
| 5125 if (first == last) { | 5112 if (first == last) { |
| 5126 DeoptimizeIf(ne, instr->environment(), scratch, Operand(first)); | 5113 DeoptimizeIf(ne, instr, scratch, Operand(first)); |
| 5127 } else { | 5114 } else { |
| 5128 DeoptimizeIf(lo, instr->environment(), scratch, Operand(first)); | 5115 DeoptimizeIf(lo, instr, scratch, Operand(first)); |
| 5129 // Omit check for the last type. | 5116 // Omit check for the last type. |
| 5130 if (last != LAST_TYPE) { | 5117 if (last != LAST_TYPE) { |
| 5131 DeoptimizeIf(hi, instr->environment(), scratch, Operand(last)); | 5118 DeoptimizeIf(hi, instr, scratch, Operand(last)); |
| 5132 } | 5119 } |
| 5133 } | 5120 } |
| 5134 } else { | 5121 } else { |
| 5135 uint8_t mask; | 5122 uint8_t mask; |
| 5136 uint8_t tag; | 5123 uint8_t tag; |
| 5137 instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag); | 5124 instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag); |
| 5138 | 5125 |
| 5139 if (base::bits::IsPowerOfTwo32(mask)) { | 5126 if (base::bits::IsPowerOfTwo32(mask)) { |
| 5140 DCHECK(tag == 0 || base::bits::IsPowerOfTwo32(tag)); | 5127 DCHECK(tag == 0 || base::bits::IsPowerOfTwo32(tag)); |
| 5141 __ And(at, scratch, mask); | 5128 __ And(at, scratch, mask); |
| 5142 DeoptimizeIf(tag == 0 ? ne : eq, instr->environment(), | 5129 DeoptimizeIf(tag == 0 ? ne : eq, instr, at, Operand(zero_reg)); |
| 5143 at, Operand(zero_reg)); | |
| 5144 } else { | 5130 } else { |
| 5145 __ And(scratch, scratch, Operand(mask)); | 5131 __ And(scratch, scratch, Operand(mask)); |
| 5146 DeoptimizeIf(ne, instr->environment(), scratch, Operand(tag)); | 5132 DeoptimizeIf(ne, instr, scratch, Operand(tag)); |
| 5147 } | 5133 } |
| 5148 } | 5134 } |
| 5149 } | 5135 } |
| 5150 | 5136 |
| 5151 | 5137 |
| 5152 void LCodeGen::DoCheckValue(LCheckValue* instr) { | 5138 void LCodeGen::DoCheckValue(LCheckValue* instr) { |
| 5153 Register reg = ToRegister(instr->value()); | 5139 Register reg = ToRegister(instr->value()); |
| 5154 Handle<HeapObject> object = instr->hydrogen()->object().handle(); | 5140 Handle<HeapObject> object = instr->hydrogen()->object().handle(); |
| 5155 AllowDeferredHandleDereference smi_check; | 5141 AllowDeferredHandleDereference smi_check; |
| 5156 if (isolate()->heap()->InNewSpace(*object)) { | 5142 if (isolate()->heap()->InNewSpace(*object)) { |
| 5157 Register reg = ToRegister(instr->value()); | 5143 Register reg = ToRegister(instr->value()); |
| 5158 Handle<Cell> cell = isolate()->factory()->NewCell(object); | 5144 Handle<Cell> cell = isolate()->factory()->NewCell(object); |
| 5159 __ li(at, Operand(Handle<Object>(cell))); | 5145 __ li(at, Operand(Handle<Object>(cell))); |
| 5160 __ lw(at, FieldMemOperand(at, Cell::kValueOffset)); | 5146 __ lw(at, FieldMemOperand(at, Cell::kValueOffset)); |
| 5161 DeoptimizeIf(ne, instr->environment(), reg, | 5147 DeoptimizeIf(ne, instr, reg, Operand(at)); |
| 5162 Operand(at)); | |
| 5163 } else { | 5148 } else { |
| 5164 DeoptimizeIf(ne, instr->environment(), reg, | 5149 DeoptimizeIf(ne, instr, reg, Operand(object)); |
| 5165 Operand(object)); | |
| 5166 } | 5150 } |
| 5167 } | 5151 } |
| 5168 | 5152 |
| 5169 | 5153 |
| 5170 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) { | 5154 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) { |
| 5171 { | 5155 { |
| 5172 PushSafepointRegistersScope scope(this); | 5156 PushSafepointRegistersScope scope(this); |
| 5173 __ push(object); | 5157 __ push(object); |
| 5174 __ mov(cp, zero_reg); | 5158 __ mov(cp, zero_reg); |
| 5175 __ CallRuntimeSaveDoubles(Runtime::kTryMigrateInstance); | 5159 __ CallRuntimeSaveDoubles(Runtime::kTryMigrateInstance); |
| 5176 RecordSafepointWithRegisters( | 5160 RecordSafepointWithRegisters( |
| 5177 instr->pointer_map(), 1, Safepoint::kNoLazyDeopt); | 5161 instr->pointer_map(), 1, Safepoint::kNoLazyDeopt); |
| 5178 __ StoreToSafepointRegisterSlot(v0, scratch0()); | 5162 __ StoreToSafepointRegisterSlot(v0, scratch0()); |
| 5179 } | 5163 } |
| 5180 __ SmiTst(scratch0(), at); | 5164 __ SmiTst(scratch0(), at); |
| 5181 DeoptimizeIf(eq, instr->environment(), at, Operand(zero_reg)); | 5165 DeoptimizeIf(eq, instr, at, Operand(zero_reg)); |
| 5182 } | 5166 } |
| 5183 | 5167 |
| 5184 | 5168 |
| 5185 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { | 5169 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { |
| 5186 class DeferredCheckMaps FINAL : public LDeferredCode { | 5170 class DeferredCheckMaps FINAL : public LDeferredCode { |
| 5187 public: | 5171 public: |
| 5188 DeferredCheckMaps(LCodeGen* codegen, LCheckMaps* instr, Register object) | 5172 DeferredCheckMaps(LCodeGen* codegen, LCheckMaps* instr, Register object) |
| 5189 : LDeferredCode(codegen), instr_(instr), object_(object) { | 5173 : LDeferredCode(codegen), instr_(instr), object_(object) { |
| 5190 SetExit(check_maps()); | 5174 SetExit(check_maps()); |
| 5191 } | 5175 } |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5224 Label success; | 5208 Label success; |
| 5225 for (int i = 0; i < maps->size() - 1; i++) { | 5209 for (int i = 0; i < maps->size() - 1; i++) { |
| 5226 Handle<Map> map = maps->at(i).handle(); | 5210 Handle<Map> map = maps->at(i).handle(); |
| 5227 __ CompareMapAndBranch(map_reg, map, &success, eq, &success); | 5211 __ CompareMapAndBranch(map_reg, map, &success, eq, &success); |
| 5228 } | 5212 } |
| 5229 Handle<Map> map = maps->at(maps->size() - 1).handle(); | 5213 Handle<Map> map = maps->at(maps->size() - 1).handle(); |
| 5230 // Do the CompareMap() directly within the Branch() and DeoptimizeIf(). | 5214 // Do the CompareMap() directly within the Branch() and DeoptimizeIf(). |
| 5231 if (instr->hydrogen()->HasMigrationTarget()) { | 5215 if (instr->hydrogen()->HasMigrationTarget()) { |
| 5232 __ Branch(deferred->entry(), ne, map_reg, Operand(map)); | 5216 __ Branch(deferred->entry(), ne, map_reg, Operand(map)); |
| 5233 } else { | 5217 } else { |
| 5234 DeoptimizeIf(ne, instr->environment(), map_reg, Operand(map)); | 5218 DeoptimizeIf(ne, instr, map_reg, Operand(map)); |
| 5235 } | 5219 } |
| 5236 | 5220 |
| 5237 __ bind(&success); | 5221 __ bind(&success); |
| 5238 } | 5222 } |
| 5239 | 5223 |
| 5240 | 5224 |
| 5241 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { | 5225 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { |
| 5242 DoubleRegister value_reg = ToDoubleRegister(instr->unclamped()); | 5226 DoubleRegister value_reg = ToDoubleRegister(instr->unclamped()); |
| 5243 Register result_reg = ToRegister(instr->result()); | 5227 Register result_reg = ToRegister(instr->result()); |
| 5244 DoubleRegister temp_reg = ToDoubleRegister(instr->temp()); | 5228 DoubleRegister temp_reg = ToDoubleRegister(instr->temp()); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 5262 | 5246 |
| 5263 // Both smi and heap number cases are handled. | 5247 // Both smi and heap number cases are handled. |
| 5264 __ UntagAndJumpIfSmi(scratch, input_reg, &is_smi); | 5248 __ UntagAndJumpIfSmi(scratch, input_reg, &is_smi); |
| 5265 | 5249 |
| 5266 // Check for heap number | 5250 // Check for heap number |
| 5267 __ lw(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); | 5251 __ lw(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); |
| 5268 __ Branch(&heap_number, eq, scratch, Operand(factory()->heap_number_map())); | 5252 __ Branch(&heap_number, eq, scratch, Operand(factory()->heap_number_map())); |
| 5269 | 5253 |
| 5270 // Check for undefined. Undefined is converted to zero for clamping | 5254 // Check for undefined. Undefined is converted to zero for clamping |
| 5271 // conversions. | 5255 // conversions. |
| 5272 DeoptimizeIf(ne, instr->environment(), input_reg, | 5256 DeoptimizeIf(ne, instr, input_reg, Operand(factory()->undefined_value())); |
| 5273 Operand(factory()->undefined_value())); | |
| 5274 __ mov(result_reg, zero_reg); | 5257 __ mov(result_reg, zero_reg); |
| 5275 __ jmp(&done); | 5258 __ jmp(&done); |
| 5276 | 5259 |
| 5277 // Heap number | 5260 // Heap number |
| 5278 __ bind(&heap_number); | 5261 __ bind(&heap_number); |
| 5279 __ ldc1(double_scratch0(), FieldMemOperand(input_reg, | 5262 __ ldc1(double_scratch0(), FieldMemOperand(input_reg, |
| 5280 HeapNumber::kValueOffset)); | 5263 HeapNumber::kValueOffset)); |
| 5281 __ ClampDoubleToUint8(result_reg, double_scratch0(), temp_reg); | 5264 __ ClampDoubleToUint8(result_reg, double_scratch0(), temp_reg); |
| 5282 __ jmp(&done); | 5265 __ jmp(&done); |
| 5283 | 5266 |
| (...skipping 403 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5687 Deoptimizer::BailoutType type = instr->hydrogen()->type(); | 5670 Deoptimizer::BailoutType type = instr->hydrogen()->type(); |
| 5688 // TODO(danno): Stubs expect all deopts to be lazy for historical reasons (the | 5671 // TODO(danno): Stubs expect all deopts to be lazy for historical reasons (the |
| 5689 // needed return address), even though the implementation of LAZY and EAGER is | 5672 // needed return address), even though the implementation of LAZY and EAGER is |
| 5690 // now identical. When LAZY is eventually completely folded into EAGER, remove | 5673 // now identical. When LAZY is eventually completely folded into EAGER, remove |
| 5691 // the special case below. | 5674 // the special case below. |
| 5692 if (info()->IsStub() && type == Deoptimizer::EAGER) { | 5675 if (info()->IsStub() && type == Deoptimizer::EAGER) { |
| 5693 type = Deoptimizer::LAZY; | 5676 type = Deoptimizer::LAZY; |
| 5694 } | 5677 } |
| 5695 | 5678 |
| 5696 Comment(";;; deoptimize: %s", instr->hydrogen()->reason()); | 5679 Comment(";;; deoptimize: %s", instr->hydrogen()->reason()); |
| 5697 DeoptimizeIf(al, instr->environment(), type, zero_reg, Operand(zero_reg)); | 5680 DeoptimizeIf(al, instr, type, zero_reg, Operand(zero_reg)); |
| 5698 } | 5681 } |
| 5699 | 5682 |
| 5700 | 5683 |
| 5701 void LCodeGen::DoDummy(LDummy* instr) { | 5684 void LCodeGen::DoDummy(LDummy* instr) { |
| 5702 // Nothing to see here, move on! | 5685 // Nothing to see here, move on! |
| 5703 } | 5686 } |
| 5704 | 5687 |
| 5705 | 5688 |
| 5706 void LCodeGen::DoDummyUse(LDummyUse* instr) { | 5689 void LCodeGen::DoDummyUse(LDummyUse* instr) { |
| 5707 // Nothing to see here, move on! | 5690 // Nothing to see here, move on! |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5778 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); | 5761 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); |
| 5779 | 5762 |
| 5780 GenerateOsrPrologue(); | 5763 GenerateOsrPrologue(); |
| 5781 } | 5764 } |
| 5782 | 5765 |
| 5783 | 5766 |
| 5784 void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) { | 5767 void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) { |
| 5785 Register result = ToRegister(instr->result()); | 5768 Register result = ToRegister(instr->result()); |
| 5786 Register object = ToRegister(instr->object()); | 5769 Register object = ToRegister(instr->object()); |
| 5787 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); | 5770 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); |
| 5788 DeoptimizeIf(eq, instr->environment(), object, Operand(at)); | 5771 DeoptimizeIf(eq, instr, object, Operand(at)); |
| 5789 | 5772 |
| 5790 Register null_value = t1; | 5773 Register null_value = t1; |
| 5791 __ LoadRoot(null_value, Heap::kNullValueRootIndex); | 5774 __ LoadRoot(null_value, Heap::kNullValueRootIndex); |
| 5792 DeoptimizeIf(eq, instr->environment(), object, Operand(null_value)); | 5775 DeoptimizeIf(eq, instr, object, Operand(null_value)); |
| 5793 | 5776 |
| 5794 __ And(at, object, kSmiTagMask); | 5777 __ And(at, object, kSmiTagMask); |
| 5795 DeoptimizeIf(eq, instr->environment(), at, Operand(zero_reg)); | 5778 DeoptimizeIf(eq, instr, at, Operand(zero_reg)); |
| 5796 | 5779 |
| 5797 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); | 5780 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); |
| 5798 __ GetObjectType(object, a1, a1); | 5781 __ GetObjectType(object, a1, a1); |
| 5799 DeoptimizeIf(le, instr->environment(), a1, Operand(LAST_JS_PROXY_TYPE)); | 5782 DeoptimizeIf(le, instr, a1, Operand(LAST_JS_PROXY_TYPE)); |
| 5800 | 5783 |
| 5801 Label use_cache, call_runtime; | 5784 Label use_cache, call_runtime; |
| 5802 DCHECK(object.is(a0)); | 5785 DCHECK(object.is(a0)); |
| 5803 __ CheckEnumCache(null_value, &call_runtime); | 5786 __ CheckEnumCache(null_value, &call_runtime); |
| 5804 | 5787 |
| 5805 __ lw(result, FieldMemOperand(object, HeapObject::kMapOffset)); | 5788 __ lw(result, FieldMemOperand(object, HeapObject::kMapOffset)); |
| 5806 __ Branch(&use_cache); | 5789 __ Branch(&use_cache); |
| 5807 | 5790 |
| 5808 // Get the set of properties to enumerate. | 5791 // Get the set of properties to enumerate. |
| 5809 __ bind(&call_runtime); | 5792 __ bind(&call_runtime); |
| 5810 __ push(object); | 5793 __ push(object); |
| 5811 CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr); | 5794 CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr); |
| 5812 | 5795 |
| 5813 __ lw(a1, FieldMemOperand(v0, HeapObject::kMapOffset)); | 5796 __ lw(a1, FieldMemOperand(v0, HeapObject::kMapOffset)); |
| 5814 DCHECK(result.is(v0)); | 5797 DCHECK(result.is(v0)); |
| 5815 __ LoadRoot(at, Heap::kMetaMapRootIndex); | 5798 __ LoadRoot(at, Heap::kMetaMapRootIndex); |
| 5816 DeoptimizeIf(ne, instr->environment(), a1, Operand(at)); | 5799 DeoptimizeIf(ne, instr, a1, Operand(at)); |
| 5817 __ bind(&use_cache); | 5800 __ bind(&use_cache); |
| 5818 } | 5801 } |
| 5819 | 5802 |
| 5820 | 5803 |
| 5821 void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) { | 5804 void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) { |
| 5822 Register map = ToRegister(instr->map()); | 5805 Register map = ToRegister(instr->map()); |
| 5823 Register result = ToRegister(instr->result()); | 5806 Register result = ToRegister(instr->result()); |
| 5824 Label load_cache, done; | 5807 Label load_cache, done; |
| 5825 __ EnumLength(result, map); | 5808 __ EnumLength(result, map); |
| 5826 __ Branch(&load_cache, ne, result, Operand(Smi::FromInt(0))); | 5809 __ Branch(&load_cache, ne, result, Operand(Smi::FromInt(0))); |
| 5827 __ li(result, Operand(isolate()->factory()->empty_fixed_array())); | 5810 __ li(result, Operand(isolate()->factory()->empty_fixed_array())); |
| 5828 __ jmp(&done); | 5811 __ jmp(&done); |
| 5829 | 5812 |
| 5830 __ bind(&load_cache); | 5813 __ bind(&load_cache); |
| 5831 __ LoadInstanceDescriptors(map, result); | 5814 __ LoadInstanceDescriptors(map, result); |
| 5832 __ lw(result, | 5815 __ lw(result, |
| 5833 FieldMemOperand(result, DescriptorArray::kEnumCacheOffset)); | 5816 FieldMemOperand(result, DescriptorArray::kEnumCacheOffset)); |
| 5834 __ lw(result, | 5817 __ lw(result, |
| 5835 FieldMemOperand(result, FixedArray::SizeFor(instr->idx()))); | 5818 FieldMemOperand(result, FixedArray::SizeFor(instr->idx()))); |
| 5836 DeoptimizeIf(eq, instr->environment(), result, Operand(zero_reg)); | 5819 DeoptimizeIf(eq, instr, result, Operand(zero_reg)); |
| 5837 | 5820 |
| 5838 __ bind(&done); | 5821 __ bind(&done); |
| 5839 } | 5822 } |
| 5840 | 5823 |
| 5841 | 5824 |
| 5842 void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) { | 5825 void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) { |
| 5843 Register object = ToRegister(instr->value()); | 5826 Register object = ToRegister(instr->value()); |
| 5844 Register map = ToRegister(instr->map()); | 5827 Register map = ToRegister(instr->map()); |
| 5845 __ lw(scratch0(), FieldMemOperand(object, HeapObject::kMapOffset)); | 5828 __ lw(scratch0(), FieldMemOperand(object, HeapObject::kMapOffset)); |
| 5846 DeoptimizeIf(ne, instr->environment(), map, Operand(scratch0())); | 5829 DeoptimizeIf(ne, instr, map, Operand(scratch0())); |
| 5847 } | 5830 } |
| 5848 | 5831 |
| 5849 | 5832 |
| 5850 void LCodeGen::DoDeferredLoadMutableDouble(LLoadFieldByIndex* instr, | 5833 void LCodeGen::DoDeferredLoadMutableDouble(LLoadFieldByIndex* instr, |
| 5851 Register result, | 5834 Register result, |
| 5852 Register object, | 5835 Register object, |
| 5853 Register index) { | 5836 Register index) { |
| 5854 PushSafepointRegistersScope scope(this); | 5837 PushSafepointRegistersScope scope(this); |
| 5855 __ Push(object, index); | 5838 __ Push(object, index); |
| 5856 __ mov(cp, zero_reg); | 5839 __ mov(cp, zero_reg); |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5932 __ li(at, scope_info); | 5915 __ li(at, scope_info); |
| 5933 __ Push(at, ToRegister(instr->function())); | 5916 __ Push(at, ToRegister(instr->function())); |
| 5934 CallRuntime(Runtime::kPushBlockContext, 2, instr); | 5917 CallRuntime(Runtime::kPushBlockContext, 2, instr); |
| 5935 RecordSafepoint(Safepoint::kNoLazyDeopt); | 5918 RecordSafepoint(Safepoint::kNoLazyDeopt); |
| 5936 } | 5919 } |
| 5937 | 5920 |
| 5938 | 5921 |
| 5939 #undef __ | 5922 #undef __ |
| 5940 | 5923 |
| 5941 } } // namespace v8::internal | 5924 } } // namespace v8::internal |
| OLD | NEW |