| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #include "src/code-factory.h" | 7 #include "src/code-factory.h" |
| 8 #include "src/code-stubs.h" | 8 #include "src/code-stubs.h" |
| 9 #include "src/hydrogen-osr.h" | 9 #include "src/hydrogen-osr.h" |
| 10 #include "src/ic/ic.h" | 10 #include "src/ic/ic.h" |
| (...skipping 754 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 765 int deoptimization_index = deoptimizations_.length(); | 765 int deoptimization_index = deoptimizations_.length(); |
| 766 int pc_offset = masm()->pc_offset(); | 766 int pc_offset = masm()->pc_offset(); |
| 767 environment->Register(deoptimization_index, | 767 environment->Register(deoptimization_index, |
| 768 translation.index(), | 768 translation.index(), |
| 769 (mode == Safepoint::kLazyDeopt) ? pc_offset : -1); | 769 (mode == Safepoint::kLazyDeopt) ? pc_offset : -1); |
| 770 deoptimizations_.Add(environment, zone()); | 770 deoptimizations_.Add(environment, zone()); |
| 771 } | 771 } |
| 772 } | 772 } |
| 773 | 773 |
| 774 | 774 |
| 775 void LCodeGen::DeoptimizeIf(Condition condition, | 775 void LCodeGen::DeoptimizeIf(Condition condition, LInstruction* instr, |
| 776 LEnvironment* environment, | |
| 777 Deoptimizer::BailoutType bailout_type, | 776 Deoptimizer::BailoutType bailout_type, |
| 778 Register src1, | 777 Register src1, const Operand& src2) { |
| 779 const Operand& src2) { | 778 LEnvironment* environment = instr->environment(); |
| 780 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); | 779 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); |
| 781 DCHECK(environment->HasBeenRegistered()); | 780 DCHECK(environment->HasBeenRegistered()); |
| 782 int id = environment->deoptimization_index(); | 781 int id = environment->deoptimization_index(); |
| 783 DCHECK(info()->IsOptimizing() || info()->IsStub()); | 782 DCHECK(info()->IsOptimizing() || info()->IsStub()); |
| 784 Address entry = | 783 Address entry = |
| 785 Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type); | 784 Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type); |
| 786 if (entry == NULL) { | 785 if (entry == NULL) { |
| 787 Abort(kBailoutWasNotPrepared); | 786 Abort(kBailoutWasNotPrepared); |
| 788 return; | 787 return; |
| 789 } | 788 } |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 832 Deoptimizer::JumpTableEntry table_entry(entry, | 831 Deoptimizer::JumpTableEntry table_entry(entry, |
| 833 bailout_type, | 832 bailout_type, |
| 834 !frame_is_built_); | 833 !frame_is_built_); |
| 835 deopt_jump_table_.Add(table_entry, zone()); | 834 deopt_jump_table_.Add(table_entry, zone()); |
| 836 } | 835 } |
| 837 __ Branch(&deopt_jump_table_.last().label, condition, src1, src2); | 836 __ Branch(&deopt_jump_table_.last().label, condition, src1, src2); |
| 838 } | 837 } |
| 839 } | 838 } |
| 840 | 839 |
| 841 | 840 |
| 842 void LCodeGen::DeoptimizeIf(Condition condition, | 841 void LCodeGen::DeoptimizeIf(Condition condition, LInstruction* instr, |
| 843 LEnvironment* environment, | 842 Register src1, const Operand& src2) { |
| 844 Register src1, | |
| 845 const Operand& src2) { | |
| 846 Deoptimizer::BailoutType bailout_type = info()->IsStub() | 843 Deoptimizer::BailoutType bailout_type = info()->IsStub() |
| 847 ? Deoptimizer::LAZY | 844 ? Deoptimizer::LAZY |
| 848 : Deoptimizer::EAGER; | 845 : Deoptimizer::EAGER; |
| 849 DeoptimizeIf(condition, environment, bailout_type, src1, src2); | 846 DeoptimizeIf(condition, instr, bailout_type, src1, src2); |
| 850 } | 847 } |
| 851 | 848 |
| 852 | 849 |
| 853 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { | 850 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { |
| 854 int length = deoptimizations_.length(); | 851 int length = deoptimizations_.length(); |
| 855 if (length == 0) return; | 852 if (length == 0) return; |
| 856 Handle<DeoptimizationInputData> data = | 853 Handle<DeoptimizationInputData> data = |
| 857 DeoptimizationInputData::New(isolate(), length, TENURED); | 854 DeoptimizationInputData::New(isolate(), length, TENURED); |
| 858 | 855 |
| 859 Handle<ByteArray> translations = | 856 Handle<ByteArray> translations = |
| (...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1069 HMod* hmod = instr->hydrogen(); | 1066 HMod* hmod = instr->hydrogen(); |
| 1070 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); | 1067 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); |
| 1071 Label dividend_is_not_negative, done; | 1068 Label dividend_is_not_negative, done; |
| 1072 | 1069 |
| 1073 if (hmod->CheckFlag(HValue::kLeftCanBeNegative)) { | 1070 if (hmod->CheckFlag(HValue::kLeftCanBeNegative)) { |
| 1074 __ Branch(÷nd_is_not_negative, ge, dividend, Operand(zero_reg)); | 1071 __ Branch(÷nd_is_not_negative, ge, dividend, Operand(zero_reg)); |
| 1075 // Note: The code below even works when right contains kMinInt. | 1072 // Note: The code below even works when right contains kMinInt. |
| 1076 __ dsubu(dividend, zero_reg, dividend); | 1073 __ dsubu(dividend, zero_reg, dividend); |
| 1077 __ And(dividend, dividend, Operand(mask)); | 1074 __ And(dividend, dividend, Operand(mask)); |
| 1078 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1075 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1079 DeoptimizeIf(eq, instr->environment(), dividend, Operand(zero_reg)); | 1076 DeoptimizeIf(eq, instr, dividend, Operand(zero_reg)); |
| 1080 } | 1077 } |
| 1081 __ Branch(USE_DELAY_SLOT, &done); | 1078 __ Branch(USE_DELAY_SLOT, &done); |
| 1082 __ dsubu(dividend, zero_reg, dividend); | 1079 __ dsubu(dividend, zero_reg, dividend); |
| 1083 } | 1080 } |
| 1084 | 1081 |
| 1085 __ bind(÷nd_is_not_negative); | 1082 __ bind(÷nd_is_not_negative); |
| 1086 __ And(dividend, dividend, Operand(mask)); | 1083 __ And(dividend, dividend, Operand(mask)); |
| 1087 __ bind(&done); | 1084 __ bind(&done); |
| 1088 } | 1085 } |
| 1089 | 1086 |
| 1090 | 1087 |
| 1091 void LCodeGen::DoModByConstI(LModByConstI* instr) { | 1088 void LCodeGen::DoModByConstI(LModByConstI* instr) { |
| 1092 Register dividend = ToRegister(instr->dividend()); | 1089 Register dividend = ToRegister(instr->dividend()); |
| 1093 int32_t divisor = instr->divisor(); | 1090 int32_t divisor = instr->divisor(); |
| 1094 Register result = ToRegister(instr->result()); | 1091 Register result = ToRegister(instr->result()); |
| 1095 DCHECK(!dividend.is(result)); | 1092 DCHECK(!dividend.is(result)); |
| 1096 | 1093 |
| 1097 if (divisor == 0) { | 1094 if (divisor == 0) { |
| 1098 DeoptimizeIf(al, instr->environment()); | 1095 DeoptimizeIf(al, instr); |
| 1099 return; | 1096 return; |
| 1100 } | 1097 } |
| 1101 | 1098 |
| 1102 __ TruncatingDiv(result, dividend, Abs(divisor)); | 1099 __ TruncatingDiv(result, dividend, Abs(divisor)); |
| 1103 __ Dmul(result, result, Operand(Abs(divisor))); | 1100 __ Dmul(result, result, Operand(Abs(divisor))); |
| 1104 __ Dsubu(result, dividend, Operand(result)); | 1101 __ Dsubu(result, dividend, Operand(result)); |
| 1105 | 1102 |
| 1106 // Check for negative zero. | 1103 // Check for negative zero. |
| 1107 HMod* hmod = instr->hydrogen(); | 1104 HMod* hmod = instr->hydrogen(); |
| 1108 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1105 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1109 Label remainder_not_zero; | 1106 Label remainder_not_zero; |
| 1110 __ Branch(&remainder_not_zero, ne, result, Operand(zero_reg)); | 1107 __ Branch(&remainder_not_zero, ne, result, Operand(zero_reg)); |
| 1111 DeoptimizeIf(lt, instr->environment(), dividend, Operand(zero_reg)); | 1108 DeoptimizeIf(lt, instr, dividend, Operand(zero_reg)); |
| 1112 __ bind(&remainder_not_zero); | 1109 __ bind(&remainder_not_zero); |
| 1113 } | 1110 } |
| 1114 } | 1111 } |
| 1115 | 1112 |
| 1116 | 1113 |
| 1117 void LCodeGen::DoModI(LModI* instr) { | 1114 void LCodeGen::DoModI(LModI* instr) { |
| 1118 HMod* hmod = instr->hydrogen(); | 1115 HMod* hmod = instr->hydrogen(); |
| 1119 const Register left_reg = ToRegister(instr->left()); | 1116 const Register left_reg = ToRegister(instr->left()); |
| 1120 const Register right_reg = ToRegister(instr->right()); | 1117 const Register right_reg = ToRegister(instr->right()); |
| 1121 const Register result_reg = ToRegister(instr->result()); | 1118 const Register result_reg = ToRegister(instr->result()); |
| 1122 | 1119 |
| 1123 // div runs in the background while we check for special cases. | 1120 // div runs in the background while we check for special cases. |
| 1124 __ Dmod(result_reg, left_reg, right_reg); | 1121 __ Dmod(result_reg, left_reg, right_reg); |
| 1125 | 1122 |
| 1126 Label done; | 1123 Label done; |
| 1127 // Check for x % 0, we have to deopt in this case because we can't return a | 1124 // Check for x % 0, we have to deopt in this case because we can't return a |
| 1128 // NaN. | 1125 // NaN. |
| 1129 if (hmod->CheckFlag(HValue::kCanBeDivByZero)) { | 1126 if (hmod->CheckFlag(HValue::kCanBeDivByZero)) { |
| 1130 DeoptimizeIf(eq, instr->environment(), right_reg, Operand(zero_reg)); | 1127 DeoptimizeIf(eq, instr, right_reg, Operand(zero_reg)); |
| 1131 } | 1128 } |
| 1132 | 1129 |
| 1133 // Check for kMinInt % -1, div will return kMinInt, which is not what we | 1130 // Check for kMinInt % -1, div will return kMinInt, which is not what we |
| 1134 // want. We have to deopt if we care about -0, because we can't return that. | 1131 // want. We have to deopt if we care about -0, because we can't return that. |
| 1135 if (hmod->CheckFlag(HValue::kCanOverflow)) { | 1132 if (hmod->CheckFlag(HValue::kCanOverflow)) { |
| 1136 Label no_overflow_possible; | 1133 Label no_overflow_possible; |
| 1137 __ Branch(&no_overflow_possible, ne, left_reg, Operand(kMinInt)); | 1134 __ Branch(&no_overflow_possible, ne, left_reg, Operand(kMinInt)); |
| 1138 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1135 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1139 DeoptimizeIf(eq, instr->environment(), right_reg, Operand(-1)); | 1136 DeoptimizeIf(eq, instr, right_reg, Operand(-1)); |
| 1140 } else { | 1137 } else { |
| 1141 __ Branch(&no_overflow_possible, ne, right_reg, Operand(-1)); | 1138 __ Branch(&no_overflow_possible, ne, right_reg, Operand(-1)); |
| 1142 __ Branch(USE_DELAY_SLOT, &done); | 1139 __ Branch(USE_DELAY_SLOT, &done); |
| 1143 __ mov(result_reg, zero_reg); | 1140 __ mov(result_reg, zero_reg); |
| 1144 } | 1141 } |
| 1145 __ bind(&no_overflow_possible); | 1142 __ bind(&no_overflow_possible); |
| 1146 } | 1143 } |
| 1147 | 1144 |
| 1148 // If we care about -0, test if the dividend is <0 and the result is 0. | 1145 // If we care about -0, test if the dividend is <0 and the result is 0. |
| 1149 __ Branch(&done, ge, left_reg, Operand(zero_reg)); | 1146 __ Branch(&done, ge, left_reg, Operand(zero_reg)); |
| 1150 | 1147 |
| 1151 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1148 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1152 DeoptimizeIf(eq, instr->environment(), result_reg, Operand(zero_reg)); | 1149 DeoptimizeIf(eq, instr, result_reg, Operand(zero_reg)); |
| 1153 } | 1150 } |
| 1154 __ bind(&done); | 1151 __ bind(&done); |
| 1155 } | 1152 } |
| 1156 | 1153 |
| 1157 | 1154 |
| 1158 void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) { | 1155 void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) { |
| 1159 Register dividend = ToRegister(instr->dividend()); | 1156 Register dividend = ToRegister(instr->dividend()); |
| 1160 int32_t divisor = instr->divisor(); | 1157 int32_t divisor = instr->divisor(); |
| 1161 Register result = ToRegister(instr->result()); | 1158 Register result = ToRegister(instr->result()); |
| 1162 DCHECK(divisor == kMinInt || base::bits::IsPowerOfTwo32(Abs(divisor))); | 1159 DCHECK(divisor == kMinInt || base::bits::IsPowerOfTwo32(Abs(divisor))); |
| 1163 DCHECK(!result.is(dividend)); | 1160 DCHECK(!result.is(dividend)); |
| 1164 | 1161 |
| 1165 // Check for (0 / -x) that will produce negative zero. | 1162 // Check for (0 / -x) that will produce negative zero. |
| 1166 HDiv* hdiv = instr->hydrogen(); | 1163 HDiv* hdiv = instr->hydrogen(); |
| 1167 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { | 1164 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { |
| 1168 DeoptimizeIf(eq, instr->environment(), dividend, Operand(zero_reg)); | 1165 DeoptimizeIf(eq, instr, dividend, Operand(zero_reg)); |
| 1169 } | 1166 } |
| 1170 // Check for (kMinInt / -1). | 1167 // Check for (kMinInt / -1). |
| 1171 if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) { | 1168 if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) { |
| 1172 DeoptimizeIf(eq, instr->environment(), dividend, Operand(kMinInt)); | 1169 DeoptimizeIf(eq, instr, dividend, Operand(kMinInt)); |
| 1173 } | 1170 } |
| 1174 // Deoptimize if remainder will not be 0. | 1171 // Deoptimize if remainder will not be 0. |
| 1175 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) && | 1172 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) && |
| 1176 divisor != 1 && divisor != -1) { | 1173 divisor != 1 && divisor != -1) { |
| 1177 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); | 1174 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); |
| 1178 __ And(at, dividend, Operand(mask)); | 1175 __ And(at, dividend, Operand(mask)); |
| 1179 DeoptimizeIf(ne, instr->environment(), at, Operand(zero_reg)); | 1176 DeoptimizeIf(ne, instr, at, Operand(zero_reg)); |
| 1180 } | 1177 } |
| 1181 | 1178 |
| 1182 if (divisor == -1) { // Nice shortcut, not needed for correctness. | 1179 if (divisor == -1) { // Nice shortcut, not needed for correctness. |
| 1183 __ Dsubu(result, zero_reg, dividend); | 1180 __ Dsubu(result, zero_reg, dividend); |
| 1184 return; | 1181 return; |
| 1185 } | 1182 } |
| 1186 uint16_t shift = WhichPowerOf2Abs(divisor); | 1183 uint16_t shift = WhichPowerOf2Abs(divisor); |
| 1187 if (shift == 0) { | 1184 if (shift == 0) { |
| 1188 __ Move(result, dividend); | 1185 __ Move(result, dividend); |
| 1189 } else if (shift == 1) { | 1186 } else if (shift == 1) { |
| 1190 __ dsrl32(result, dividend, 31); | 1187 __ dsrl32(result, dividend, 31); |
| 1191 __ Daddu(result, dividend, Operand(result)); | 1188 __ Daddu(result, dividend, Operand(result)); |
| 1192 } else { | 1189 } else { |
| 1193 __ dsra32(result, dividend, 31); | 1190 __ dsra32(result, dividend, 31); |
| 1194 __ dsrl32(result, result, 32 - shift); | 1191 __ dsrl32(result, result, 32 - shift); |
| 1195 __ Daddu(result, dividend, Operand(result)); | 1192 __ Daddu(result, dividend, Operand(result)); |
| 1196 } | 1193 } |
| 1197 if (shift > 0) __ dsra(result, result, shift); | 1194 if (shift > 0) __ dsra(result, result, shift); |
| 1198 if (divisor < 0) __ Dsubu(result, zero_reg, result); | 1195 if (divisor < 0) __ Dsubu(result, zero_reg, result); |
| 1199 } | 1196 } |
| 1200 | 1197 |
| 1201 | 1198 |
| 1202 void LCodeGen::DoDivByConstI(LDivByConstI* instr) { | 1199 void LCodeGen::DoDivByConstI(LDivByConstI* instr) { |
| 1203 Register dividend = ToRegister(instr->dividend()); | 1200 Register dividend = ToRegister(instr->dividend()); |
| 1204 int32_t divisor = instr->divisor(); | 1201 int32_t divisor = instr->divisor(); |
| 1205 Register result = ToRegister(instr->result()); | 1202 Register result = ToRegister(instr->result()); |
| 1206 DCHECK(!dividend.is(result)); | 1203 DCHECK(!dividend.is(result)); |
| 1207 | 1204 |
| 1208 if (divisor == 0) { | 1205 if (divisor == 0) { |
| 1209 DeoptimizeIf(al, instr->environment()); | 1206 DeoptimizeIf(al, instr); |
| 1210 return; | 1207 return; |
| 1211 } | 1208 } |
| 1212 | 1209 |
| 1213 // Check for (0 / -x) that will produce negative zero. | 1210 // Check for (0 / -x) that will produce negative zero. |
| 1214 HDiv* hdiv = instr->hydrogen(); | 1211 HDiv* hdiv = instr->hydrogen(); |
| 1215 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { | 1212 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { |
| 1216 DeoptimizeIf(eq, instr->environment(), dividend, Operand(zero_reg)); | 1213 DeoptimizeIf(eq, instr, dividend, Operand(zero_reg)); |
| 1217 } | 1214 } |
| 1218 | 1215 |
| 1219 __ TruncatingDiv(result, dividend, Abs(divisor)); | 1216 __ TruncatingDiv(result, dividend, Abs(divisor)); |
| 1220 if (divisor < 0) __ Subu(result, zero_reg, result); | 1217 if (divisor < 0) __ Subu(result, zero_reg, result); |
| 1221 | 1218 |
| 1222 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) { | 1219 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) { |
| 1223 __ Dmul(scratch0(), result, Operand(divisor)); | 1220 __ Dmul(scratch0(), result, Operand(divisor)); |
| 1224 __ Dsubu(scratch0(), scratch0(), dividend); | 1221 __ Dsubu(scratch0(), scratch0(), dividend); |
| 1225 DeoptimizeIf(ne, instr->environment(), scratch0(), Operand(zero_reg)); | 1222 DeoptimizeIf(ne, instr, scratch0(), Operand(zero_reg)); |
| 1226 } | 1223 } |
| 1227 } | 1224 } |
| 1228 | 1225 |
| 1229 | 1226 |
| 1230 // TODO(svenpanne) Refactor this to avoid code duplication with DoFlooringDivI. | 1227 // TODO(svenpanne) Refactor this to avoid code duplication with DoFlooringDivI. |
| 1231 void LCodeGen::DoDivI(LDivI* instr) { | 1228 void LCodeGen::DoDivI(LDivI* instr) { |
| 1232 HBinaryOperation* hdiv = instr->hydrogen(); | 1229 HBinaryOperation* hdiv = instr->hydrogen(); |
| 1233 Register dividend = ToRegister(instr->dividend()); | 1230 Register dividend = ToRegister(instr->dividend()); |
| 1234 Register divisor = ToRegister(instr->divisor()); | 1231 Register divisor = ToRegister(instr->divisor()); |
| 1235 const Register result = ToRegister(instr->result()); | 1232 const Register result = ToRegister(instr->result()); |
| 1236 | 1233 |
| 1237 // On MIPS div is asynchronous - it will run in the background while we | 1234 // On MIPS div is asynchronous - it will run in the background while we |
| 1238 // check for special cases. | 1235 // check for special cases. |
| 1239 __ Ddiv(result, dividend, divisor); | 1236 __ Ddiv(result, dividend, divisor); |
| 1240 | 1237 |
| 1241 // Check for x / 0. | 1238 // Check for x / 0. |
| 1242 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { | 1239 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { |
| 1243 DeoptimizeIf(eq, instr->environment(), divisor, Operand(zero_reg)); | 1240 DeoptimizeIf(eq, instr, divisor, Operand(zero_reg)); |
| 1244 } | 1241 } |
| 1245 | 1242 |
| 1246 // Check for (0 / -x) that will produce negative zero. | 1243 // Check for (0 / -x) that will produce negative zero. |
| 1247 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1244 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1248 Label left_not_zero; | 1245 Label left_not_zero; |
| 1249 __ Branch(&left_not_zero, ne, dividend, Operand(zero_reg)); | 1246 __ Branch(&left_not_zero, ne, dividend, Operand(zero_reg)); |
| 1250 DeoptimizeIf(lt, instr->environment(), divisor, Operand(zero_reg)); | 1247 DeoptimizeIf(lt, instr, divisor, Operand(zero_reg)); |
| 1251 __ bind(&left_not_zero); | 1248 __ bind(&left_not_zero); |
| 1252 } | 1249 } |
| 1253 | 1250 |
| 1254 // Check for (kMinInt / -1). | 1251 // Check for (kMinInt / -1). |
| 1255 if (hdiv->CheckFlag(HValue::kCanOverflow) && | 1252 if (hdiv->CheckFlag(HValue::kCanOverflow) && |
| 1256 !hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { | 1253 !hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { |
| 1257 Label left_not_min_int; | 1254 Label left_not_min_int; |
| 1258 __ Branch(&left_not_min_int, ne, dividend, Operand(kMinInt)); | 1255 __ Branch(&left_not_min_int, ne, dividend, Operand(kMinInt)); |
| 1259 DeoptimizeIf(eq, instr->environment(), divisor, Operand(-1)); | 1256 DeoptimizeIf(eq, instr, divisor, Operand(-1)); |
| 1260 __ bind(&left_not_min_int); | 1257 __ bind(&left_not_min_int); |
| 1261 } | 1258 } |
| 1262 | 1259 |
| 1263 if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { | 1260 if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { |
| 1264 // Calculate remainder. | 1261 // Calculate remainder. |
| 1265 Register remainder = ToRegister(instr->temp()); | 1262 Register remainder = ToRegister(instr->temp()); |
| 1266 if (kArchVariant != kMips64r6) { | 1263 if (kArchVariant != kMips64r6) { |
| 1267 __ mfhi(remainder); | 1264 __ mfhi(remainder); |
| 1268 } else { | 1265 } else { |
| 1269 __ dmod(remainder, dividend, divisor); | 1266 __ dmod(remainder, dividend, divisor); |
| 1270 } | 1267 } |
| 1271 DeoptimizeIf(ne, instr->environment(), remainder, Operand(zero_reg)); | 1268 DeoptimizeIf(ne, instr, remainder, Operand(zero_reg)); |
| 1272 } | 1269 } |
| 1273 } | 1270 } |
| 1274 | 1271 |
| 1275 | 1272 |
| 1276 void LCodeGen::DoMultiplyAddD(LMultiplyAddD* instr) { | 1273 void LCodeGen::DoMultiplyAddD(LMultiplyAddD* instr) { |
| 1277 DoubleRegister addend = ToDoubleRegister(instr->addend()); | 1274 DoubleRegister addend = ToDoubleRegister(instr->addend()); |
| 1278 DoubleRegister multiplier = ToDoubleRegister(instr->multiplier()); | 1275 DoubleRegister multiplier = ToDoubleRegister(instr->multiplier()); |
| 1279 DoubleRegister multiplicand = ToDoubleRegister(instr->multiplicand()); | 1276 DoubleRegister multiplicand = ToDoubleRegister(instr->multiplicand()); |
| 1280 | 1277 |
| 1281 // This is computed in-place. | 1278 // This is computed in-place. |
| (...skipping 24 matching lines...) Expand all Loading... |
| 1306 return; | 1303 return; |
| 1307 } | 1304 } |
| 1308 | 1305 |
| 1309 // If the divisor is negative, we have to negate and handle edge cases. | 1306 // If the divisor is negative, we have to negate and handle edge cases. |
| 1310 // Dividend can be the same register as result so save the value of it | 1307 // Dividend can be the same register as result so save the value of it |
| 1311 // for checking overflow. | 1308 // for checking overflow. |
| 1312 __ Move(scratch, dividend); | 1309 __ Move(scratch, dividend); |
| 1313 | 1310 |
| 1314 __ Dsubu(result, zero_reg, dividend); | 1311 __ Dsubu(result, zero_reg, dividend); |
| 1315 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1312 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1316 DeoptimizeIf(eq, instr->environment(), result, Operand(zero_reg)); | 1313 DeoptimizeIf(eq, instr, result, Operand(zero_reg)); |
| 1317 } | 1314 } |
| 1318 | 1315 |
| 1319 __ Xor(scratch, scratch, result); | 1316 __ Xor(scratch, scratch, result); |
| 1320 // Dividing by -1 is basically negation, unless we overflow. | 1317 // Dividing by -1 is basically negation, unless we overflow. |
| 1321 if (divisor == -1) { | 1318 if (divisor == -1) { |
| 1322 if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { | 1319 if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { |
| 1323 DeoptimizeIf(gt, instr->environment(), result, Operand(kMaxInt)); | 1320 DeoptimizeIf(gt, instr, result, Operand(kMaxInt)); |
| 1324 } | 1321 } |
| 1325 return; | 1322 return; |
| 1326 } | 1323 } |
| 1327 | 1324 |
| 1328 // If the negation could not overflow, simply shifting is OK. | 1325 // If the negation could not overflow, simply shifting is OK. |
| 1329 if (!instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { | 1326 if (!instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { |
| 1330 __ dsra(result, result, shift); | 1327 __ dsra(result, result, shift); |
| 1331 return; | 1328 return; |
| 1332 } | 1329 } |
| 1333 | 1330 |
| 1334 Label no_overflow, done; | 1331 Label no_overflow, done; |
| 1335 __ Branch(&no_overflow, lt, scratch, Operand(zero_reg)); | 1332 __ Branch(&no_overflow, lt, scratch, Operand(zero_reg)); |
| 1336 __ li(result, Operand(kMinInt / divisor), CONSTANT_SIZE); | 1333 __ li(result, Operand(kMinInt / divisor), CONSTANT_SIZE); |
| 1337 __ Branch(&done); | 1334 __ Branch(&done); |
| 1338 __ bind(&no_overflow); | 1335 __ bind(&no_overflow); |
| 1339 __ dsra(result, result, shift); | 1336 __ dsra(result, result, shift); |
| 1340 __ bind(&done); | 1337 __ bind(&done); |
| 1341 } | 1338 } |
| 1342 | 1339 |
| 1343 | 1340 |
| 1344 void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) { | 1341 void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) { |
| 1345 Register dividend = ToRegister(instr->dividend()); | 1342 Register dividend = ToRegister(instr->dividend()); |
| 1346 int32_t divisor = instr->divisor(); | 1343 int32_t divisor = instr->divisor(); |
| 1347 Register result = ToRegister(instr->result()); | 1344 Register result = ToRegister(instr->result()); |
| 1348 DCHECK(!dividend.is(result)); | 1345 DCHECK(!dividend.is(result)); |
| 1349 | 1346 |
| 1350 if (divisor == 0) { | 1347 if (divisor == 0) { |
| 1351 DeoptimizeIf(al, instr->environment()); | 1348 DeoptimizeIf(al, instr); |
| 1352 return; | 1349 return; |
| 1353 } | 1350 } |
| 1354 | 1351 |
| 1355 // Check for (0 / -x) that will produce negative zero. | 1352 // Check for (0 / -x) that will produce negative zero. |
| 1356 HMathFloorOfDiv* hdiv = instr->hydrogen(); | 1353 HMathFloorOfDiv* hdiv = instr->hydrogen(); |
| 1357 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { | 1354 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { |
| 1358 DeoptimizeIf(eq, instr->environment(), dividend, Operand(zero_reg)); | 1355 DeoptimizeIf(eq, instr, dividend, Operand(zero_reg)); |
| 1359 } | 1356 } |
| 1360 | 1357 |
| 1361 // Easy case: We need no dynamic check for the dividend and the flooring | 1358 // Easy case: We need no dynamic check for the dividend and the flooring |
| 1362 // division is the same as the truncating division. | 1359 // division is the same as the truncating division. |
| 1363 if ((divisor > 0 && !hdiv->CheckFlag(HValue::kLeftCanBeNegative)) || | 1360 if ((divisor > 0 && !hdiv->CheckFlag(HValue::kLeftCanBeNegative)) || |
| 1364 (divisor < 0 && !hdiv->CheckFlag(HValue::kLeftCanBePositive))) { | 1361 (divisor < 0 && !hdiv->CheckFlag(HValue::kLeftCanBePositive))) { |
| 1365 __ TruncatingDiv(result, dividend, Abs(divisor)); | 1362 __ TruncatingDiv(result, dividend, Abs(divisor)); |
| 1366 if (divisor < 0) __ Dsubu(result, zero_reg, result); | 1363 if (divisor < 0) __ Dsubu(result, zero_reg, result); |
| 1367 return; | 1364 return; |
| 1368 } | 1365 } |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1392 Register dividend = ToRegister(instr->dividend()); | 1389 Register dividend = ToRegister(instr->dividend()); |
| 1393 Register divisor = ToRegister(instr->divisor()); | 1390 Register divisor = ToRegister(instr->divisor()); |
| 1394 const Register result = ToRegister(instr->result()); | 1391 const Register result = ToRegister(instr->result()); |
| 1395 | 1392 |
| 1396 // On MIPS div is asynchronous - it will run in the background while we | 1393 // On MIPS div is asynchronous - it will run in the background while we |
| 1397 // check for special cases. | 1394 // check for special cases. |
| 1398 __ Ddiv(result, dividend, divisor); | 1395 __ Ddiv(result, dividend, divisor); |
| 1399 | 1396 |
| 1400 // Check for x / 0. | 1397 // Check for x / 0. |
| 1401 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { | 1398 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { |
| 1402 DeoptimizeIf(eq, instr->environment(), divisor, Operand(zero_reg)); | 1399 DeoptimizeIf(eq, instr, divisor, Operand(zero_reg)); |
| 1403 } | 1400 } |
| 1404 | 1401 |
| 1405 // Check for (0 / -x) that will produce negative zero. | 1402 // Check for (0 / -x) that will produce negative zero. |
| 1406 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1403 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 1407 Label left_not_zero; | 1404 Label left_not_zero; |
| 1408 __ Branch(&left_not_zero, ne, dividend, Operand(zero_reg)); | 1405 __ Branch(&left_not_zero, ne, dividend, Operand(zero_reg)); |
| 1409 DeoptimizeIf(lt, instr->environment(), divisor, Operand(zero_reg)); | 1406 DeoptimizeIf(lt, instr, divisor, Operand(zero_reg)); |
| 1410 __ bind(&left_not_zero); | 1407 __ bind(&left_not_zero); |
| 1411 } | 1408 } |
| 1412 | 1409 |
| 1413 // Check for (kMinInt / -1). | 1410 // Check for (kMinInt / -1). |
| 1414 if (hdiv->CheckFlag(HValue::kCanOverflow) && | 1411 if (hdiv->CheckFlag(HValue::kCanOverflow) && |
| 1415 !hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { | 1412 !hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { |
| 1416 Label left_not_min_int; | 1413 Label left_not_min_int; |
| 1417 __ Branch(&left_not_min_int, ne, dividend, Operand(kMinInt)); | 1414 __ Branch(&left_not_min_int, ne, dividend, Operand(kMinInt)); |
| 1418 DeoptimizeIf(eq, instr->environment(), divisor, Operand(-1)); | 1415 DeoptimizeIf(eq, instr, divisor, Operand(-1)); |
| 1419 __ bind(&left_not_min_int); | 1416 __ bind(&left_not_min_int); |
| 1420 } | 1417 } |
| 1421 | 1418 |
| 1422 // We performed a truncating division. Correct the result if necessary. | 1419 // We performed a truncating division. Correct the result if necessary. |
| 1423 Label done; | 1420 Label done; |
| 1424 Register remainder = scratch0(); | 1421 Register remainder = scratch0(); |
| 1425 if (kArchVariant != kMips64r6) { | 1422 if (kArchVariant != kMips64r6) { |
| 1426 __ mfhi(remainder); | 1423 __ mfhi(remainder); |
| 1427 } else { | 1424 } else { |
| 1428 __ dmod(remainder, dividend, divisor); | 1425 __ dmod(remainder, dividend, divisor); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1445 bool bailout_on_minus_zero = | 1442 bool bailout_on_minus_zero = |
| 1446 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero); | 1443 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero); |
| 1447 bool overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); | 1444 bool overflow = instr->hydrogen()->CheckFlag(HValue::kCanOverflow); |
| 1448 | 1445 |
| 1449 if (right_op->IsConstantOperand()) { | 1446 if (right_op->IsConstantOperand()) { |
| 1450 int32_t constant = ToInteger32(LConstantOperand::cast(right_op)); | 1447 int32_t constant = ToInteger32(LConstantOperand::cast(right_op)); |
| 1451 | 1448 |
| 1452 if (bailout_on_minus_zero && (constant < 0)) { | 1449 if (bailout_on_minus_zero && (constant < 0)) { |
| 1453 // The case of a null constant will be handled separately. | 1450 // The case of a null constant will be handled separately. |
| 1454 // If constant is negative and left is null, the result should be -0. | 1451 // If constant is negative and left is null, the result should be -0. |
| 1455 DeoptimizeIf(eq, instr->environment(), left, Operand(zero_reg)); | 1452 DeoptimizeIf(eq, instr, left, Operand(zero_reg)); |
| 1456 } | 1453 } |
| 1457 | 1454 |
| 1458 switch (constant) { | 1455 switch (constant) { |
| 1459 case -1: | 1456 case -1: |
| 1460 if (overflow) { | 1457 if (overflow) { |
| 1461 __ SubuAndCheckForOverflow(result, zero_reg, left, scratch); | 1458 __ SubuAndCheckForOverflow(result, zero_reg, left, scratch); |
| 1462 DeoptimizeIf(gt, instr->environment(), scratch, Operand(kMaxInt)); | 1459 DeoptimizeIf(gt, instr, scratch, Operand(kMaxInt)); |
| 1463 } else { | 1460 } else { |
| 1464 __ Dsubu(result, zero_reg, left); | 1461 __ Dsubu(result, zero_reg, left); |
| 1465 } | 1462 } |
| 1466 break; | 1463 break; |
| 1467 case 0: | 1464 case 0: |
| 1468 if (bailout_on_minus_zero) { | 1465 if (bailout_on_minus_zero) { |
| 1469 // If left is strictly negative and the constant is null, the | 1466 // If left is strictly negative and the constant is null, the |
| 1470 // result is -0. Deoptimize if required, otherwise return 0. | 1467 // result is -0. Deoptimize if required, otherwise return 0. |
| 1471 DeoptimizeIf(lt, instr->environment(), left, Operand(zero_reg)); | 1468 DeoptimizeIf(lt, instr, left, Operand(zero_reg)); |
| 1472 } | 1469 } |
| 1473 __ mov(result, zero_reg); | 1470 __ mov(result, zero_reg); |
| 1474 break; | 1471 break; |
| 1475 case 1: | 1472 case 1: |
| 1476 // Nothing to do. | 1473 // Nothing to do. |
| 1477 __ Move(result, left); | 1474 __ Move(result, left); |
| 1478 break; | 1475 break; |
| 1479 default: | 1476 default: |
| 1480 // Multiplying by powers of two and powers of two plus or minus | 1477 // Multiplying by powers of two and powers of two plus or minus |
| 1481 // one can be done faster with shifted operands. | 1478 // one can be done faster with shifted operands. |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1516 if (instr->hydrogen()->representation().IsSmi()) { | 1513 if (instr->hydrogen()->representation().IsSmi()) { |
| 1517 __ Dmulh(result, left, right); | 1514 __ Dmulh(result, left, right); |
| 1518 } else { | 1515 } else { |
| 1519 __ Dmul(result, left, right); | 1516 __ Dmul(result, left, right); |
| 1520 } | 1517 } |
| 1521 __ dsra32(scratch, result, 0); | 1518 __ dsra32(scratch, result, 0); |
| 1522 __ sra(at, result, 31); | 1519 __ sra(at, result, 31); |
| 1523 if (instr->hydrogen()->representation().IsSmi()) { | 1520 if (instr->hydrogen()->representation().IsSmi()) { |
| 1524 __ SmiTag(result); | 1521 __ SmiTag(result); |
| 1525 } | 1522 } |
| 1526 DeoptimizeIf(ne, instr->environment(), scratch, Operand(at)); | 1523 DeoptimizeIf(ne, instr, scratch, Operand(at)); |
| 1527 } else { | 1524 } else { |
| 1528 if (instr->hydrogen()->representation().IsSmi()) { | 1525 if (instr->hydrogen()->representation().IsSmi()) { |
| 1529 __ SmiUntag(result, left); | 1526 __ SmiUntag(result, left); |
| 1530 __ Dmul(result, result, right); | 1527 __ Dmul(result, result, right); |
| 1531 } else { | 1528 } else { |
| 1532 __ Dmul(result, left, right); | 1529 __ Dmul(result, left, right); |
| 1533 } | 1530 } |
| 1534 } | 1531 } |
| 1535 | 1532 |
| 1536 if (bailout_on_minus_zero) { | 1533 if (bailout_on_minus_zero) { |
| 1537 Label done; | 1534 Label done; |
| 1538 __ Xor(at, left, right); | 1535 __ Xor(at, left, right); |
| 1539 __ Branch(&done, ge, at, Operand(zero_reg)); | 1536 __ Branch(&done, ge, at, Operand(zero_reg)); |
| 1540 // Bail out if the result is minus zero. | 1537 // Bail out if the result is minus zero. |
| 1541 DeoptimizeIf(eq, | 1538 DeoptimizeIf(eq, instr, result, Operand(zero_reg)); |
| 1542 instr->environment(), | |
| 1543 result, | |
| 1544 Operand(zero_reg)); | |
| 1545 __ bind(&done); | 1539 __ bind(&done); |
| 1546 } | 1540 } |
| 1547 } | 1541 } |
| 1548 } | 1542 } |
| 1549 | 1543 |
| 1550 | 1544 |
| 1551 void LCodeGen::DoBitI(LBitI* instr) { | 1545 void LCodeGen::DoBitI(LBitI* instr) { |
| 1552 LOperand* left_op = instr->left(); | 1546 LOperand* left_op = instr->left(); |
| 1553 LOperand* right_op = instr->right(); | 1547 LOperand* right_op = instr->right(); |
| 1554 DCHECK(left_op->IsRegister()); | 1548 DCHECK(left_op->IsRegister()); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1598 case Token::ROR: | 1592 case Token::ROR: |
| 1599 __ Ror(result, left, Operand(ToRegister(right_op))); | 1593 __ Ror(result, left, Operand(ToRegister(right_op))); |
| 1600 break; | 1594 break; |
| 1601 case Token::SAR: | 1595 case Token::SAR: |
| 1602 __ srav(result, left, ToRegister(right_op)); | 1596 __ srav(result, left, ToRegister(right_op)); |
| 1603 break; | 1597 break; |
| 1604 case Token::SHR: | 1598 case Token::SHR: |
| 1605 __ srlv(result, left, ToRegister(right_op)); | 1599 __ srlv(result, left, ToRegister(right_op)); |
| 1606 if (instr->can_deopt()) { | 1600 if (instr->can_deopt()) { |
| 1607 // TODO(yy): (-1) >>> 0. anything else? | 1601 // TODO(yy): (-1) >>> 0. anything else? |
| 1608 DeoptimizeIf(lt, instr->environment(), result, Operand(zero_reg)); | 1602 DeoptimizeIf(lt, instr, result, Operand(zero_reg)); |
| 1609 DeoptimizeIf(gt, instr->environment(), result, Operand(kMaxInt)); | 1603 DeoptimizeIf(gt, instr, result, Operand(kMaxInt)); |
| 1610 } | 1604 } |
| 1611 break; | 1605 break; |
| 1612 case Token::SHL: | 1606 case Token::SHL: |
| 1613 __ sllv(result, left, ToRegister(right_op)); | 1607 __ sllv(result, left, ToRegister(right_op)); |
| 1614 break; | 1608 break; |
| 1615 default: | 1609 default: |
| 1616 UNREACHABLE(); | 1610 UNREACHABLE(); |
| 1617 break; | 1611 break; |
| 1618 } | 1612 } |
| 1619 } else { | 1613 } else { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1634 } else { | 1628 } else { |
| 1635 __ Move(result, left); | 1629 __ Move(result, left); |
| 1636 } | 1630 } |
| 1637 break; | 1631 break; |
| 1638 case Token::SHR: | 1632 case Token::SHR: |
| 1639 if (shift_count != 0) { | 1633 if (shift_count != 0) { |
| 1640 __ srl(result, left, shift_count); | 1634 __ srl(result, left, shift_count); |
| 1641 } else { | 1635 } else { |
| 1642 if (instr->can_deopt()) { | 1636 if (instr->can_deopt()) { |
| 1643 __ And(at, left, Operand(0x80000000)); | 1637 __ And(at, left, Operand(0x80000000)); |
| 1644 DeoptimizeIf(ne, instr->environment(), at, Operand(zero_reg)); | 1638 DeoptimizeIf(ne, instr, at, Operand(zero_reg)); |
| 1645 } | 1639 } |
| 1646 __ Move(result, left); | 1640 __ Move(result, left); |
| 1647 } | 1641 } |
| 1648 break; | 1642 break; |
| 1649 case Token::SHL: | 1643 case Token::SHL: |
| 1650 if (shift_count != 0) { | 1644 if (shift_count != 0) { |
| 1651 if (instr->hydrogen_value()->representation().IsSmi()) { | 1645 if (instr->hydrogen_value()->representation().IsSmi()) { |
| 1652 __ dsll(result, left, shift_count); | 1646 __ dsll(result, left, shift_count); |
| 1653 } else { | 1647 } else { |
| 1654 __ sll(result, left, shift_count); | 1648 __ sll(result, left, shift_count); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1690 overflow); // Reg at also used as scratch. | 1684 overflow); // Reg at also used as scratch. |
| 1691 } else { | 1685 } else { |
| 1692 DCHECK(right->IsRegister()); | 1686 DCHECK(right->IsRegister()); |
| 1693 // Due to overflow check macros not supporting constant operands, | 1687 // Due to overflow check macros not supporting constant operands, |
| 1694 // handling the IsConstantOperand case was moved to prev if clause. | 1688 // handling the IsConstantOperand case was moved to prev if clause. |
| 1695 __ SubuAndCheckForOverflow(ToRegister(result), | 1689 __ SubuAndCheckForOverflow(ToRegister(result), |
| 1696 ToRegister(left), | 1690 ToRegister(left), |
| 1697 ToRegister(right), | 1691 ToRegister(right), |
| 1698 overflow); // Reg at also used as scratch. | 1692 overflow); // Reg at also used as scratch. |
| 1699 } | 1693 } |
| 1700 DeoptimizeIf(lt, instr->environment(), overflow, Operand(zero_reg)); | 1694 DeoptimizeIf(lt, instr, overflow, Operand(zero_reg)); |
| 1701 if (!instr->hydrogen()->representation().IsSmi()) { | 1695 if (!instr->hydrogen()->representation().IsSmi()) { |
| 1702 DeoptimizeIf(gt, instr->environment(), | 1696 DeoptimizeIf(gt, instr, ToRegister(result), Operand(kMaxInt)); |
| 1703 ToRegister(result), Operand(kMaxInt)); | 1697 DeoptimizeIf(lt, instr, ToRegister(result), Operand(kMinInt)); |
| 1704 DeoptimizeIf(lt, instr->environment(), | |
| 1705 ToRegister(result), Operand(kMinInt)); | |
| 1706 } | 1698 } |
| 1707 } | 1699 } |
| 1708 } | 1700 } |
| 1709 | 1701 |
| 1710 | 1702 |
| 1711 void LCodeGen::DoConstantI(LConstantI* instr) { | 1703 void LCodeGen::DoConstantI(LConstantI* instr) { |
| 1712 __ li(ToRegister(instr->result()), Operand(instr->value())); | 1704 __ li(ToRegister(instr->result()), Operand(instr->value())); |
| 1713 } | 1705 } |
| 1714 | 1706 |
| 1715 | 1707 |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1750 Register result = ToRegister(instr->result()); | 1742 Register result = ToRegister(instr->result()); |
| 1751 Register scratch = ToRegister(instr->temp()); | 1743 Register scratch = ToRegister(instr->temp()); |
| 1752 Smi* index = instr->index(); | 1744 Smi* index = instr->index(); |
| 1753 Label runtime, done; | 1745 Label runtime, done; |
| 1754 DCHECK(object.is(a0)); | 1746 DCHECK(object.is(a0)); |
| 1755 DCHECK(result.is(v0)); | 1747 DCHECK(result.is(v0)); |
| 1756 DCHECK(!scratch.is(scratch0())); | 1748 DCHECK(!scratch.is(scratch0())); |
| 1757 DCHECK(!scratch.is(object)); | 1749 DCHECK(!scratch.is(object)); |
| 1758 | 1750 |
| 1759 __ SmiTst(object, at); | 1751 __ SmiTst(object, at); |
| 1760 DeoptimizeIf(eq, instr->environment(), at, Operand(zero_reg)); | 1752 DeoptimizeIf(eq, instr, at, Operand(zero_reg)); |
| 1761 __ GetObjectType(object, scratch, scratch); | 1753 __ GetObjectType(object, scratch, scratch); |
| 1762 DeoptimizeIf(ne, instr->environment(), scratch, Operand(JS_DATE_TYPE)); | 1754 DeoptimizeIf(ne, instr, scratch, Operand(JS_DATE_TYPE)); |
| 1763 | 1755 |
| 1764 if (index->value() == 0) { | 1756 if (index->value() == 0) { |
| 1765 __ ld(result, FieldMemOperand(object, JSDate::kValueOffset)); | 1757 __ ld(result, FieldMemOperand(object, JSDate::kValueOffset)); |
| 1766 } else { | 1758 } else { |
| 1767 if (index->value() < JSDate::kFirstUncachedField) { | 1759 if (index->value() < JSDate::kFirstUncachedField) { |
| 1768 ExternalReference stamp = ExternalReference::date_cache_stamp(isolate()); | 1760 ExternalReference stamp = ExternalReference::date_cache_stamp(isolate()); |
| 1769 __ li(scratch, Operand(stamp)); | 1761 __ li(scratch, Operand(stamp)); |
| 1770 __ ld(scratch, MemOperand(scratch)); | 1762 __ ld(scratch, MemOperand(scratch)); |
| 1771 __ ld(scratch0(), FieldMemOperand(object, JSDate::kCacheStampOffset)); | 1763 __ ld(scratch0(), FieldMemOperand(object, JSDate::kCacheStampOffset)); |
| 1772 __ Branch(&runtime, ne, scratch, Operand(scratch0())); | 1764 __ Branch(&runtime, ne, scratch, Operand(scratch0())); |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1887 overflow); // Reg at also used as scratch. | 1879 overflow); // Reg at also used as scratch. |
| 1888 } else { | 1880 } else { |
| 1889 DCHECK(right->IsRegister()); | 1881 DCHECK(right->IsRegister()); |
| 1890 // Due to overflow check macros not supporting constant operands, | 1882 // Due to overflow check macros not supporting constant operands, |
| 1891 // handling the IsConstantOperand case was moved to prev if clause. | 1883 // handling the IsConstantOperand case was moved to prev if clause. |
| 1892 __ AdduAndCheckForOverflow(ToRegister(result), | 1884 __ AdduAndCheckForOverflow(ToRegister(result), |
| 1893 ToRegister(left), | 1885 ToRegister(left), |
| 1894 ToRegister(right), | 1886 ToRegister(right), |
| 1895 overflow); // Reg at also used as scratch. | 1887 overflow); // Reg at also used as scratch. |
| 1896 } | 1888 } |
| 1897 DeoptimizeIf(lt, instr->environment(), overflow, Operand(zero_reg)); | 1889 DeoptimizeIf(lt, instr, overflow, Operand(zero_reg)); |
| 1898 // if not smi, it must int32. | 1890 // if not smi, it must int32. |
| 1899 if (!instr->hydrogen()->representation().IsSmi()) { | 1891 if (!instr->hydrogen()->representation().IsSmi()) { |
| 1900 DeoptimizeIf(gt, instr->environment(), | 1892 DeoptimizeIf(gt, instr, ToRegister(result), Operand(kMaxInt)); |
| 1901 ToRegister(result), Operand(kMaxInt)); | 1893 DeoptimizeIf(lt, instr, ToRegister(result), Operand(kMinInt)); |
| 1902 DeoptimizeIf(lt, instr->environment(), | |
| 1903 ToRegister(result), Operand(kMinInt)); | |
| 1904 } | 1894 } |
| 1905 } | 1895 } |
| 1906 } | 1896 } |
| 1907 | 1897 |
| 1908 | 1898 |
| 1909 void LCodeGen::DoMathMinMax(LMathMinMax* instr) { | 1899 void LCodeGen::DoMathMinMax(LMathMinMax* instr) { |
| 1910 LOperand* left = instr->left(); | 1900 LOperand* left = instr->left(); |
| 1911 LOperand* right = instr->right(); | 1901 LOperand* right = instr->right(); |
| 1912 HMathMinMax::Operation operation = instr->hydrogen()->operation(); | 1902 HMathMinMax::Operation operation = instr->hydrogen()->operation(); |
| 1913 Condition condition = (operation == HMathMinMax::kMathMin) ? le : ge; | 1903 Condition condition = (operation == HMathMinMax::kMathMin) ? le : ge; |
| (...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2155 __ Branch(instr->FalseLabel(chunk_), eq, reg, Operand(at)); | 2145 __ Branch(instr->FalseLabel(chunk_), eq, reg, Operand(at)); |
| 2156 } | 2146 } |
| 2157 | 2147 |
| 2158 if (expected.Contains(ToBooleanStub::SMI)) { | 2148 if (expected.Contains(ToBooleanStub::SMI)) { |
| 2159 // Smis: 0 -> false, all other -> true. | 2149 // Smis: 0 -> false, all other -> true. |
| 2160 __ Branch(instr->FalseLabel(chunk_), eq, reg, Operand(zero_reg)); | 2150 __ Branch(instr->FalseLabel(chunk_), eq, reg, Operand(zero_reg)); |
| 2161 __ JumpIfSmi(reg, instr->TrueLabel(chunk_)); | 2151 __ JumpIfSmi(reg, instr->TrueLabel(chunk_)); |
| 2162 } else if (expected.NeedsMap()) { | 2152 } else if (expected.NeedsMap()) { |
| 2163 // If we need a map later and have a Smi -> deopt. | 2153 // If we need a map later and have a Smi -> deopt. |
| 2164 __ SmiTst(reg, at); | 2154 __ SmiTst(reg, at); |
| 2165 DeoptimizeIf(eq, instr->environment(), at, Operand(zero_reg)); | 2155 DeoptimizeIf(eq, instr, at, Operand(zero_reg)); |
| 2166 } | 2156 } |
| 2167 | 2157 |
| 2168 const Register map = scratch0(); | 2158 const Register map = scratch0(); |
| 2169 if (expected.NeedsMap()) { | 2159 if (expected.NeedsMap()) { |
| 2170 __ ld(map, FieldMemOperand(reg, HeapObject::kMapOffset)); | 2160 __ ld(map, FieldMemOperand(reg, HeapObject::kMapOffset)); |
| 2171 if (expected.CanBeUndetectable()) { | 2161 if (expected.CanBeUndetectable()) { |
| 2172 // Undetectable -> false. | 2162 // Undetectable -> false. |
| 2173 __ lbu(at, FieldMemOperand(map, Map::kBitFieldOffset)); | 2163 __ lbu(at, FieldMemOperand(map, Map::kBitFieldOffset)); |
| 2174 __ And(at, at, Operand(1 << Map::kIsUndetectable)); | 2164 __ And(at, at, Operand(1 << Map::kIsUndetectable)); |
| 2175 __ Branch(instr->FalseLabel(chunk_), ne, at, Operand(zero_reg)); | 2165 __ Branch(instr->FalseLabel(chunk_), ne, at, Operand(zero_reg)); |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2211 __ BranchF(instr->TrueLabel(chunk_), instr->FalseLabel(chunk_), | 2201 __ BranchF(instr->TrueLabel(chunk_), instr->FalseLabel(chunk_), |
| 2212 ne, dbl_scratch, kDoubleRegZero); | 2202 ne, dbl_scratch, kDoubleRegZero); |
| 2213 // Falls through if dbl_scratch == 0. | 2203 // Falls through if dbl_scratch == 0. |
| 2214 __ Branch(instr->FalseLabel(chunk_)); | 2204 __ Branch(instr->FalseLabel(chunk_)); |
| 2215 __ bind(¬_heap_number); | 2205 __ bind(¬_heap_number); |
| 2216 } | 2206 } |
| 2217 | 2207 |
| 2218 if (!expected.IsGeneric()) { | 2208 if (!expected.IsGeneric()) { |
| 2219 // We've seen something for the first time -> deopt. | 2209 // We've seen something for the first time -> deopt. |
| 2220 // This can only happen if we are not generic already. | 2210 // This can only happen if we are not generic already. |
| 2221 DeoptimizeIf(al, instr->environment(), zero_reg, Operand(zero_reg)); | 2211 DeoptimizeIf(al, instr, zero_reg, Operand(zero_reg)); |
| 2222 } | 2212 } |
| 2223 } | 2213 } |
| 2224 } | 2214 } |
| 2225 } | 2215 } |
| 2226 | 2216 |
| 2227 | 2217 |
| 2228 void LCodeGen::EmitGoto(int block) { | 2218 void LCodeGen::EmitGoto(int block) { |
| 2229 if (!IsNextEmittedBlock(block)) { | 2219 if (!IsNextEmittedBlock(block)) { |
| 2230 __ jmp(chunk_->GetAssemblyLabel(LookupDestination(block))); | 2220 __ jmp(chunk_->GetAssemblyLabel(LookupDestination(block))); |
| 2231 } | 2221 } |
| (...skipping 625 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2857 } | 2847 } |
| 2858 } | 2848 } |
| 2859 | 2849 |
| 2860 | 2850 |
| 2861 void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) { | 2851 void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) { |
| 2862 Register result = ToRegister(instr->result()); | 2852 Register result = ToRegister(instr->result()); |
| 2863 __ li(at, Operand(Handle<Object>(instr->hydrogen()->cell().handle()))); | 2853 __ li(at, Operand(Handle<Object>(instr->hydrogen()->cell().handle()))); |
| 2864 __ ld(result, FieldMemOperand(at, Cell::kValueOffset)); | 2854 __ ld(result, FieldMemOperand(at, Cell::kValueOffset)); |
| 2865 if (instr->hydrogen()->RequiresHoleCheck()) { | 2855 if (instr->hydrogen()->RequiresHoleCheck()) { |
| 2866 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | 2856 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
| 2867 DeoptimizeIf(eq, instr->environment(), result, Operand(at)); | 2857 DeoptimizeIf(eq, instr, result, Operand(at)); |
| 2868 } | 2858 } |
| 2869 } | 2859 } |
| 2870 | 2860 |
| 2871 | 2861 |
| 2872 template <class T> | 2862 template <class T> |
| 2873 void LCodeGen::EmitVectorLoadICRegisters(T* instr) { | 2863 void LCodeGen::EmitVectorLoadICRegisters(T* instr) { |
| 2874 DCHECK(FLAG_vector_ics); | 2864 DCHECK(FLAG_vector_ics); |
| 2875 Register vector = ToRegister(instr->temp_vector()); | 2865 Register vector = ToRegister(instr->temp_vector()); |
| 2876 DCHECK(vector.is(VectorLoadICDescriptor::VectorRegister())); | 2866 DCHECK(vector.is(VectorLoadICDescriptor::VectorRegister())); |
| 2877 __ li(vector, instr->hydrogen()->feedback_vector()); | 2867 __ li(vector, instr->hydrogen()->feedback_vector()); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 2907 | 2897 |
| 2908 // If the cell we are storing to contains the hole it could have | 2898 // If the cell we are storing to contains the hole it could have |
| 2909 // been deleted from the property dictionary. In that case, we need | 2899 // been deleted from the property dictionary. In that case, we need |
| 2910 // to update the property details in the property dictionary to mark | 2900 // to update the property details in the property dictionary to mark |
| 2911 // it as no longer deleted. | 2901 // it as no longer deleted. |
| 2912 if (instr->hydrogen()->RequiresHoleCheck()) { | 2902 if (instr->hydrogen()->RequiresHoleCheck()) { |
| 2913 // We use a temp to check the payload. | 2903 // We use a temp to check the payload. |
| 2914 Register payload = ToRegister(instr->temp()); | 2904 Register payload = ToRegister(instr->temp()); |
| 2915 __ ld(payload, FieldMemOperand(cell, Cell::kValueOffset)); | 2905 __ ld(payload, FieldMemOperand(cell, Cell::kValueOffset)); |
| 2916 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | 2906 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
| 2917 DeoptimizeIf(eq, instr->environment(), payload, Operand(at)); | 2907 DeoptimizeIf(eq, instr, payload, Operand(at)); |
| 2918 } | 2908 } |
| 2919 | 2909 |
| 2920 // Store the value. | 2910 // Store the value. |
| 2921 __ sd(value, FieldMemOperand(cell, Cell::kValueOffset)); | 2911 __ sd(value, FieldMemOperand(cell, Cell::kValueOffset)); |
| 2922 // Cells are always rescanned, so no write barrier here. | 2912 // Cells are always rescanned, so no write barrier here. |
| 2923 } | 2913 } |
| 2924 | 2914 |
| 2925 | 2915 |
| 2926 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { | 2916 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { |
| 2927 Register context = ToRegister(instr->context()); | 2917 Register context = ToRegister(instr->context()); |
| 2928 Register result = ToRegister(instr->result()); | 2918 Register result = ToRegister(instr->result()); |
| 2929 | 2919 |
| 2930 __ ld(result, ContextOperand(context, instr->slot_index())); | 2920 __ ld(result, ContextOperand(context, instr->slot_index())); |
| 2931 if (instr->hydrogen()->RequiresHoleCheck()) { | 2921 if (instr->hydrogen()->RequiresHoleCheck()) { |
| 2932 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | 2922 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
| 2933 | 2923 |
| 2934 if (instr->hydrogen()->DeoptimizesOnHole()) { | 2924 if (instr->hydrogen()->DeoptimizesOnHole()) { |
| 2935 DeoptimizeIf(eq, instr->environment(), result, Operand(at)); | 2925 DeoptimizeIf(eq, instr, result, Operand(at)); |
| 2936 } else { | 2926 } else { |
| 2937 Label is_not_hole; | 2927 Label is_not_hole; |
| 2938 __ Branch(&is_not_hole, ne, result, Operand(at)); | 2928 __ Branch(&is_not_hole, ne, result, Operand(at)); |
| 2939 __ LoadRoot(result, Heap::kUndefinedValueRootIndex); | 2929 __ LoadRoot(result, Heap::kUndefinedValueRootIndex); |
| 2940 __ bind(&is_not_hole); | 2930 __ bind(&is_not_hole); |
| 2941 } | 2931 } |
| 2942 } | 2932 } |
| 2943 } | 2933 } |
| 2944 | 2934 |
| 2945 | 2935 |
| 2946 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { | 2936 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { |
| 2947 Register context = ToRegister(instr->context()); | 2937 Register context = ToRegister(instr->context()); |
| 2948 Register value = ToRegister(instr->value()); | 2938 Register value = ToRegister(instr->value()); |
| 2949 Register scratch = scratch0(); | 2939 Register scratch = scratch0(); |
| 2950 MemOperand target = ContextOperand(context, instr->slot_index()); | 2940 MemOperand target = ContextOperand(context, instr->slot_index()); |
| 2951 | 2941 |
| 2952 Label skip_assignment; | 2942 Label skip_assignment; |
| 2953 | 2943 |
| 2954 if (instr->hydrogen()->RequiresHoleCheck()) { | 2944 if (instr->hydrogen()->RequiresHoleCheck()) { |
| 2955 __ ld(scratch, target); | 2945 __ ld(scratch, target); |
| 2956 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | 2946 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
| 2957 | 2947 |
| 2958 if (instr->hydrogen()->DeoptimizesOnHole()) { | 2948 if (instr->hydrogen()->DeoptimizesOnHole()) { |
| 2959 DeoptimizeIf(eq, instr->environment(), scratch, Operand(at)); | 2949 DeoptimizeIf(eq, instr, scratch, Operand(at)); |
| 2960 } else { | 2950 } else { |
| 2961 __ Branch(&skip_assignment, ne, scratch, Operand(at)); | 2951 __ Branch(&skip_assignment, ne, scratch, Operand(at)); |
| 2962 } | 2952 } |
| 2963 } | 2953 } |
| 2964 | 2954 |
| 2965 __ sd(value, target); | 2955 __ sd(value, target); |
| 2966 if (instr->hydrogen()->NeedsWriteBarrier()) { | 2956 if (instr->hydrogen()->NeedsWriteBarrier()) { |
| 2967 SmiCheck check_needed = | 2957 SmiCheck check_needed = |
| 2968 instr->hydrogen()->value()->type().IsHeapObject() | 2958 instr->hydrogen()->value()->type().IsHeapObject() |
| 2969 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; | 2959 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3043 Register scratch = scratch0(); | 3033 Register scratch = scratch0(); |
| 3044 Register function = ToRegister(instr->function()); | 3034 Register function = ToRegister(instr->function()); |
| 3045 Register result = ToRegister(instr->result()); | 3035 Register result = ToRegister(instr->result()); |
| 3046 | 3036 |
| 3047 // Get the prototype or initial map from the function. | 3037 // Get the prototype or initial map from the function. |
| 3048 __ ld(result, | 3038 __ ld(result, |
| 3049 FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); | 3039 FieldMemOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); |
| 3050 | 3040 |
| 3051 // Check that the function has a prototype or an initial map. | 3041 // Check that the function has a prototype or an initial map. |
| 3052 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); | 3042 __ LoadRoot(at, Heap::kTheHoleValueRootIndex); |
| 3053 DeoptimizeIf(eq, instr->environment(), result, Operand(at)); | 3043 DeoptimizeIf(eq, instr, result, Operand(at)); |
| 3054 | 3044 |
| 3055 // If the function does not have an initial map, we're done. | 3045 // If the function does not have an initial map, we're done. |
| 3056 Label done; | 3046 Label done; |
| 3057 __ GetObjectType(result, scratch, scratch); | 3047 __ GetObjectType(result, scratch, scratch); |
| 3058 __ Branch(&done, ne, scratch, Operand(MAP_TYPE)); | 3048 __ Branch(&done, ne, scratch, Operand(MAP_TYPE)); |
| 3059 | 3049 |
| 3060 // Get the prototype from the initial map. | 3050 // Get the prototype from the initial map. |
| 3061 __ ld(result, FieldMemOperand(result, Map::kPrototypeOffset)); | 3051 __ ld(result, FieldMemOperand(result, Map::kPrototypeOffset)); |
| 3062 | 3052 |
| 3063 // All done. | 3053 // All done. |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3189 __ lhu(result, mem_operand); | 3179 __ lhu(result, mem_operand); |
| 3190 break; | 3180 break; |
| 3191 case EXTERNAL_INT32_ELEMENTS: | 3181 case EXTERNAL_INT32_ELEMENTS: |
| 3192 case INT32_ELEMENTS: | 3182 case INT32_ELEMENTS: |
| 3193 __ lw(result, mem_operand); | 3183 __ lw(result, mem_operand); |
| 3194 break; | 3184 break; |
| 3195 case EXTERNAL_UINT32_ELEMENTS: | 3185 case EXTERNAL_UINT32_ELEMENTS: |
| 3196 case UINT32_ELEMENTS: | 3186 case UINT32_ELEMENTS: |
| 3197 __ lw(result, mem_operand); | 3187 __ lw(result, mem_operand); |
| 3198 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) { | 3188 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) { |
| 3199 DeoptimizeIf(Ugreater_equal, instr->environment(), | 3189 DeoptimizeIf(Ugreater_equal, instr, result, Operand(0x80000000)); |
| 3200 result, Operand(0x80000000)); | |
| 3201 } | 3190 } |
| 3202 break; | 3191 break; |
| 3203 case FLOAT32_ELEMENTS: | 3192 case FLOAT32_ELEMENTS: |
| 3204 case FLOAT64_ELEMENTS: | 3193 case FLOAT64_ELEMENTS: |
| 3205 case EXTERNAL_FLOAT32_ELEMENTS: | 3194 case EXTERNAL_FLOAT32_ELEMENTS: |
| 3206 case EXTERNAL_FLOAT64_ELEMENTS: | 3195 case EXTERNAL_FLOAT64_ELEMENTS: |
| 3207 case FAST_DOUBLE_ELEMENTS: | 3196 case FAST_DOUBLE_ELEMENTS: |
| 3208 case FAST_ELEMENTS: | 3197 case FAST_ELEMENTS: |
| 3209 case FAST_SMI_ELEMENTS: | 3198 case FAST_SMI_ELEMENTS: |
| 3210 case FAST_HOLEY_DOUBLE_ELEMENTS: | 3199 case FAST_HOLEY_DOUBLE_ELEMENTS: |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3250 } else { | 3239 } else { |
| 3251 __ dsra(at, key, -shift_size); | 3240 __ dsra(at, key, -shift_size); |
| 3252 } | 3241 } |
| 3253 __ Daddu(scratch, scratch, at); | 3242 __ Daddu(scratch, scratch, at); |
| 3254 } | 3243 } |
| 3255 | 3244 |
| 3256 __ ldc1(result, MemOperand(scratch)); | 3245 __ ldc1(result, MemOperand(scratch)); |
| 3257 | 3246 |
| 3258 if (instr->hydrogen()->RequiresHoleCheck()) { | 3247 if (instr->hydrogen()->RequiresHoleCheck()) { |
| 3259 __ lw(scratch, MemOperand(scratch, sizeof(kHoleNanLower32))); | 3248 __ lw(scratch, MemOperand(scratch, sizeof(kHoleNanLower32))); |
| 3260 DeoptimizeIf(eq, instr->environment(), scratch, Operand(kHoleNanUpper32)); | 3249 DeoptimizeIf(eq, instr, scratch, Operand(kHoleNanUpper32)); |
| 3261 } | 3250 } |
| 3262 } | 3251 } |
| 3263 | 3252 |
| 3264 | 3253 |
| 3265 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { | 3254 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { |
| 3266 HLoadKeyed* hinstr = instr->hydrogen(); | 3255 HLoadKeyed* hinstr = instr->hydrogen(); |
| 3267 Register elements = ToRegister(instr->elements()); | 3256 Register elements = ToRegister(instr->elements()); |
| 3268 Register result = ToRegister(instr->result()); | 3257 Register result = ToRegister(instr->result()); |
| 3269 Register scratch = scratch0(); | 3258 Register scratch = scratch0(); |
| 3270 Register store_base = scratch; | 3259 Register store_base = scratch; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3304 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 32); | 3293 STATIC_ASSERT(kSmiTagSize + kSmiShiftSize == 32); |
| 3305 offset += kPointerSize / 2; | 3294 offset += kPointerSize / 2; |
| 3306 } | 3295 } |
| 3307 | 3296 |
| 3308 __ Load(result, MemOperand(store_base, offset), representation); | 3297 __ Load(result, MemOperand(store_base, offset), representation); |
| 3309 | 3298 |
| 3310 // Check for the hole value. | 3299 // Check for the hole value. |
| 3311 if (hinstr->RequiresHoleCheck()) { | 3300 if (hinstr->RequiresHoleCheck()) { |
| 3312 if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) { | 3301 if (IsFastSmiElementsKind(instr->hydrogen()->elements_kind())) { |
| 3313 __ SmiTst(result, scratch); | 3302 __ SmiTst(result, scratch); |
| 3314 DeoptimizeIf(ne, instr->environment(), scratch, Operand(zero_reg)); | 3303 DeoptimizeIf(ne, instr, scratch, Operand(zero_reg)); |
| 3315 } else { | 3304 } else { |
| 3316 __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex); | 3305 __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex); |
| 3317 DeoptimizeIf(eq, instr->environment(), result, Operand(scratch)); | 3306 DeoptimizeIf(eq, instr, result, Operand(scratch)); |
| 3318 } | 3307 } |
| 3319 } | 3308 } |
| 3320 } | 3309 } |
| 3321 | 3310 |
| 3322 | 3311 |
| 3323 void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) { | 3312 void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) { |
| 3324 if (instr->is_typed_elements()) { | 3313 if (instr->is_typed_elements()) { |
| 3325 DoLoadKeyedExternalArray(instr); | 3314 DoLoadKeyedExternalArray(instr); |
| 3326 } else if (instr->hydrogen()->representation().IsDouble()) { | 3315 } else if (instr->hydrogen()->representation().IsDouble()) { |
| 3327 DoLoadKeyedFixedDoubleArray(instr); | 3316 DoLoadKeyedFixedDoubleArray(instr); |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3463 } | 3452 } |
| 3464 | 3453 |
| 3465 // Normal function. Replace undefined or null with global receiver. | 3454 // Normal function. Replace undefined or null with global receiver. |
| 3466 __ LoadRoot(scratch, Heap::kNullValueRootIndex); | 3455 __ LoadRoot(scratch, Heap::kNullValueRootIndex); |
| 3467 __ Branch(&global_object, eq, receiver, Operand(scratch)); | 3456 __ Branch(&global_object, eq, receiver, Operand(scratch)); |
| 3468 __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex); | 3457 __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex); |
| 3469 __ Branch(&global_object, eq, receiver, Operand(scratch)); | 3458 __ Branch(&global_object, eq, receiver, Operand(scratch)); |
| 3470 | 3459 |
| 3471 // Deoptimize if the receiver is not a JS object. | 3460 // Deoptimize if the receiver is not a JS object. |
| 3472 __ SmiTst(receiver, scratch); | 3461 __ SmiTst(receiver, scratch); |
| 3473 DeoptimizeIf(eq, instr->environment(), scratch, Operand(zero_reg)); | 3462 DeoptimizeIf(eq, instr, scratch, Operand(zero_reg)); |
| 3474 | 3463 |
| 3475 __ GetObjectType(receiver, scratch, scratch); | 3464 __ GetObjectType(receiver, scratch, scratch); |
| 3476 DeoptimizeIf(lt, instr->environment(), | 3465 DeoptimizeIf(lt, instr, scratch, Operand(FIRST_SPEC_OBJECT_TYPE)); |
| 3477 scratch, Operand(FIRST_SPEC_OBJECT_TYPE)); | |
| 3478 __ Branch(&result_in_receiver); | 3466 __ Branch(&result_in_receiver); |
| 3479 | 3467 |
| 3480 __ bind(&global_object); | 3468 __ bind(&global_object); |
| 3481 __ ld(result, FieldMemOperand(function, JSFunction::kContextOffset)); | 3469 __ ld(result, FieldMemOperand(function, JSFunction::kContextOffset)); |
| 3482 __ ld(result, | 3470 __ ld(result, |
| 3483 ContextOperand(result, Context::GLOBAL_OBJECT_INDEX)); | 3471 ContextOperand(result, Context::GLOBAL_OBJECT_INDEX)); |
| 3484 __ ld(result, | 3472 __ ld(result, |
| 3485 FieldMemOperand(result, GlobalObject::kGlobalProxyOffset)); | 3473 FieldMemOperand(result, GlobalObject::kGlobalProxyOffset)); |
| 3486 | 3474 |
| 3487 if (result.is(receiver)) { | 3475 if (result.is(receiver)) { |
| (...skipping 14 matching lines...) Expand all Loading... |
| 3502 Register length = ToRegister(instr->length()); | 3490 Register length = ToRegister(instr->length()); |
| 3503 Register elements = ToRegister(instr->elements()); | 3491 Register elements = ToRegister(instr->elements()); |
| 3504 Register scratch = scratch0(); | 3492 Register scratch = scratch0(); |
| 3505 DCHECK(receiver.is(a0)); // Used for parameter count. | 3493 DCHECK(receiver.is(a0)); // Used for parameter count. |
| 3506 DCHECK(function.is(a1)); // Required by InvokeFunction. | 3494 DCHECK(function.is(a1)); // Required by InvokeFunction. |
| 3507 DCHECK(ToRegister(instr->result()).is(v0)); | 3495 DCHECK(ToRegister(instr->result()).is(v0)); |
| 3508 | 3496 |
| 3509 // Copy the arguments to this function possibly from the | 3497 // Copy the arguments to this function possibly from the |
| 3510 // adaptor frame below it. | 3498 // adaptor frame below it. |
| 3511 const uint32_t kArgumentsLimit = 1 * KB; | 3499 const uint32_t kArgumentsLimit = 1 * KB; |
| 3512 DeoptimizeIf(hi, instr->environment(), length, Operand(kArgumentsLimit)); | 3500 DeoptimizeIf(hi, instr, length, Operand(kArgumentsLimit)); |
| 3513 | 3501 |
| 3514 // Push the receiver and use the register to keep the original | 3502 // Push the receiver and use the register to keep the original |
| 3515 // number of arguments. | 3503 // number of arguments. |
| 3516 __ push(receiver); | 3504 __ push(receiver); |
| 3517 __ Move(receiver, length); | 3505 __ Move(receiver, length); |
| 3518 // The arguments are at a one pointer size offset from elements. | 3506 // The arguments are at a one pointer size offset from elements. |
| 3519 __ Daddu(elements, elements, Operand(1 * kPointerSize)); | 3507 __ Daddu(elements, elements, Operand(1 * kPointerSize)); |
| 3520 | 3508 |
| 3521 // Loop through the arguments pushing them onto the execution | 3509 // Loop through the arguments pushing them onto the execution |
| 3522 // stack. | 3510 // stack. |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3632 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { | 3620 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { |
| 3633 DCHECK(instr->context() != NULL); | 3621 DCHECK(instr->context() != NULL); |
| 3634 DCHECK(ToRegister(instr->context()).is(cp)); | 3622 DCHECK(ToRegister(instr->context()).is(cp)); |
| 3635 Register input = ToRegister(instr->value()); | 3623 Register input = ToRegister(instr->value()); |
| 3636 Register result = ToRegister(instr->result()); | 3624 Register result = ToRegister(instr->result()); |
| 3637 Register scratch = scratch0(); | 3625 Register scratch = scratch0(); |
| 3638 | 3626 |
| 3639 // Deoptimize if not a heap number. | 3627 // Deoptimize if not a heap number. |
| 3640 __ ld(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); | 3628 __ ld(scratch, FieldMemOperand(input, HeapObject::kMapOffset)); |
| 3641 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); | 3629 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); |
| 3642 DeoptimizeIf(ne, instr->environment(), scratch, Operand(at)); | 3630 DeoptimizeIf(ne, instr, scratch, Operand(at)); |
| 3643 | 3631 |
| 3644 Label done; | 3632 Label done; |
| 3645 Register exponent = scratch0(); | 3633 Register exponent = scratch0(); |
| 3646 scratch = no_reg; | 3634 scratch = no_reg; |
| 3647 __ lwu(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset)); | 3635 __ lwu(exponent, FieldMemOperand(input, HeapNumber::kExponentOffset)); |
| 3648 // Check the sign of the argument. If the argument is positive, just | 3636 // Check the sign of the argument. If the argument is positive, just |
| 3649 // return it. | 3637 // return it. |
| 3650 __ Move(result, input); | 3638 __ Move(result, input); |
| 3651 __ And(at, exponent, Operand(HeapNumber::kSignMask)); | 3639 __ And(at, exponent, Operand(HeapNumber::kSignMask)); |
| 3652 __ Branch(&done, eq, at, Operand(zero_reg)); | 3640 __ Branch(&done, eq, at, Operand(zero_reg)); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3699 | 3687 |
| 3700 void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) { | 3688 void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) { |
| 3701 Register input = ToRegister(instr->value()); | 3689 Register input = ToRegister(instr->value()); |
| 3702 Register result = ToRegister(instr->result()); | 3690 Register result = ToRegister(instr->result()); |
| 3703 Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_); | 3691 Assembler::BlockTrampolinePoolScope block_trampoline_pool(masm_); |
| 3704 Label done; | 3692 Label done; |
| 3705 __ Branch(USE_DELAY_SLOT, &done, ge, input, Operand(zero_reg)); | 3693 __ Branch(USE_DELAY_SLOT, &done, ge, input, Operand(zero_reg)); |
| 3706 __ mov(result, input); | 3694 __ mov(result, input); |
| 3707 __ dsubu(result, zero_reg, input); | 3695 __ dsubu(result, zero_reg, input); |
| 3708 // Overflow if result is still negative, i.e. 0x80000000. | 3696 // Overflow if result is still negative, i.e. 0x80000000. |
| 3709 DeoptimizeIf(lt, instr->environment(), result, Operand(zero_reg)); | 3697 DeoptimizeIf(lt, instr, result, Operand(zero_reg)); |
| 3710 __ bind(&done); | 3698 __ bind(&done); |
| 3711 } | 3699 } |
| 3712 | 3700 |
| 3713 | 3701 |
| 3714 void LCodeGen::DoMathAbs(LMathAbs* instr) { | 3702 void LCodeGen::DoMathAbs(LMathAbs* instr) { |
| 3715 // Class for deferred case. | 3703 // Class for deferred case. |
| 3716 class DeferredMathAbsTaggedHeapNumber FINAL : public LDeferredCode { | 3704 class DeferredMathAbsTaggedHeapNumber FINAL : public LDeferredCode { |
| 3717 public: | 3705 public: |
| 3718 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, LMathAbs* instr) | 3706 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, LMathAbs* instr) |
| 3719 : LDeferredCode(codegen), instr_(instr) { } | 3707 : LDeferredCode(codegen), instr_(instr) { } |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3753 Register except_flag = ToRegister(instr->temp()); | 3741 Register except_flag = ToRegister(instr->temp()); |
| 3754 | 3742 |
| 3755 __ EmitFPUTruncate(kRoundToMinusInf, | 3743 __ EmitFPUTruncate(kRoundToMinusInf, |
| 3756 result, | 3744 result, |
| 3757 input, | 3745 input, |
| 3758 scratch1, | 3746 scratch1, |
| 3759 double_scratch0(), | 3747 double_scratch0(), |
| 3760 except_flag); | 3748 except_flag); |
| 3761 | 3749 |
| 3762 // Deopt if the operation did not succeed. | 3750 // Deopt if the operation did not succeed. |
| 3763 DeoptimizeIf(ne, instr->environment(), except_flag, Operand(zero_reg)); | 3751 DeoptimizeIf(ne, instr, except_flag, Operand(zero_reg)); |
| 3764 | 3752 |
| 3765 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3753 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 3766 // Test for -0. | 3754 // Test for -0. |
| 3767 Label done; | 3755 Label done; |
| 3768 __ Branch(&done, ne, result, Operand(zero_reg)); | 3756 __ Branch(&done, ne, result, Operand(zero_reg)); |
| 3769 __ mfhc1(scratch1, input); // Get exponent/sign bits. | 3757 __ mfhc1(scratch1, input); // Get exponent/sign bits. |
| 3770 __ And(scratch1, scratch1, Operand(HeapNumber::kSignMask)); | 3758 __ And(scratch1, scratch1, Operand(HeapNumber::kSignMask)); |
| 3771 DeoptimizeIf(ne, instr->environment(), scratch1, Operand(zero_reg)); | 3759 DeoptimizeIf(ne, instr, scratch1, Operand(zero_reg)); |
| 3772 __ bind(&done); | 3760 __ bind(&done); |
| 3773 } | 3761 } |
| 3774 } | 3762 } |
| 3775 | 3763 |
| 3776 | 3764 |
| 3777 void LCodeGen::DoMathRound(LMathRound* instr) { | 3765 void LCodeGen::DoMathRound(LMathRound* instr) { |
| 3778 DoubleRegister input = ToDoubleRegister(instr->value()); | 3766 DoubleRegister input = ToDoubleRegister(instr->value()); |
| 3779 Register result = ToRegister(instr->result()); | 3767 Register result = ToRegister(instr->result()); |
| 3780 DoubleRegister double_scratch1 = ToDoubleRegister(instr->temp()); | 3768 DoubleRegister double_scratch1 = ToDoubleRegister(instr->temp()); |
| 3781 Register scratch = scratch0(); | 3769 Register scratch = scratch0(); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 3794 __ mov(result, zero_reg); | 3782 __ mov(result, zero_reg); |
| 3795 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3783 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 3796 __ Branch(&check_sign_on_zero); | 3784 __ Branch(&check_sign_on_zero); |
| 3797 } else { | 3785 } else { |
| 3798 __ Branch(&done); | 3786 __ Branch(&done); |
| 3799 } | 3787 } |
| 3800 __ bind(&skip1); | 3788 __ bind(&skip1); |
| 3801 | 3789 |
| 3802 // The following conversion will not work with numbers | 3790 // The following conversion will not work with numbers |
| 3803 // outside of ]-2^32, 2^32[. | 3791 // outside of ]-2^32, 2^32[. |
| 3804 DeoptimizeIf(ge, instr->environment(), scratch, | 3792 DeoptimizeIf(ge, instr, scratch, Operand(HeapNumber::kExponentBias + 32)); |
| 3805 Operand(HeapNumber::kExponentBias + 32)); | |
| 3806 | 3793 |
| 3807 // Save the original sign for later comparison. | 3794 // Save the original sign for later comparison. |
| 3808 __ And(scratch, result, Operand(HeapNumber::kSignMask)); | 3795 __ And(scratch, result, Operand(HeapNumber::kSignMask)); |
| 3809 | 3796 |
| 3810 __ Move(double_scratch0(), 0.5); | 3797 __ Move(double_scratch0(), 0.5); |
| 3811 __ add_d(double_scratch0(), input, double_scratch0()); | 3798 __ add_d(double_scratch0(), input, double_scratch0()); |
| 3812 | 3799 |
| 3813 // Check sign of the result: if the sign changed, the input | 3800 // Check sign of the result: if the sign changed, the input |
| 3814 // value was in ]0.5, 0[ and the result should be -0. | 3801 // value was in ]0.5, 0[ and the result should be -0. |
| 3815 __ mfhc1(result, double_scratch0()); | 3802 __ mfhc1(result, double_scratch0()); |
| 3816 // mfhc1 sign-extends, clear the upper bits. | 3803 // mfhc1 sign-extends, clear the upper bits. |
| 3817 __ dsll32(result, result, 0); | 3804 __ dsll32(result, result, 0); |
| 3818 __ dsrl32(result, result, 0); | 3805 __ dsrl32(result, result, 0); |
| 3819 __ Xor(result, result, Operand(scratch)); | 3806 __ Xor(result, result, Operand(scratch)); |
| 3820 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3807 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 3821 // ARM uses 'mi' here, which is 'lt' | 3808 // ARM uses 'mi' here, which is 'lt' |
| 3822 DeoptimizeIf(lt, instr->environment(), result, | 3809 DeoptimizeIf(lt, instr, result, Operand(zero_reg)); |
| 3823 Operand(zero_reg)); | |
| 3824 } else { | 3810 } else { |
| 3825 Label skip2; | 3811 Label skip2; |
| 3826 // ARM uses 'mi' here, which is 'lt' | 3812 // ARM uses 'mi' here, which is 'lt' |
| 3827 // Negating it results in 'ge' | 3813 // Negating it results in 'ge' |
| 3828 __ Branch(&skip2, ge, result, Operand(zero_reg)); | 3814 __ Branch(&skip2, ge, result, Operand(zero_reg)); |
| 3829 __ mov(result, zero_reg); | 3815 __ mov(result, zero_reg); |
| 3830 __ Branch(&done); | 3816 __ Branch(&done); |
| 3831 __ bind(&skip2); | 3817 __ bind(&skip2); |
| 3832 } | 3818 } |
| 3833 | 3819 |
| 3834 Register except_flag = scratch; | 3820 Register except_flag = scratch; |
| 3835 __ EmitFPUTruncate(kRoundToMinusInf, | 3821 __ EmitFPUTruncate(kRoundToMinusInf, |
| 3836 result, | 3822 result, |
| 3837 double_scratch0(), | 3823 double_scratch0(), |
| 3838 at, | 3824 at, |
| 3839 double_scratch1, | 3825 double_scratch1, |
| 3840 except_flag); | 3826 except_flag); |
| 3841 | 3827 |
| 3842 DeoptimizeIf(ne, instr->environment(), except_flag, Operand(zero_reg)); | 3828 DeoptimizeIf(ne, instr, except_flag, Operand(zero_reg)); |
| 3843 | 3829 |
| 3844 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3830 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 3845 // Test for -0. | 3831 // Test for -0. |
| 3846 __ Branch(&done, ne, result, Operand(zero_reg)); | 3832 __ Branch(&done, ne, result, Operand(zero_reg)); |
| 3847 __ bind(&check_sign_on_zero); | 3833 __ bind(&check_sign_on_zero); |
| 3848 __ mfhc1(scratch, input); // Get exponent/sign bits. | 3834 __ mfhc1(scratch, input); // Get exponent/sign bits. |
| 3849 __ And(scratch, scratch, Operand(HeapNumber::kSignMask)); | 3835 __ And(scratch, scratch, Operand(HeapNumber::kSignMask)); |
| 3850 DeoptimizeIf(ne, instr->environment(), scratch, Operand(zero_reg)); | 3836 DeoptimizeIf(ne, instr, scratch, Operand(zero_reg)); |
| 3851 } | 3837 } |
| 3852 __ bind(&done); | 3838 __ bind(&done); |
| 3853 } | 3839 } |
| 3854 | 3840 |
| 3855 | 3841 |
| 3856 void LCodeGen::DoMathFround(LMathFround* instr) { | 3842 void LCodeGen::DoMathFround(LMathFround* instr) { |
| 3857 DoubleRegister input = ToDoubleRegister(instr->value()); | 3843 DoubleRegister input = ToDoubleRegister(instr->value()); |
| 3858 DoubleRegister result = ToDoubleRegister(instr->result()); | 3844 DoubleRegister result = ToDoubleRegister(instr->result()); |
| 3859 __ cvt_s_d(result, input); | 3845 __ cvt_s_d(result, input); |
| 3860 __ cvt_d_s(result, result); | 3846 __ cvt_d_s(result, result); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3906 | 3892 |
| 3907 if (exponent_type.IsSmi()) { | 3893 if (exponent_type.IsSmi()) { |
| 3908 MathPowStub stub(isolate(), MathPowStub::TAGGED); | 3894 MathPowStub stub(isolate(), MathPowStub::TAGGED); |
| 3909 __ CallStub(&stub); | 3895 __ CallStub(&stub); |
| 3910 } else if (exponent_type.IsTagged()) { | 3896 } else if (exponent_type.IsTagged()) { |
| 3911 Label no_deopt; | 3897 Label no_deopt; |
| 3912 __ JumpIfSmi(tagged_exponent, &no_deopt); | 3898 __ JumpIfSmi(tagged_exponent, &no_deopt); |
| 3913 DCHECK(!a7.is(tagged_exponent)); | 3899 DCHECK(!a7.is(tagged_exponent)); |
| 3914 __ lw(a7, FieldMemOperand(tagged_exponent, HeapObject::kMapOffset)); | 3900 __ lw(a7, FieldMemOperand(tagged_exponent, HeapObject::kMapOffset)); |
| 3915 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); | 3901 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); |
| 3916 DeoptimizeIf(ne, instr->environment(), a7, Operand(at)); | 3902 DeoptimizeIf(ne, instr, a7, Operand(at)); |
| 3917 __ bind(&no_deopt); | 3903 __ bind(&no_deopt); |
| 3918 MathPowStub stub(isolate(), MathPowStub::TAGGED); | 3904 MathPowStub stub(isolate(), MathPowStub::TAGGED); |
| 3919 __ CallStub(&stub); | 3905 __ CallStub(&stub); |
| 3920 } else if (exponent_type.IsInteger32()) { | 3906 } else if (exponent_type.IsInteger32()) { |
| 3921 MathPowStub stub(isolate(), MathPowStub::INTEGER); | 3907 MathPowStub stub(isolate(), MathPowStub::INTEGER); |
| 3922 __ CallStub(&stub); | 3908 __ CallStub(&stub); |
| 3923 } else { | 3909 } else { |
| 3924 DCHECK(exponent_type.IsDouble()); | 3910 DCHECK(exponent_type.IsDouble()); |
| 3925 MathPowStub stub(isolate(), MathPowStub::DOUBLE); | 3911 MathPowStub stub(isolate(), MathPowStub::DOUBLE); |
| 3926 __ CallStub(&stub); | 3912 __ CallStub(&stub); |
| (...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4248 } else { | 4234 } else { |
| 4249 reg = ToRegister(instr->index()); | 4235 reg = ToRegister(instr->index()); |
| 4250 operand = ToOperand(instr->length()); | 4236 operand = ToOperand(instr->length()); |
| 4251 } | 4237 } |
| 4252 if (FLAG_debug_code && instr->hydrogen()->skip_check()) { | 4238 if (FLAG_debug_code && instr->hydrogen()->skip_check()) { |
| 4253 Label done; | 4239 Label done; |
| 4254 __ Branch(&done, NegateCondition(cc), reg, operand); | 4240 __ Branch(&done, NegateCondition(cc), reg, operand); |
| 4255 __ stop("eliminated bounds check failed"); | 4241 __ stop("eliminated bounds check failed"); |
| 4256 __ bind(&done); | 4242 __ bind(&done); |
| 4257 } else { | 4243 } else { |
| 4258 DeoptimizeIf(cc, instr->environment(), reg, operand); | 4244 DeoptimizeIf(cc, instr, reg, operand); |
| 4259 } | 4245 } |
| 4260 } | 4246 } |
| 4261 | 4247 |
| 4262 | 4248 |
| 4263 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) { | 4249 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) { |
| 4264 Register external_pointer = ToRegister(instr->elements()); | 4250 Register external_pointer = ToRegister(instr->elements()); |
| 4265 Register key = no_reg; | 4251 Register key = no_reg; |
| 4266 ElementsKind elements_kind = instr->elements_kind(); | 4252 ElementsKind elements_kind = instr->elements_kind(); |
| 4267 bool key_is_constant = instr->key()->IsConstantOperand(); | 4253 bool key_is_constant = instr->key()->IsConstantOperand(); |
| 4268 int constant_key = 0; | 4254 int constant_key = 0; |
| (...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4539 __ bind(¬_applicable); | 4525 __ bind(¬_applicable); |
| 4540 } | 4526 } |
| 4541 | 4527 |
| 4542 | 4528 |
| 4543 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) { | 4529 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) { |
| 4544 Register object = ToRegister(instr->object()); | 4530 Register object = ToRegister(instr->object()); |
| 4545 Register temp = ToRegister(instr->temp()); | 4531 Register temp = ToRegister(instr->temp()); |
| 4546 Label no_memento_found; | 4532 Label no_memento_found; |
| 4547 __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found, | 4533 __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found, |
| 4548 ne, &no_memento_found); | 4534 ne, &no_memento_found); |
| 4549 DeoptimizeIf(al, instr->environment()); | 4535 DeoptimizeIf(al, instr); |
| 4550 __ bind(&no_memento_found); | 4536 __ bind(&no_memento_found); |
| 4551 } | 4537 } |
| 4552 | 4538 |
| 4553 | 4539 |
| 4554 void LCodeGen::DoStringAdd(LStringAdd* instr) { | 4540 void LCodeGen::DoStringAdd(LStringAdd* instr) { |
| 4555 DCHECK(ToRegister(instr->context()).is(cp)); | 4541 DCHECK(ToRegister(instr->context()).is(cp)); |
| 4556 DCHECK(ToRegister(instr->left()).is(a1)); | 4542 DCHECK(ToRegister(instr->left()).is(a1)); |
| 4557 DCHECK(ToRegister(instr->right()).is(a0)); | 4543 DCHECK(ToRegister(instr->right()).is(a0)); |
| 4558 StringAddStub stub(isolate(), | 4544 StringAddStub stub(isolate(), |
| 4559 instr->hydrogen()->flags(), | 4545 instr->hydrogen()->flags(), |
| (...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4842 } | 4828 } |
| 4843 | 4829 |
| 4844 | 4830 |
| 4845 void LCodeGen::DoSmiTag(LSmiTag* instr) { | 4831 void LCodeGen::DoSmiTag(LSmiTag* instr) { |
| 4846 HChange* hchange = instr->hydrogen(); | 4832 HChange* hchange = instr->hydrogen(); |
| 4847 Register input = ToRegister(instr->value()); | 4833 Register input = ToRegister(instr->value()); |
| 4848 Register output = ToRegister(instr->result()); | 4834 Register output = ToRegister(instr->result()); |
| 4849 if (hchange->CheckFlag(HValue::kCanOverflow) && | 4835 if (hchange->CheckFlag(HValue::kCanOverflow) && |
| 4850 hchange->value()->CheckFlag(HValue::kUint32)) { | 4836 hchange->value()->CheckFlag(HValue::kUint32)) { |
| 4851 __ And(at, input, Operand(0x80000000)); | 4837 __ And(at, input, Operand(0x80000000)); |
| 4852 DeoptimizeIf(ne, instr->environment(), at, Operand(zero_reg)); | 4838 DeoptimizeIf(ne, instr, at, Operand(zero_reg)); |
| 4853 } | 4839 } |
| 4854 if (hchange->CheckFlag(HValue::kCanOverflow) && | 4840 if (hchange->CheckFlag(HValue::kCanOverflow) && |
| 4855 !hchange->value()->CheckFlag(HValue::kUint32)) { | 4841 !hchange->value()->CheckFlag(HValue::kUint32)) { |
| 4856 __ SmiTagCheckOverflow(output, input, at); | 4842 __ SmiTagCheckOverflow(output, input, at); |
| 4857 DeoptimizeIf(lt, instr->environment(), at, Operand(zero_reg)); | 4843 DeoptimizeIf(lt, instr, at, Operand(zero_reg)); |
| 4858 } else { | 4844 } else { |
| 4859 __ SmiTag(output, input); | 4845 __ SmiTag(output, input); |
| 4860 } | 4846 } |
| 4861 } | 4847 } |
| 4862 | 4848 |
| 4863 | 4849 |
| 4864 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { | 4850 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { |
| 4865 Register scratch = scratch0(); | 4851 Register scratch = scratch0(); |
| 4866 Register input = ToRegister(instr->value()); | 4852 Register input = ToRegister(instr->value()); |
| 4867 Register result = ToRegister(instr->result()); | 4853 Register result = ToRegister(instr->result()); |
| 4868 if (instr->needs_check()) { | 4854 if (instr->needs_check()) { |
| 4869 STATIC_ASSERT(kHeapObjectTag == 1); | 4855 STATIC_ASSERT(kHeapObjectTag == 1); |
| 4870 // If the input is a HeapObject, value of scratch won't be zero. | 4856 // If the input is a HeapObject, value of scratch won't be zero. |
| 4871 __ And(scratch, input, Operand(kHeapObjectTag)); | 4857 __ And(scratch, input, Operand(kHeapObjectTag)); |
| 4872 __ SmiUntag(result, input); | 4858 __ SmiUntag(result, input); |
| 4873 DeoptimizeIf(ne, instr->environment(), scratch, Operand(zero_reg)); | 4859 DeoptimizeIf(ne, instr, scratch, Operand(zero_reg)); |
| 4874 } else { | 4860 } else { |
| 4875 __ SmiUntag(result, input); | 4861 __ SmiUntag(result, input); |
| 4876 } | 4862 } |
| 4877 } | 4863 } |
| 4878 | 4864 |
| 4879 | 4865 |
| 4880 void LCodeGen::EmitNumberUntagD(Register input_reg, | 4866 void LCodeGen::EmitNumberUntagD(LNumberUntagD* instr, Register input_reg, |
| 4881 DoubleRegister result_reg, | 4867 DoubleRegister result_reg, |
| 4882 bool can_convert_undefined_to_nan, | |
| 4883 bool deoptimize_on_minus_zero, | |
| 4884 LEnvironment* env, | |
| 4885 NumberUntagDMode mode) { | 4868 NumberUntagDMode mode) { |
| 4869 bool can_convert_undefined_to_nan = |
| 4870 instr->hydrogen()->can_convert_undefined_to_nan(); |
| 4871 bool deoptimize_on_minus_zero = instr->hydrogen()->deoptimize_on_minus_zero(); |
| 4872 |
| 4886 Register scratch = scratch0(); | 4873 Register scratch = scratch0(); |
| 4887 Label convert, load_smi, done; | 4874 Label convert, load_smi, done; |
| 4888 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) { | 4875 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) { |
| 4889 // Smi check. | 4876 // Smi check. |
| 4890 __ UntagAndJumpIfSmi(scratch, input_reg, &load_smi); | 4877 __ UntagAndJumpIfSmi(scratch, input_reg, &load_smi); |
| 4891 // Heap number map check. | 4878 // Heap number map check. |
| 4892 __ ld(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); | 4879 __ ld(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); |
| 4893 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); | 4880 __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); |
| 4894 if (can_convert_undefined_to_nan) { | 4881 if (can_convert_undefined_to_nan) { |
| 4895 __ Branch(&convert, ne, scratch, Operand(at)); | 4882 __ Branch(&convert, ne, scratch, Operand(at)); |
| 4896 } else { | 4883 } else { |
| 4897 DeoptimizeIf(ne, env, scratch, Operand(at)); | 4884 DeoptimizeIf(ne, instr, scratch, Operand(at)); |
| 4898 } | 4885 } |
| 4899 // Load heap number. | 4886 // Load heap number. |
| 4900 __ ldc1(result_reg, FieldMemOperand(input_reg, HeapNumber::kValueOffset)); | 4887 __ ldc1(result_reg, FieldMemOperand(input_reg, HeapNumber::kValueOffset)); |
| 4901 if (deoptimize_on_minus_zero) { | 4888 if (deoptimize_on_minus_zero) { |
| 4902 __ mfc1(at, result_reg); | 4889 __ mfc1(at, result_reg); |
| 4903 __ Branch(&done, ne, at, Operand(zero_reg)); | 4890 __ Branch(&done, ne, at, Operand(zero_reg)); |
| 4904 __ mfhc1(scratch, result_reg); // Get exponent/sign bits. | 4891 __ mfhc1(scratch, result_reg); // Get exponent/sign bits. |
| 4905 DeoptimizeIf(eq, env, scratch, Operand(HeapNumber::kSignMask)); | 4892 DeoptimizeIf(eq, instr, scratch, Operand(HeapNumber::kSignMask)); |
| 4906 } | 4893 } |
| 4907 __ Branch(&done); | 4894 __ Branch(&done); |
| 4908 if (can_convert_undefined_to_nan) { | 4895 if (can_convert_undefined_to_nan) { |
| 4909 __ bind(&convert); | 4896 __ bind(&convert); |
| 4910 // Convert undefined (and hole) to NaN. | 4897 // Convert undefined (and hole) to NaN. |
| 4911 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); | 4898 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); |
| 4912 DeoptimizeIf(ne, env, input_reg, Operand(at)); | 4899 DeoptimizeIf(ne, instr, input_reg, Operand(at)); |
| 4913 __ LoadRoot(scratch, Heap::kNanValueRootIndex); | 4900 __ LoadRoot(scratch, Heap::kNanValueRootIndex); |
| 4914 __ ldc1(result_reg, FieldMemOperand(scratch, HeapNumber::kValueOffset)); | 4901 __ ldc1(result_reg, FieldMemOperand(scratch, HeapNumber::kValueOffset)); |
| 4915 __ Branch(&done); | 4902 __ Branch(&done); |
| 4916 } | 4903 } |
| 4917 } else { | 4904 } else { |
| 4918 __ SmiUntag(scratch, input_reg); | 4905 __ SmiUntag(scratch, input_reg); |
| 4919 DCHECK(mode == NUMBER_CANDIDATE_IS_SMI); | 4906 DCHECK(mode == NUMBER_CANDIDATE_IS_SMI); |
| 4920 } | 4907 } |
| 4921 // Smi to double register conversion | 4908 // Smi to double register conversion |
| 4922 __ bind(&load_smi); | 4909 __ bind(&load_smi); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4967 | 4954 |
| 4968 __ bind(&check_bools); | 4955 __ bind(&check_bools); |
| 4969 __ LoadRoot(at, Heap::kTrueValueRootIndex); | 4956 __ LoadRoot(at, Heap::kTrueValueRootIndex); |
| 4970 __ Branch(&check_false, ne, scratch2, Operand(at)); | 4957 __ Branch(&check_false, ne, scratch2, Operand(at)); |
| 4971 __ Branch(USE_DELAY_SLOT, &done); | 4958 __ Branch(USE_DELAY_SLOT, &done); |
| 4972 __ li(input_reg, Operand(1)); // In delay slot. | 4959 __ li(input_reg, Operand(1)); // In delay slot. |
| 4973 | 4960 |
| 4974 __ bind(&check_false); | 4961 __ bind(&check_false); |
| 4975 __ LoadRoot(at, Heap::kFalseValueRootIndex); | 4962 __ LoadRoot(at, Heap::kFalseValueRootIndex); |
| 4976 __ RecordComment("Deferred TaggedToI: cannot truncate"); | 4963 __ RecordComment("Deferred TaggedToI: cannot truncate"); |
| 4977 DeoptimizeIf(ne, instr->environment(), scratch2, Operand(at)); | 4964 DeoptimizeIf(ne, instr, scratch2, Operand(at)); |
| 4978 __ Branch(USE_DELAY_SLOT, &done); | 4965 __ Branch(USE_DELAY_SLOT, &done); |
| 4979 __ mov(input_reg, zero_reg); // In delay slot. | 4966 __ mov(input_reg, zero_reg); // In delay slot. |
| 4980 } else { | 4967 } else { |
| 4981 __ RecordComment("Deferred TaggedToI: not a heap number"); | 4968 __ RecordComment("Deferred TaggedToI: not a heap number"); |
| 4982 DeoptimizeIf(ne, instr->environment(), scratch1, Operand(at)); | 4969 DeoptimizeIf(ne, instr, scratch1, Operand(at)); |
| 4983 | 4970 |
| 4984 // Load the double value. | 4971 // Load the double value. |
| 4985 __ ldc1(double_scratch, | 4972 __ ldc1(double_scratch, |
| 4986 FieldMemOperand(input_reg, HeapNumber::kValueOffset)); | 4973 FieldMemOperand(input_reg, HeapNumber::kValueOffset)); |
| 4987 | 4974 |
| 4988 Register except_flag = scratch2; | 4975 Register except_flag = scratch2; |
| 4989 __ EmitFPUTruncate(kRoundToZero, | 4976 __ EmitFPUTruncate(kRoundToZero, |
| 4990 input_reg, | 4977 input_reg, |
| 4991 double_scratch, | 4978 double_scratch, |
| 4992 scratch1, | 4979 scratch1, |
| 4993 double_scratch2, | 4980 double_scratch2, |
| 4994 except_flag, | 4981 except_flag, |
| 4995 kCheckForInexactConversion); | 4982 kCheckForInexactConversion); |
| 4996 | 4983 |
| 4997 __ RecordComment("Deferred TaggedToI: lost precision or NaN"); | 4984 __ RecordComment("Deferred TaggedToI: lost precision or NaN"); |
| 4998 DeoptimizeIf(ne, instr->environment(), except_flag, Operand(zero_reg)); | 4985 DeoptimizeIf(ne, instr, except_flag, Operand(zero_reg)); |
| 4999 | 4986 |
| 5000 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 4987 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 5001 __ Branch(&done, ne, input_reg, Operand(zero_reg)); | 4988 __ Branch(&done, ne, input_reg, Operand(zero_reg)); |
| 5002 | 4989 |
| 5003 __ mfhc1(scratch1, double_scratch); // Get exponent/sign bits. | 4990 __ mfhc1(scratch1, double_scratch); // Get exponent/sign bits. |
| 5004 __ And(scratch1, scratch1, Operand(HeapNumber::kSignMask)); | 4991 __ And(scratch1, scratch1, Operand(HeapNumber::kSignMask)); |
| 5005 __ RecordComment("Deferred TaggedToI: minus zero"); | 4992 __ RecordComment("Deferred TaggedToI: minus zero"); |
| 5006 DeoptimizeIf(ne, instr->environment(), scratch1, Operand(zero_reg)); | 4993 DeoptimizeIf(ne, instr, scratch1, Operand(zero_reg)); |
| 5007 } | 4994 } |
| 5008 } | 4995 } |
| 5009 __ bind(&done); | 4996 __ bind(&done); |
| 5010 } | 4997 } |
| 5011 | 4998 |
| 5012 | 4999 |
| 5013 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { | 5000 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { |
| 5014 class DeferredTaggedToI FINAL : public LDeferredCode { | 5001 class DeferredTaggedToI FINAL : public LDeferredCode { |
| 5015 public: | 5002 public: |
| 5016 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) | 5003 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5050 LOperand* result = instr->result(); | 5037 LOperand* result = instr->result(); |
| 5051 DCHECK(result->IsDoubleRegister()); | 5038 DCHECK(result->IsDoubleRegister()); |
| 5052 | 5039 |
| 5053 Register input_reg = ToRegister(input); | 5040 Register input_reg = ToRegister(input); |
| 5054 DoubleRegister result_reg = ToDoubleRegister(result); | 5041 DoubleRegister result_reg = ToDoubleRegister(result); |
| 5055 | 5042 |
| 5056 HValue* value = instr->hydrogen()->value(); | 5043 HValue* value = instr->hydrogen()->value(); |
| 5057 NumberUntagDMode mode = value->representation().IsSmi() | 5044 NumberUntagDMode mode = value->representation().IsSmi() |
| 5058 ? NUMBER_CANDIDATE_IS_SMI : NUMBER_CANDIDATE_IS_ANY_TAGGED; | 5045 ? NUMBER_CANDIDATE_IS_SMI : NUMBER_CANDIDATE_IS_ANY_TAGGED; |
| 5059 | 5046 |
| 5060 EmitNumberUntagD(input_reg, result_reg, | 5047 EmitNumberUntagD(instr, input_reg, result_reg, mode); |
| 5061 instr->hydrogen()->can_convert_undefined_to_nan(), | |
| 5062 instr->hydrogen()->deoptimize_on_minus_zero(), | |
| 5063 instr->environment(), | |
| 5064 mode); | |
| 5065 } | 5048 } |
| 5066 | 5049 |
| 5067 | 5050 |
| 5068 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { | 5051 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { |
| 5069 Register result_reg = ToRegister(instr->result()); | 5052 Register result_reg = ToRegister(instr->result()); |
| 5070 Register scratch1 = scratch0(); | 5053 Register scratch1 = scratch0(); |
| 5071 DoubleRegister double_input = ToDoubleRegister(instr->value()); | 5054 DoubleRegister double_input = ToDoubleRegister(instr->value()); |
| 5072 | 5055 |
| 5073 if (instr->truncating()) { | 5056 if (instr->truncating()) { |
| 5074 __ TruncateDoubleToI(result_reg, double_input); | 5057 __ TruncateDoubleToI(result_reg, double_input); |
| 5075 } else { | 5058 } else { |
| 5076 Register except_flag = LCodeGen::scratch1(); | 5059 Register except_flag = LCodeGen::scratch1(); |
| 5077 | 5060 |
| 5078 __ EmitFPUTruncate(kRoundToMinusInf, | 5061 __ EmitFPUTruncate(kRoundToMinusInf, |
| 5079 result_reg, | 5062 result_reg, |
| 5080 double_input, | 5063 double_input, |
| 5081 scratch1, | 5064 scratch1, |
| 5082 double_scratch0(), | 5065 double_scratch0(), |
| 5083 except_flag, | 5066 except_flag, |
| 5084 kCheckForInexactConversion); | 5067 kCheckForInexactConversion); |
| 5085 | 5068 |
| 5086 // Deopt if the operation did not succeed (except_flag != 0). | 5069 // Deopt if the operation did not succeed (except_flag != 0). |
| 5087 DeoptimizeIf(ne, instr->environment(), except_flag, Operand(zero_reg)); | 5070 DeoptimizeIf(ne, instr, except_flag, Operand(zero_reg)); |
| 5088 | 5071 |
| 5089 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 5072 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 5090 Label done; | 5073 Label done; |
| 5091 __ Branch(&done, ne, result_reg, Operand(zero_reg)); | 5074 __ Branch(&done, ne, result_reg, Operand(zero_reg)); |
| 5092 __ mfhc1(scratch1, double_input); // Get exponent/sign bits. | 5075 __ mfhc1(scratch1, double_input); // Get exponent/sign bits. |
| 5093 __ And(scratch1, scratch1, Operand(HeapNumber::kSignMask)); | 5076 __ And(scratch1, scratch1, Operand(HeapNumber::kSignMask)); |
| 5094 DeoptimizeIf(ne, instr->environment(), scratch1, Operand(zero_reg)); | 5077 DeoptimizeIf(ne, instr, scratch1, Operand(zero_reg)); |
| 5095 __ bind(&done); | 5078 __ bind(&done); |
| 5096 } | 5079 } |
| 5097 } | 5080 } |
| 5098 } | 5081 } |
| 5099 | 5082 |
| 5100 | 5083 |
| 5101 void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) { | 5084 void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) { |
| 5102 Register result_reg = ToRegister(instr->result()); | 5085 Register result_reg = ToRegister(instr->result()); |
| 5103 Register scratch1 = LCodeGen::scratch0(); | 5086 Register scratch1 = LCodeGen::scratch0(); |
| 5104 DoubleRegister double_input = ToDoubleRegister(instr->value()); | 5087 DoubleRegister double_input = ToDoubleRegister(instr->value()); |
| 5105 | 5088 |
| 5106 if (instr->truncating()) { | 5089 if (instr->truncating()) { |
| 5107 __ TruncateDoubleToI(result_reg, double_input); | 5090 __ TruncateDoubleToI(result_reg, double_input); |
| 5108 } else { | 5091 } else { |
| 5109 Register except_flag = LCodeGen::scratch1(); | 5092 Register except_flag = LCodeGen::scratch1(); |
| 5110 | 5093 |
| 5111 __ EmitFPUTruncate(kRoundToMinusInf, | 5094 __ EmitFPUTruncate(kRoundToMinusInf, |
| 5112 result_reg, | 5095 result_reg, |
| 5113 double_input, | 5096 double_input, |
| 5114 scratch1, | 5097 scratch1, |
| 5115 double_scratch0(), | 5098 double_scratch0(), |
| 5116 except_flag, | 5099 except_flag, |
| 5117 kCheckForInexactConversion); | 5100 kCheckForInexactConversion); |
| 5118 | 5101 |
| 5119 // Deopt if the operation did not succeed (except_flag != 0). | 5102 // Deopt if the operation did not succeed (except_flag != 0). |
| 5120 DeoptimizeIf(ne, instr->environment(), except_flag, Operand(zero_reg)); | 5103 DeoptimizeIf(ne, instr, except_flag, Operand(zero_reg)); |
| 5121 | 5104 |
| 5122 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 5105 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| 5123 Label done; | 5106 Label done; |
| 5124 __ Branch(&done, ne, result_reg, Operand(zero_reg)); | 5107 __ Branch(&done, ne, result_reg, Operand(zero_reg)); |
| 5125 __ mfhc1(scratch1, double_input); // Get exponent/sign bits. | 5108 __ mfhc1(scratch1, double_input); // Get exponent/sign bits. |
| 5126 __ And(scratch1, scratch1, Operand(HeapNumber::kSignMask)); | 5109 __ And(scratch1, scratch1, Operand(HeapNumber::kSignMask)); |
| 5127 DeoptimizeIf(ne, instr->environment(), scratch1, Operand(zero_reg)); | 5110 DeoptimizeIf(ne, instr, scratch1, Operand(zero_reg)); |
| 5128 __ bind(&done); | 5111 __ bind(&done); |
| 5129 } | 5112 } |
| 5130 } | 5113 } |
| 5131 __ SmiTag(result_reg, result_reg); | 5114 __ SmiTag(result_reg, result_reg); |
| 5132 } | 5115 } |
| 5133 | 5116 |
| 5134 | 5117 |
| 5135 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { | 5118 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { |
| 5136 LOperand* input = instr->value(); | 5119 LOperand* input = instr->value(); |
| 5137 __ SmiTst(ToRegister(input), at); | 5120 __ SmiTst(ToRegister(input), at); |
| 5138 DeoptimizeIf(ne, instr->environment(), at, Operand(zero_reg)); | 5121 DeoptimizeIf(ne, instr, at, Operand(zero_reg)); |
| 5139 } | 5122 } |
| 5140 | 5123 |
| 5141 | 5124 |
| 5142 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { | 5125 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { |
| 5143 if (!instr->hydrogen()->value()->type().IsHeapObject()) { | 5126 if (!instr->hydrogen()->value()->type().IsHeapObject()) { |
| 5144 LOperand* input = instr->value(); | 5127 LOperand* input = instr->value(); |
| 5145 __ SmiTst(ToRegister(input), at); | 5128 __ SmiTst(ToRegister(input), at); |
| 5146 DeoptimizeIf(eq, instr->environment(), at, Operand(zero_reg)); | 5129 DeoptimizeIf(eq, instr, at, Operand(zero_reg)); |
| 5147 } | 5130 } |
| 5148 } | 5131 } |
| 5149 | 5132 |
| 5150 | 5133 |
| 5151 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { | 5134 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { |
| 5152 Register input = ToRegister(instr->value()); | 5135 Register input = ToRegister(instr->value()); |
| 5153 Register scratch = scratch0(); | 5136 Register scratch = scratch0(); |
| 5154 | 5137 |
| 5155 __ GetObjectType(input, scratch, scratch); | 5138 __ GetObjectType(input, scratch, scratch); |
| 5156 | 5139 |
| 5157 if (instr->hydrogen()->is_interval_check()) { | 5140 if (instr->hydrogen()->is_interval_check()) { |
| 5158 InstanceType first; | 5141 InstanceType first; |
| 5159 InstanceType last; | 5142 InstanceType last; |
| 5160 instr->hydrogen()->GetCheckInterval(&first, &last); | 5143 instr->hydrogen()->GetCheckInterval(&first, &last); |
| 5161 | 5144 |
| 5162 // If there is only one type in the interval check for equality. | 5145 // If there is only one type in the interval check for equality. |
| 5163 if (first == last) { | 5146 if (first == last) { |
| 5164 DeoptimizeIf(ne, instr->environment(), scratch, Operand(first)); | 5147 DeoptimizeIf(ne, instr, scratch, Operand(first)); |
| 5165 } else { | 5148 } else { |
| 5166 DeoptimizeIf(lo, instr->environment(), scratch, Operand(first)); | 5149 DeoptimizeIf(lo, instr, scratch, Operand(first)); |
| 5167 // Omit check for the last type. | 5150 // Omit check for the last type. |
| 5168 if (last != LAST_TYPE) { | 5151 if (last != LAST_TYPE) { |
| 5169 DeoptimizeIf(hi, instr->environment(), scratch, Operand(last)); | 5152 DeoptimizeIf(hi, instr, scratch, Operand(last)); |
| 5170 } | 5153 } |
| 5171 } | 5154 } |
| 5172 } else { | 5155 } else { |
| 5173 uint8_t mask; | 5156 uint8_t mask; |
| 5174 uint8_t tag; | 5157 uint8_t tag; |
| 5175 instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag); | 5158 instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag); |
| 5176 | 5159 |
| 5177 if (base::bits::IsPowerOfTwo32(mask)) { | 5160 if (base::bits::IsPowerOfTwo32(mask)) { |
| 5178 DCHECK(tag == 0 || base::bits::IsPowerOfTwo32(tag)); | 5161 DCHECK(tag == 0 || base::bits::IsPowerOfTwo32(tag)); |
| 5179 __ And(at, scratch, mask); | 5162 __ And(at, scratch, mask); |
| 5180 DeoptimizeIf(tag == 0 ? ne : eq, instr->environment(), | 5163 DeoptimizeIf(tag == 0 ? ne : eq, instr, at, Operand(zero_reg)); |
| 5181 at, Operand(zero_reg)); | |
| 5182 } else { | 5164 } else { |
| 5183 __ And(scratch, scratch, Operand(mask)); | 5165 __ And(scratch, scratch, Operand(mask)); |
| 5184 DeoptimizeIf(ne, instr->environment(), scratch, Operand(tag)); | 5166 DeoptimizeIf(ne, instr, scratch, Operand(tag)); |
| 5185 } | 5167 } |
| 5186 } | 5168 } |
| 5187 } | 5169 } |
| 5188 | 5170 |
| 5189 | 5171 |
| 5190 void LCodeGen::DoCheckValue(LCheckValue* instr) { | 5172 void LCodeGen::DoCheckValue(LCheckValue* instr) { |
| 5191 Register reg = ToRegister(instr->value()); | 5173 Register reg = ToRegister(instr->value()); |
| 5192 Handle<HeapObject> object = instr->hydrogen()->object().handle(); | 5174 Handle<HeapObject> object = instr->hydrogen()->object().handle(); |
| 5193 AllowDeferredHandleDereference smi_check; | 5175 AllowDeferredHandleDereference smi_check; |
| 5194 if (isolate()->heap()->InNewSpace(*object)) { | 5176 if (isolate()->heap()->InNewSpace(*object)) { |
| 5195 Register reg = ToRegister(instr->value()); | 5177 Register reg = ToRegister(instr->value()); |
| 5196 Handle<Cell> cell = isolate()->factory()->NewCell(object); | 5178 Handle<Cell> cell = isolate()->factory()->NewCell(object); |
| 5197 __ li(at, Operand(Handle<Object>(cell))); | 5179 __ li(at, Operand(Handle<Object>(cell))); |
| 5198 __ ld(at, FieldMemOperand(at, Cell::kValueOffset)); | 5180 __ ld(at, FieldMemOperand(at, Cell::kValueOffset)); |
| 5199 DeoptimizeIf(ne, instr->environment(), reg, | 5181 DeoptimizeIf(ne, instr, reg, Operand(at)); |
| 5200 Operand(at)); | |
| 5201 } else { | 5182 } else { |
| 5202 DeoptimizeIf(ne, instr->environment(), reg, | 5183 DeoptimizeIf(ne, instr, reg, Operand(object)); |
| 5203 Operand(object)); | |
| 5204 } | 5184 } |
| 5205 } | 5185 } |
| 5206 | 5186 |
| 5207 | 5187 |
| 5208 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) { | 5188 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) { |
| 5209 { | 5189 { |
| 5210 PushSafepointRegistersScope scope(this); | 5190 PushSafepointRegistersScope scope(this); |
| 5211 __ push(object); | 5191 __ push(object); |
| 5212 __ mov(cp, zero_reg); | 5192 __ mov(cp, zero_reg); |
| 5213 __ CallRuntimeSaveDoubles(Runtime::kTryMigrateInstance); | 5193 __ CallRuntimeSaveDoubles(Runtime::kTryMigrateInstance); |
| 5214 RecordSafepointWithRegisters( | 5194 RecordSafepointWithRegisters( |
| 5215 instr->pointer_map(), 1, Safepoint::kNoLazyDeopt); | 5195 instr->pointer_map(), 1, Safepoint::kNoLazyDeopt); |
| 5216 __ StoreToSafepointRegisterSlot(v0, scratch0()); | 5196 __ StoreToSafepointRegisterSlot(v0, scratch0()); |
| 5217 } | 5197 } |
| 5218 __ SmiTst(scratch0(), at); | 5198 __ SmiTst(scratch0(), at); |
| 5219 DeoptimizeIf(eq, instr->environment(), at, Operand(zero_reg)); | 5199 DeoptimizeIf(eq, instr, at, Operand(zero_reg)); |
| 5220 } | 5200 } |
| 5221 | 5201 |
| 5222 | 5202 |
| 5223 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { | 5203 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { |
| 5224 class DeferredCheckMaps FINAL : public LDeferredCode { | 5204 class DeferredCheckMaps FINAL : public LDeferredCode { |
| 5225 public: | 5205 public: |
| 5226 DeferredCheckMaps(LCodeGen* codegen, LCheckMaps* instr, Register object) | 5206 DeferredCheckMaps(LCodeGen* codegen, LCheckMaps* instr, Register object) |
| 5227 : LDeferredCode(codegen), instr_(instr), object_(object) { | 5207 : LDeferredCode(codegen), instr_(instr), object_(object) { |
| 5228 SetExit(check_maps()); | 5208 SetExit(check_maps()); |
| 5229 } | 5209 } |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5262 Label success; | 5242 Label success; |
| 5263 for (int i = 0; i < maps->size() - 1; i++) { | 5243 for (int i = 0; i < maps->size() - 1; i++) { |
| 5264 Handle<Map> map = maps->at(i).handle(); | 5244 Handle<Map> map = maps->at(i).handle(); |
| 5265 __ CompareMapAndBranch(map_reg, map, &success, eq, &success); | 5245 __ CompareMapAndBranch(map_reg, map, &success, eq, &success); |
| 5266 } | 5246 } |
| 5267 Handle<Map> map = maps->at(maps->size() - 1).handle(); | 5247 Handle<Map> map = maps->at(maps->size() - 1).handle(); |
| 5268 // Do the CompareMap() directly within the Branch() and DeoptimizeIf(). | 5248 // Do the CompareMap() directly within the Branch() and DeoptimizeIf(). |
| 5269 if (instr->hydrogen()->HasMigrationTarget()) { | 5249 if (instr->hydrogen()->HasMigrationTarget()) { |
| 5270 __ Branch(deferred->entry(), ne, map_reg, Operand(map)); | 5250 __ Branch(deferred->entry(), ne, map_reg, Operand(map)); |
| 5271 } else { | 5251 } else { |
| 5272 DeoptimizeIf(ne, instr->environment(), map_reg, Operand(map)); | 5252 DeoptimizeIf(ne, instr, map_reg, Operand(map)); |
| 5273 } | 5253 } |
| 5274 | 5254 |
| 5275 __ bind(&success); | 5255 __ bind(&success); |
| 5276 } | 5256 } |
| 5277 | 5257 |
| 5278 | 5258 |
| 5279 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { | 5259 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { |
| 5280 DoubleRegister value_reg = ToDoubleRegister(instr->unclamped()); | 5260 DoubleRegister value_reg = ToDoubleRegister(instr->unclamped()); |
| 5281 Register result_reg = ToRegister(instr->result()); | 5261 Register result_reg = ToRegister(instr->result()); |
| 5282 DoubleRegister temp_reg = ToDoubleRegister(instr->temp()); | 5262 DoubleRegister temp_reg = ToDoubleRegister(instr->temp()); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 5300 | 5280 |
| 5301 // Both smi and heap number cases are handled. | 5281 // Both smi and heap number cases are handled. |
| 5302 __ UntagAndJumpIfSmi(scratch, input_reg, &is_smi); | 5282 __ UntagAndJumpIfSmi(scratch, input_reg, &is_smi); |
| 5303 | 5283 |
| 5304 // Check for heap number | 5284 // Check for heap number |
| 5305 __ ld(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); | 5285 __ ld(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset)); |
| 5306 __ Branch(&heap_number, eq, scratch, Operand(factory()->heap_number_map())); | 5286 __ Branch(&heap_number, eq, scratch, Operand(factory()->heap_number_map())); |
| 5307 | 5287 |
| 5308 // Check for undefined. Undefined is converted to zero for clamping | 5288 // Check for undefined. Undefined is converted to zero for clamping |
| 5309 // conversions. | 5289 // conversions. |
| 5310 DeoptimizeIf(ne, instr->environment(), input_reg, | 5290 DeoptimizeIf(ne, instr, input_reg, Operand(factory()->undefined_value())); |
| 5311 Operand(factory()->undefined_value())); | |
| 5312 __ mov(result_reg, zero_reg); | 5291 __ mov(result_reg, zero_reg); |
| 5313 __ jmp(&done); | 5292 __ jmp(&done); |
| 5314 | 5293 |
| 5315 // Heap number | 5294 // Heap number |
| 5316 __ bind(&heap_number); | 5295 __ bind(&heap_number); |
| 5317 __ ldc1(double_scratch0(), FieldMemOperand(input_reg, | 5296 __ ldc1(double_scratch0(), FieldMemOperand(input_reg, |
| 5318 HeapNumber::kValueOffset)); | 5297 HeapNumber::kValueOffset)); |
| 5319 __ ClampDoubleToUint8(result_reg, double_scratch0(), temp_reg); | 5298 __ ClampDoubleToUint8(result_reg, double_scratch0(), temp_reg); |
| 5320 __ jmp(&done); | 5299 __ jmp(&done); |
| 5321 | 5300 |
| (...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5727 Deoptimizer::BailoutType type = instr->hydrogen()->type(); | 5706 Deoptimizer::BailoutType type = instr->hydrogen()->type(); |
| 5728 // TODO(danno): Stubs expect all deopts to be lazy for historical reasons (the | 5707 // TODO(danno): Stubs expect all deopts to be lazy for historical reasons (the |
| 5729 // needed return address), even though the implementation of LAZY and EAGER is | 5708 // needed return address), even though the implementation of LAZY and EAGER is |
| 5730 // now identical. When LAZY is eventually completely folded into EAGER, remove | 5709 // now identical. When LAZY is eventually completely folded into EAGER, remove |
| 5731 // the special case below. | 5710 // the special case below. |
| 5732 if (info()->IsStub() && type == Deoptimizer::EAGER) { | 5711 if (info()->IsStub() && type == Deoptimizer::EAGER) { |
| 5733 type = Deoptimizer::LAZY; | 5712 type = Deoptimizer::LAZY; |
| 5734 } | 5713 } |
| 5735 | 5714 |
| 5736 Comment(";;; deoptimize: %s", instr->hydrogen()->reason()); | 5715 Comment(";;; deoptimize: %s", instr->hydrogen()->reason()); |
| 5737 DeoptimizeIf(al, instr->environment(), type, zero_reg, Operand(zero_reg)); | 5716 DeoptimizeIf(al, instr, type, zero_reg, Operand(zero_reg)); |
| 5738 } | 5717 } |
| 5739 | 5718 |
| 5740 | 5719 |
| 5741 void LCodeGen::DoDummy(LDummy* instr) { | 5720 void LCodeGen::DoDummy(LDummy* instr) { |
| 5742 // Nothing to see here, move on! | 5721 // Nothing to see here, move on! |
| 5743 } | 5722 } |
| 5744 | 5723 |
| 5745 | 5724 |
| 5746 void LCodeGen::DoDummyUse(LDummyUse* instr) { | 5725 void LCodeGen::DoDummyUse(LDummyUse* instr) { |
| 5747 // Nothing to see here, move on! | 5726 // Nothing to see here, move on! |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5818 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); | 5797 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); |
| 5819 | 5798 |
| 5820 GenerateOsrPrologue(); | 5799 GenerateOsrPrologue(); |
| 5821 } | 5800 } |
| 5822 | 5801 |
| 5823 | 5802 |
| 5824 void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) { | 5803 void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) { |
| 5825 Register result = ToRegister(instr->result()); | 5804 Register result = ToRegister(instr->result()); |
| 5826 Register object = ToRegister(instr->object()); | 5805 Register object = ToRegister(instr->object()); |
| 5827 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); | 5806 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); |
| 5828 DeoptimizeIf(eq, instr->environment(), object, Operand(at)); | 5807 DeoptimizeIf(eq, instr, object, Operand(at)); |
| 5829 | 5808 |
| 5830 Register null_value = a5; | 5809 Register null_value = a5; |
| 5831 __ LoadRoot(null_value, Heap::kNullValueRootIndex); | 5810 __ LoadRoot(null_value, Heap::kNullValueRootIndex); |
| 5832 DeoptimizeIf(eq, instr->environment(), object, Operand(null_value)); | 5811 DeoptimizeIf(eq, instr, object, Operand(null_value)); |
| 5833 | 5812 |
| 5834 __ And(at, object, kSmiTagMask); | 5813 __ And(at, object, kSmiTagMask); |
| 5835 DeoptimizeIf(eq, instr->environment(), at, Operand(zero_reg)); | 5814 DeoptimizeIf(eq, instr, at, Operand(zero_reg)); |
| 5836 | 5815 |
| 5837 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); | 5816 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); |
| 5838 __ GetObjectType(object, a1, a1); | 5817 __ GetObjectType(object, a1, a1); |
| 5839 DeoptimizeIf(le, instr->environment(), a1, Operand(LAST_JS_PROXY_TYPE)); | 5818 DeoptimizeIf(le, instr, a1, Operand(LAST_JS_PROXY_TYPE)); |
| 5840 | 5819 |
| 5841 Label use_cache, call_runtime; | 5820 Label use_cache, call_runtime; |
| 5842 DCHECK(object.is(a0)); | 5821 DCHECK(object.is(a0)); |
| 5843 __ CheckEnumCache(null_value, &call_runtime); | 5822 __ CheckEnumCache(null_value, &call_runtime); |
| 5844 | 5823 |
| 5845 __ ld(result, FieldMemOperand(object, HeapObject::kMapOffset)); | 5824 __ ld(result, FieldMemOperand(object, HeapObject::kMapOffset)); |
| 5846 __ Branch(&use_cache); | 5825 __ Branch(&use_cache); |
| 5847 | 5826 |
| 5848 // Get the set of properties to enumerate. | 5827 // Get the set of properties to enumerate. |
| 5849 __ bind(&call_runtime); | 5828 __ bind(&call_runtime); |
| 5850 __ push(object); | 5829 __ push(object); |
| 5851 CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr); | 5830 CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr); |
| 5852 | 5831 |
| 5853 __ ld(a1, FieldMemOperand(v0, HeapObject::kMapOffset)); | 5832 __ ld(a1, FieldMemOperand(v0, HeapObject::kMapOffset)); |
| 5854 DCHECK(result.is(v0)); | 5833 DCHECK(result.is(v0)); |
| 5855 __ LoadRoot(at, Heap::kMetaMapRootIndex); | 5834 __ LoadRoot(at, Heap::kMetaMapRootIndex); |
| 5856 DeoptimizeIf(ne, instr->environment(), a1, Operand(at)); | 5835 DeoptimizeIf(ne, instr, a1, Operand(at)); |
| 5857 __ bind(&use_cache); | 5836 __ bind(&use_cache); |
| 5858 } | 5837 } |
| 5859 | 5838 |
| 5860 | 5839 |
| 5861 void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) { | 5840 void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) { |
| 5862 Register map = ToRegister(instr->map()); | 5841 Register map = ToRegister(instr->map()); |
| 5863 Register result = ToRegister(instr->result()); | 5842 Register result = ToRegister(instr->result()); |
| 5864 Label load_cache, done; | 5843 Label load_cache, done; |
| 5865 __ EnumLength(result, map); | 5844 __ EnumLength(result, map); |
| 5866 __ Branch(&load_cache, ne, result, Operand(Smi::FromInt(0))); | 5845 __ Branch(&load_cache, ne, result, Operand(Smi::FromInt(0))); |
| 5867 __ li(result, Operand(isolate()->factory()->empty_fixed_array())); | 5846 __ li(result, Operand(isolate()->factory()->empty_fixed_array())); |
| 5868 __ jmp(&done); | 5847 __ jmp(&done); |
| 5869 | 5848 |
| 5870 __ bind(&load_cache); | 5849 __ bind(&load_cache); |
| 5871 __ LoadInstanceDescriptors(map, result); | 5850 __ LoadInstanceDescriptors(map, result); |
| 5872 __ ld(result, | 5851 __ ld(result, |
| 5873 FieldMemOperand(result, DescriptorArray::kEnumCacheOffset)); | 5852 FieldMemOperand(result, DescriptorArray::kEnumCacheOffset)); |
| 5874 __ ld(result, | 5853 __ ld(result, |
| 5875 FieldMemOperand(result, FixedArray::SizeFor(instr->idx()))); | 5854 FieldMemOperand(result, FixedArray::SizeFor(instr->idx()))); |
| 5876 DeoptimizeIf(eq, instr->environment(), result, Operand(zero_reg)); | 5855 DeoptimizeIf(eq, instr, result, Operand(zero_reg)); |
| 5877 | 5856 |
| 5878 __ bind(&done); | 5857 __ bind(&done); |
| 5879 } | 5858 } |
| 5880 | 5859 |
| 5881 | 5860 |
| 5882 void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) { | 5861 void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) { |
| 5883 Register object = ToRegister(instr->value()); | 5862 Register object = ToRegister(instr->value()); |
| 5884 Register map = ToRegister(instr->map()); | 5863 Register map = ToRegister(instr->map()); |
| 5885 __ ld(scratch0(), FieldMemOperand(object, HeapObject::kMapOffset)); | 5864 __ ld(scratch0(), FieldMemOperand(object, HeapObject::kMapOffset)); |
| 5886 DeoptimizeIf(ne, instr->environment(), map, Operand(scratch0())); | 5865 DeoptimizeIf(ne, instr, map, Operand(scratch0())); |
| 5887 } | 5866 } |
| 5888 | 5867 |
| 5889 | 5868 |
| 5890 void LCodeGen::DoDeferredLoadMutableDouble(LLoadFieldByIndex* instr, | 5869 void LCodeGen::DoDeferredLoadMutableDouble(LLoadFieldByIndex* instr, |
| 5891 Register result, | 5870 Register result, |
| 5892 Register object, | 5871 Register object, |
| 5893 Register index) { | 5872 Register index) { |
| 5894 PushSafepointRegistersScope scope(this); | 5873 PushSafepointRegistersScope scope(this); |
| 5895 __ Push(object, index); | 5874 __ Push(object, index); |
| 5896 __ mov(cp, zero_reg); | 5875 __ mov(cp, zero_reg); |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5970 __ li(at, scope_info); | 5949 __ li(at, scope_info); |
| 5971 __ Push(at, ToRegister(instr->function())); | 5950 __ Push(at, ToRegister(instr->function())); |
| 5972 CallRuntime(Runtime::kPushBlockContext, 2, instr); | 5951 CallRuntime(Runtime::kPushBlockContext, 2, instr); |
| 5973 RecordSafepoint(Safepoint::kNoLazyDeopt); | 5952 RecordSafepoint(Safepoint::kNoLazyDeopt); |
| 5974 } | 5953 } |
| 5975 | 5954 |
| 5976 | 5955 |
| 5977 #undef __ | 5956 #undef __ |
| 5978 | 5957 |
| 5979 } } // namespace v8::internal | 5958 } } // namespace v8::internal |
| OLD | NEW |