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 |