OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 #if V8_TARGET_ARCH_X64 | 7 #if V8_TARGET_ARCH_X64 |
8 | 8 |
9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
10 #include "src/code-factory.h" | 10 #include "src/code-factory.h" |
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
299 | 299 |
300 bool LCodeGen::GenerateJumpTable() { | 300 bool LCodeGen::GenerateJumpTable() { |
301 Label needs_frame; | 301 Label needs_frame; |
302 if (jump_table_.length() > 0) { | 302 if (jump_table_.length() > 0) { |
303 Comment(";;; -------------------- Jump table --------------------"); | 303 Comment(";;; -------------------- Jump table --------------------"); |
304 } | 304 } |
305 for (int i = 0; i < jump_table_.length(); i++) { | 305 for (int i = 0; i < jump_table_.length(); i++) { |
306 Deoptimizer::JumpTableEntry* table_entry = &jump_table_[i]; | 306 Deoptimizer::JumpTableEntry* table_entry = &jump_table_[i]; |
307 __ bind(&table_entry->label); | 307 __ bind(&table_entry->label); |
308 Address entry = table_entry->address; | 308 Address entry = table_entry->address; |
309 Deoptimizer::BailoutType type = table_entry->bailout_type; | |
310 int id = Deoptimizer::GetDeoptimizationId(isolate(), entry, type); | |
311 DCHECK_NE(Deoptimizer::kNotDeoptimizationEntry, id); | |
312 Comment(";;; jump table entry %d: deoptimization bailout %d.", i, id); | |
313 DeoptComment(table_entry->reason); | 309 DeoptComment(table_entry->reason); |
314 if (table_entry->needs_frame) { | 310 if (table_entry->needs_frame) { |
315 DCHECK(!info()->saves_caller_doubles()); | 311 DCHECK(!info()->saves_caller_doubles()); |
316 __ Move(kScratchRegister, ExternalReference::ForDeoptEntry(entry)); | 312 __ Move(kScratchRegister, ExternalReference::ForDeoptEntry(entry)); |
317 if (needs_frame.is_bound()) { | 313 if (needs_frame.is_bound()) { |
318 __ jmp(&needs_frame); | 314 __ jmp(&needs_frame); |
319 } else { | 315 } else { |
320 __ bind(&needs_frame); | 316 __ bind(&needs_frame); |
321 __ movp(rsi, MemOperand(rbp, StandardFrameConstants::kContextOffset)); | 317 __ movp(rsi, MemOperand(rbp, StandardFrameConstants::kContextOffset)); |
322 __ pushq(rbp); | 318 __ pushq(rbp); |
(...skipping 454 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
777 Deoptimizer::Reason reason(instr->hydrogen_value()->position().raw(), | 773 Deoptimizer::Reason reason(instr->hydrogen_value()->position().raw(), |
778 instr->Mnemonic(), detail); | 774 instr->Mnemonic(), detail); |
779 DCHECK(info()->IsStub() || frame_is_built_); | 775 DCHECK(info()->IsStub() || frame_is_built_); |
780 // Go through jump table if we need to handle condition, build frame, or | 776 // Go through jump table if we need to handle condition, build frame, or |
781 // restore caller doubles. | 777 // restore caller doubles. |
782 if (cc == no_condition && frame_is_built_ && | 778 if (cc == no_condition && frame_is_built_ && |
783 !info()->saves_caller_doubles()) { | 779 !info()->saves_caller_doubles()) { |
784 DeoptComment(reason); | 780 DeoptComment(reason); |
785 __ call(entry, RelocInfo::RUNTIME_ENTRY); | 781 __ call(entry, RelocInfo::RUNTIME_ENTRY); |
786 } else { | 782 } else { |
| 783 Deoptimizer::JumpTableEntry table_entry(entry, reason, bailout_type, |
| 784 !frame_is_built_); |
787 // We often have several deopts to the same entry, reuse the last | 785 // We often have several deopts to the same entry, reuse the last |
788 // jump entry if this is the case. | 786 // jump entry if this is the case. |
789 if (jump_table_.is_empty() || | 787 if (jump_table_.is_empty() || |
790 jump_table_.last().address != entry || | 788 !table_entry.IsEquivalentTo(jump_table_.last())) { |
791 jump_table_.last().needs_frame != !frame_is_built_ || | |
792 jump_table_.last().bailout_type != bailout_type) { | |
793 Deoptimizer::JumpTableEntry table_entry(entry, reason, bailout_type, | |
794 !frame_is_built_); | |
795 jump_table_.Add(table_entry, zone()); | 789 jump_table_.Add(table_entry, zone()); |
796 } | 790 } |
797 if (cc == no_condition) { | 791 if (cc == no_condition) { |
798 __ jmp(&jump_table_.last().label); | 792 __ jmp(&jump_table_.last().label); |
799 } else { | 793 } else { |
800 __ j(cc, &jump_table_.last().label); | 794 __ j(cc, &jump_table_.last().label); |
801 } | 795 } |
802 } | 796 } |
803 } | 797 } |
804 | 798 |
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1032 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); | 1026 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); |
1033 Label dividend_is_not_negative, done; | 1027 Label dividend_is_not_negative, done; |
1034 if (hmod->CheckFlag(HValue::kLeftCanBeNegative)) { | 1028 if (hmod->CheckFlag(HValue::kLeftCanBeNegative)) { |
1035 __ testl(dividend, dividend); | 1029 __ testl(dividend, dividend); |
1036 __ j(not_sign, ÷nd_is_not_negative, Label::kNear); | 1030 __ j(not_sign, ÷nd_is_not_negative, Label::kNear); |
1037 // Note that this is correct even for kMinInt operands. | 1031 // Note that this is correct even for kMinInt operands. |
1038 __ negl(dividend); | 1032 __ negl(dividend); |
1039 __ andl(dividend, Immediate(mask)); | 1033 __ andl(dividend, Immediate(mask)); |
1040 __ negl(dividend); | 1034 __ negl(dividend); |
1041 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1035 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1042 DeoptimizeIf(zero, instr); | 1036 DeoptimizeIf(zero, instr, "minus zero"); |
1043 } | 1037 } |
1044 __ jmp(&done, Label::kNear); | 1038 __ jmp(&done, Label::kNear); |
1045 } | 1039 } |
1046 | 1040 |
1047 __ bind(÷nd_is_not_negative); | 1041 __ bind(÷nd_is_not_negative); |
1048 __ andl(dividend, Immediate(mask)); | 1042 __ andl(dividend, Immediate(mask)); |
1049 __ bind(&done); | 1043 __ bind(&done); |
1050 } | 1044 } |
1051 | 1045 |
1052 | 1046 |
1053 void LCodeGen::DoModByConstI(LModByConstI* instr) { | 1047 void LCodeGen::DoModByConstI(LModByConstI* instr) { |
1054 Register dividend = ToRegister(instr->dividend()); | 1048 Register dividend = ToRegister(instr->dividend()); |
1055 int32_t divisor = instr->divisor(); | 1049 int32_t divisor = instr->divisor(); |
1056 DCHECK(ToRegister(instr->result()).is(rax)); | 1050 DCHECK(ToRegister(instr->result()).is(rax)); |
1057 | 1051 |
1058 if (divisor == 0) { | 1052 if (divisor == 0) { |
1059 DeoptimizeIf(no_condition, instr); | 1053 DeoptimizeIf(no_condition, instr, "division by zero"); |
1060 return; | 1054 return; |
1061 } | 1055 } |
1062 | 1056 |
1063 __ TruncatingDiv(dividend, Abs(divisor)); | 1057 __ TruncatingDiv(dividend, Abs(divisor)); |
1064 __ imull(rdx, rdx, Immediate(Abs(divisor))); | 1058 __ imull(rdx, rdx, Immediate(Abs(divisor))); |
1065 __ movl(rax, dividend); | 1059 __ movl(rax, dividend); |
1066 __ subl(rax, rdx); | 1060 __ subl(rax, rdx); |
1067 | 1061 |
1068 // Check for negative zero. | 1062 // Check for negative zero. |
1069 HMod* hmod = instr->hydrogen(); | 1063 HMod* hmod = instr->hydrogen(); |
1070 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1064 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1071 Label remainder_not_zero; | 1065 Label remainder_not_zero; |
1072 __ j(not_zero, &remainder_not_zero, Label::kNear); | 1066 __ j(not_zero, &remainder_not_zero, Label::kNear); |
1073 __ cmpl(dividend, Immediate(0)); | 1067 __ cmpl(dividend, Immediate(0)); |
1074 DeoptimizeIf(less, instr); | 1068 DeoptimizeIf(less, instr, "minus zero"); |
1075 __ bind(&remainder_not_zero); | 1069 __ bind(&remainder_not_zero); |
1076 } | 1070 } |
1077 } | 1071 } |
1078 | 1072 |
1079 | 1073 |
1080 void LCodeGen::DoModI(LModI* instr) { | 1074 void LCodeGen::DoModI(LModI* instr) { |
1081 HMod* hmod = instr->hydrogen(); | 1075 HMod* hmod = instr->hydrogen(); |
1082 | 1076 |
1083 Register left_reg = ToRegister(instr->left()); | 1077 Register left_reg = ToRegister(instr->left()); |
1084 DCHECK(left_reg.is(rax)); | 1078 DCHECK(left_reg.is(rax)); |
1085 Register right_reg = ToRegister(instr->right()); | 1079 Register right_reg = ToRegister(instr->right()); |
1086 DCHECK(!right_reg.is(rax)); | 1080 DCHECK(!right_reg.is(rax)); |
1087 DCHECK(!right_reg.is(rdx)); | 1081 DCHECK(!right_reg.is(rdx)); |
1088 Register result_reg = ToRegister(instr->result()); | 1082 Register result_reg = ToRegister(instr->result()); |
1089 DCHECK(result_reg.is(rdx)); | 1083 DCHECK(result_reg.is(rdx)); |
1090 | 1084 |
1091 Label done; | 1085 Label done; |
1092 // Check for x % 0, idiv would signal a divide error. We have to | 1086 // Check for x % 0, idiv would signal a divide error. We have to |
1093 // deopt in this case because we can't return a NaN. | 1087 // deopt in this case because we can't return a NaN. |
1094 if (hmod->CheckFlag(HValue::kCanBeDivByZero)) { | 1088 if (hmod->CheckFlag(HValue::kCanBeDivByZero)) { |
1095 __ testl(right_reg, right_reg); | 1089 __ testl(right_reg, right_reg); |
1096 DeoptimizeIf(zero, instr); | 1090 DeoptimizeIf(zero, instr, "division by zero"); |
1097 } | 1091 } |
1098 | 1092 |
1099 // Check for kMinInt % -1, idiv would signal a divide error. We | 1093 // Check for kMinInt % -1, idiv would signal a divide error. We |
1100 // have to deopt if we care about -0, because we can't return that. | 1094 // have to deopt if we care about -0, because we can't return that. |
1101 if (hmod->CheckFlag(HValue::kCanOverflow)) { | 1095 if (hmod->CheckFlag(HValue::kCanOverflow)) { |
1102 Label no_overflow_possible; | 1096 Label no_overflow_possible; |
1103 __ cmpl(left_reg, Immediate(kMinInt)); | 1097 __ cmpl(left_reg, Immediate(kMinInt)); |
1104 __ j(not_zero, &no_overflow_possible, Label::kNear); | 1098 __ j(not_zero, &no_overflow_possible, Label::kNear); |
1105 __ cmpl(right_reg, Immediate(-1)); | 1099 __ cmpl(right_reg, Immediate(-1)); |
1106 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1100 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1107 DeoptimizeIf(equal, instr); | 1101 DeoptimizeIf(equal, instr, "minus zero"); |
1108 } else { | 1102 } else { |
1109 __ j(not_equal, &no_overflow_possible, Label::kNear); | 1103 __ j(not_equal, &no_overflow_possible, Label::kNear); |
1110 __ Set(result_reg, 0); | 1104 __ Set(result_reg, 0); |
1111 __ jmp(&done, Label::kNear); | 1105 __ jmp(&done, Label::kNear); |
1112 } | 1106 } |
1113 __ bind(&no_overflow_possible); | 1107 __ bind(&no_overflow_possible); |
1114 } | 1108 } |
1115 | 1109 |
1116 // Sign extend dividend in eax into edx:eax, since we are using only the low | 1110 // Sign extend dividend in eax into edx:eax, since we are using only the low |
1117 // 32 bits of the values. | 1111 // 32 bits of the values. |
1118 __ cdq(); | 1112 __ cdq(); |
1119 | 1113 |
1120 // If we care about -0, test if the dividend is <0 and the result is 0. | 1114 // If we care about -0, test if the dividend is <0 and the result is 0. |
1121 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1115 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1122 Label positive_left; | 1116 Label positive_left; |
1123 __ testl(left_reg, left_reg); | 1117 __ testl(left_reg, left_reg); |
1124 __ j(not_sign, &positive_left, Label::kNear); | 1118 __ j(not_sign, &positive_left, Label::kNear); |
1125 __ idivl(right_reg); | 1119 __ idivl(right_reg); |
1126 __ testl(result_reg, result_reg); | 1120 __ testl(result_reg, result_reg); |
1127 DeoptimizeIf(zero, instr); | 1121 DeoptimizeIf(zero, instr, "minus zero"); |
1128 __ jmp(&done, Label::kNear); | 1122 __ jmp(&done, Label::kNear); |
1129 __ bind(&positive_left); | 1123 __ bind(&positive_left); |
1130 } | 1124 } |
1131 __ idivl(right_reg); | 1125 __ idivl(right_reg); |
1132 __ bind(&done); | 1126 __ bind(&done); |
1133 } | 1127 } |
1134 | 1128 |
1135 | 1129 |
1136 void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) { | 1130 void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) { |
1137 Register dividend = ToRegister(instr->dividend()); | 1131 Register dividend = ToRegister(instr->dividend()); |
1138 int32_t divisor = instr->divisor(); | 1132 int32_t divisor = instr->divisor(); |
1139 DCHECK(dividend.is(ToRegister(instr->result()))); | 1133 DCHECK(dividend.is(ToRegister(instr->result()))); |
1140 | 1134 |
1141 // If the divisor is positive, things are easy: There can be no deopts and we | 1135 // If the divisor is positive, things are easy: There can be no deopts and we |
1142 // can simply do an arithmetic right shift. | 1136 // can simply do an arithmetic right shift. |
1143 if (divisor == 1) return; | 1137 if (divisor == 1) return; |
1144 int32_t shift = WhichPowerOf2Abs(divisor); | 1138 int32_t shift = WhichPowerOf2Abs(divisor); |
1145 if (divisor > 1) { | 1139 if (divisor > 1) { |
1146 __ sarl(dividend, Immediate(shift)); | 1140 __ sarl(dividend, Immediate(shift)); |
1147 return; | 1141 return; |
1148 } | 1142 } |
1149 | 1143 |
1150 // If the divisor is negative, we have to negate and handle edge cases. | 1144 // If the divisor is negative, we have to negate and handle edge cases. |
1151 __ negl(dividend); | 1145 __ negl(dividend); |
1152 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1146 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1153 DeoptimizeIf(zero, instr); | 1147 DeoptimizeIf(zero, instr, "minus zero"); |
1154 } | 1148 } |
1155 | 1149 |
1156 // Dividing by -1 is basically negation, unless we overflow. | 1150 // Dividing by -1 is basically negation, unless we overflow. |
1157 if (divisor == -1) { | 1151 if (divisor == -1) { |
1158 if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { | 1152 if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { |
1159 DeoptimizeIf(overflow, instr); | 1153 DeoptimizeIf(overflow, instr, "overflow"); |
1160 } | 1154 } |
1161 return; | 1155 return; |
1162 } | 1156 } |
1163 | 1157 |
1164 // If the negation could not overflow, simply shifting is OK. | 1158 // If the negation could not overflow, simply shifting is OK. |
1165 if (!instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { | 1159 if (!instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { |
1166 __ sarl(dividend, Immediate(shift)); | 1160 __ sarl(dividend, Immediate(shift)); |
1167 return; | 1161 return; |
1168 } | 1162 } |
1169 | 1163 |
1170 Label not_kmin_int, done; | 1164 Label not_kmin_int, done; |
1171 __ j(no_overflow, ¬_kmin_int, Label::kNear); | 1165 __ j(no_overflow, ¬_kmin_int, Label::kNear); |
1172 __ movl(dividend, Immediate(kMinInt / divisor)); | 1166 __ movl(dividend, Immediate(kMinInt / divisor)); |
1173 __ jmp(&done, Label::kNear); | 1167 __ jmp(&done, Label::kNear); |
1174 __ bind(¬_kmin_int); | 1168 __ bind(¬_kmin_int); |
1175 __ sarl(dividend, Immediate(shift)); | 1169 __ sarl(dividend, Immediate(shift)); |
1176 __ bind(&done); | 1170 __ bind(&done); |
1177 } | 1171 } |
1178 | 1172 |
1179 | 1173 |
1180 void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) { | 1174 void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) { |
1181 Register dividend = ToRegister(instr->dividend()); | 1175 Register dividend = ToRegister(instr->dividend()); |
1182 int32_t divisor = instr->divisor(); | 1176 int32_t divisor = instr->divisor(); |
1183 DCHECK(ToRegister(instr->result()).is(rdx)); | 1177 DCHECK(ToRegister(instr->result()).is(rdx)); |
1184 | 1178 |
1185 if (divisor == 0) { | 1179 if (divisor == 0) { |
1186 DeoptimizeIf(no_condition, instr); | 1180 DeoptimizeIf(no_condition, instr, "division by zero"); |
1187 return; | 1181 return; |
1188 } | 1182 } |
1189 | 1183 |
1190 // Check for (0 / -x) that will produce negative zero. | 1184 // Check for (0 / -x) that will produce negative zero. |
1191 HMathFloorOfDiv* hdiv = instr->hydrogen(); | 1185 HMathFloorOfDiv* hdiv = instr->hydrogen(); |
1192 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { | 1186 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { |
1193 __ testl(dividend, dividend); | 1187 __ testl(dividend, dividend); |
1194 DeoptimizeIf(zero, instr); | 1188 DeoptimizeIf(zero, instr, "minus zero"); |
1195 } | 1189 } |
1196 | 1190 |
1197 // Easy case: We need no dynamic check for the dividend and the flooring | 1191 // Easy case: We need no dynamic check for the dividend and the flooring |
1198 // division is the same as the truncating division. | 1192 // division is the same as the truncating division. |
1199 if ((divisor > 0 && !hdiv->CheckFlag(HValue::kLeftCanBeNegative)) || | 1193 if ((divisor > 0 && !hdiv->CheckFlag(HValue::kLeftCanBeNegative)) || |
1200 (divisor < 0 && !hdiv->CheckFlag(HValue::kLeftCanBePositive))) { | 1194 (divisor < 0 && !hdiv->CheckFlag(HValue::kLeftCanBePositive))) { |
1201 __ TruncatingDiv(dividend, Abs(divisor)); | 1195 __ TruncatingDiv(dividend, Abs(divisor)); |
1202 if (divisor < 0) __ negl(rdx); | 1196 if (divisor < 0) __ negl(rdx); |
1203 return; | 1197 return; |
1204 } | 1198 } |
(...skipping 26 matching lines...) Expand all Loading... |
1231 Register result = ToRegister(instr->result()); | 1225 Register result = ToRegister(instr->result()); |
1232 DCHECK(dividend.is(rax)); | 1226 DCHECK(dividend.is(rax)); |
1233 DCHECK(remainder.is(rdx)); | 1227 DCHECK(remainder.is(rdx)); |
1234 DCHECK(result.is(rax)); | 1228 DCHECK(result.is(rax)); |
1235 DCHECK(!divisor.is(rax)); | 1229 DCHECK(!divisor.is(rax)); |
1236 DCHECK(!divisor.is(rdx)); | 1230 DCHECK(!divisor.is(rdx)); |
1237 | 1231 |
1238 // Check for x / 0. | 1232 // Check for x / 0. |
1239 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { | 1233 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { |
1240 __ testl(divisor, divisor); | 1234 __ testl(divisor, divisor); |
1241 DeoptimizeIf(zero, instr); | 1235 DeoptimizeIf(zero, instr, "division by zero"); |
1242 } | 1236 } |
1243 | 1237 |
1244 // Check for (0 / -x) that will produce negative zero. | 1238 // Check for (0 / -x) that will produce negative zero. |
1245 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1239 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1246 Label dividend_not_zero; | 1240 Label dividend_not_zero; |
1247 __ testl(dividend, dividend); | 1241 __ testl(dividend, dividend); |
1248 __ j(not_zero, ÷nd_not_zero, Label::kNear); | 1242 __ j(not_zero, ÷nd_not_zero, Label::kNear); |
1249 __ testl(divisor, divisor); | 1243 __ testl(divisor, divisor); |
1250 DeoptimizeIf(sign, instr); | 1244 DeoptimizeIf(sign, instr, "minus zero"); |
1251 __ bind(÷nd_not_zero); | 1245 __ bind(÷nd_not_zero); |
1252 } | 1246 } |
1253 | 1247 |
1254 // Check for (kMinInt / -1). | 1248 // Check for (kMinInt / -1). |
1255 if (hdiv->CheckFlag(HValue::kCanOverflow)) { | 1249 if (hdiv->CheckFlag(HValue::kCanOverflow)) { |
1256 Label dividend_not_min_int; | 1250 Label dividend_not_min_int; |
1257 __ cmpl(dividend, Immediate(kMinInt)); | 1251 __ cmpl(dividend, Immediate(kMinInt)); |
1258 __ j(not_zero, ÷nd_not_min_int, Label::kNear); | 1252 __ j(not_zero, ÷nd_not_min_int, Label::kNear); |
1259 __ cmpl(divisor, Immediate(-1)); | 1253 __ cmpl(divisor, Immediate(-1)); |
1260 DeoptimizeIf(zero, instr); | 1254 DeoptimizeIf(zero, instr, "overflow"); |
1261 __ bind(÷nd_not_min_int); | 1255 __ bind(÷nd_not_min_int); |
1262 } | 1256 } |
1263 | 1257 |
1264 // Sign extend to rdx (= remainder). | 1258 // Sign extend to rdx (= remainder). |
1265 __ cdq(); | 1259 __ cdq(); |
1266 __ idivl(divisor); | 1260 __ idivl(divisor); |
1267 | 1261 |
1268 Label done; | 1262 Label done; |
1269 __ testl(remainder, remainder); | 1263 __ testl(remainder, remainder); |
1270 __ j(zero, &done, Label::kNear); | 1264 __ j(zero, &done, Label::kNear); |
1271 __ xorl(remainder, divisor); | 1265 __ xorl(remainder, divisor); |
1272 __ sarl(remainder, Immediate(31)); | 1266 __ sarl(remainder, Immediate(31)); |
1273 __ addl(result, remainder); | 1267 __ addl(result, remainder); |
1274 __ bind(&done); | 1268 __ bind(&done); |
1275 } | 1269 } |
1276 | 1270 |
1277 | 1271 |
1278 void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) { | 1272 void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) { |
1279 Register dividend = ToRegister(instr->dividend()); | 1273 Register dividend = ToRegister(instr->dividend()); |
1280 int32_t divisor = instr->divisor(); | 1274 int32_t divisor = instr->divisor(); |
1281 Register result = ToRegister(instr->result()); | 1275 Register result = ToRegister(instr->result()); |
1282 DCHECK(divisor == kMinInt || base::bits::IsPowerOfTwo32(Abs(divisor))); | 1276 DCHECK(divisor == kMinInt || base::bits::IsPowerOfTwo32(Abs(divisor))); |
1283 DCHECK(!result.is(dividend)); | 1277 DCHECK(!result.is(dividend)); |
1284 | 1278 |
1285 // Check for (0 / -x) that will produce negative zero. | 1279 // Check for (0 / -x) that will produce negative zero. |
1286 HDiv* hdiv = instr->hydrogen(); | 1280 HDiv* hdiv = instr->hydrogen(); |
1287 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { | 1281 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { |
1288 __ testl(dividend, dividend); | 1282 __ testl(dividend, dividend); |
1289 DeoptimizeIf(zero, instr); | 1283 DeoptimizeIf(zero, instr, "minus zero"); |
1290 } | 1284 } |
1291 // Check for (kMinInt / -1). | 1285 // Check for (kMinInt / -1). |
1292 if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) { | 1286 if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) { |
1293 __ cmpl(dividend, Immediate(kMinInt)); | 1287 __ cmpl(dividend, Immediate(kMinInt)); |
1294 DeoptimizeIf(zero, instr); | 1288 DeoptimizeIf(zero, instr, "overflow"); |
1295 } | 1289 } |
1296 // Deoptimize if remainder will not be 0. | 1290 // Deoptimize if remainder will not be 0. |
1297 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) && | 1291 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) && |
1298 divisor != 1 && divisor != -1) { | 1292 divisor != 1 && divisor != -1) { |
1299 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); | 1293 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); |
1300 __ testl(dividend, Immediate(mask)); | 1294 __ testl(dividend, Immediate(mask)); |
1301 DeoptimizeIf(not_zero, instr); | 1295 DeoptimizeIf(not_zero, instr, "remainder not zero"); |
1302 } | 1296 } |
1303 __ Move(result, dividend); | 1297 __ Move(result, dividend); |
1304 int32_t shift = WhichPowerOf2Abs(divisor); | 1298 int32_t shift = WhichPowerOf2Abs(divisor); |
1305 if (shift > 0) { | 1299 if (shift > 0) { |
1306 // The arithmetic shift is always OK, the 'if' is an optimization only. | 1300 // The arithmetic shift is always OK, the 'if' is an optimization only. |
1307 if (shift > 1) __ sarl(result, Immediate(31)); | 1301 if (shift > 1) __ sarl(result, Immediate(31)); |
1308 __ shrl(result, Immediate(32 - shift)); | 1302 __ shrl(result, Immediate(32 - shift)); |
1309 __ addl(result, dividend); | 1303 __ addl(result, dividend); |
1310 __ sarl(result, Immediate(shift)); | 1304 __ sarl(result, Immediate(shift)); |
1311 } | 1305 } |
1312 if (divisor < 0) __ negl(result); | 1306 if (divisor < 0) __ negl(result); |
1313 } | 1307 } |
1314 | 1308 |
1315 | 1309 |
1316 void LCodeGen::DoDivByConstI(LDivByConstI* instr) { | 1310 void LCodeGen::DoDivByConstI(LDivByConstI* instr) { |
1317 Register dividend = ToRegister(instr->dividend()); | 1311 Register dividend = ToRegister(instr->dividend()); |
1318 int32_t divisor = instr->divisor(); | 1312 int32_t divisor = instr->divisor(); |
1319 DCHECK(ToRegister(instr->result()).is(rdx)); | 1313 DCHECK(ToRegister(instr->result()).is(rdx)); |
1320 | 1314 |
1321 if (divisor == 0) { | 1315 if (divisor == 0) { |
1322 DeoptimizeIf(no_condition, instr); | 1316 DeoptimizeIf(no_condition, instr, "division by zero"); |
1323 return; | 1317 return; |
1324 } | 1318 } |
1325 | 1319 |
1326 // Check for (0 / -x) that will produce negative zero. | 1320 // Check for (0 / -x) that will produce negative zero. |
1327 HDiv* hdiv = instr->hydrogen(); | 1321 HDiv* hdiv = instr->hydrogen(); |
1328 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { | 1322 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { |
1329 __ testl(dividend, dividend); | 1323 __ testl(dividend, dividend); |
1330 DeoptimizeIf(zero, instr); | 1324 DeoptimizeIf(zero, instr, "minus zero"); |
1331 } | 1325 } |
1332 | 1326 |
1333 __ TruncatingDiv(dividend, Abs(divisor)); | 1327 __ TruncatingDiv(dividend, Abs(divisor)); |
1334 if (divisor < 0) __ negl(rdx); | 1328 if (divisor < 0) __ negl(rdx); |
1335 | 1329 |
1336 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) { | 1330 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) { |
1337 __ movl(rax, rdx); | 1331 __ movl(rax, rdx); |
1338 __ imull(rax, rax, Immediate(divisor)); | 1332 __ imull(rax, rax, Immediate(divisor)); |
1339 __ subl(rax, dividend); | 1333 __ subl(rax, dividend); |
1340 DeoptimizeIf(not_equal, instr); | 1334 DeoptimizeIf(not_equal, instr, "remainder not zero"); |
1341 } | 1335 } |
1342 } | 1336 } |
1343 | 1337 |
1344 | 1338 |
1345 // TODO(svenpanne) Refactor this to avoid code duplication with DoFlooringDivI. | 1339 // TODO(svenpanne) Refactor this to avoid code duplication with DoFlooringDivI. |
1346 void LCodeGen::DoDivI(LDivI* instr) { | 1340 void LCodeGen::DoDivI(LDivI* instr) { |
1347 HBinaryOperation* hdiv = instr->hydrogen(); | 1341 HBinaryOperation* hdiv = instr->hydrogen(); |
1348 Register dividend = ToRegister(instr->dividend()); | 1342 Register dividend = ToRegister(instr->dividend()); |
1349 Register divisor = ToRegister(instr->divisor()); | 1343 Register divisor = ToRegister(instr->divisor()); |
1350 Register remainder = ToRegister(instr->temp()); | 1344 Register remainder = ToRegister(instr->temp()); |
1351 DCHECK(dividend.is(rax)); | 1345 DCHECK(dividend.is(rax)); |
1352 DCHECK(remainder.is(rdx)); | 1346 DCHECK(remainder.is(rdx)); |
1353 DCHECK(ToRegister(instr->result()).is(rax)); | 1347 DCHECK(ToRegister(instr->result()).is(rax)); |
1354 DCHECK(!divisor.is(rax)); | 1348 DCHECK(!divisor.is(rax)); |
1355 DCHECK(!divisor.is(rdx)); | 1349 DCHECK(!divisor.is(rdx)); |
1356 | 1350 |
1357 // Check for x / 0. | 1351 // Check for x / 0. |
1358 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { | 1352 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { |
1359 __ testl(divisor, divisor); | 1353 __ testl(divisor, divisor); |
1360 DeoptimizeIf(zero, instr); | 1354 DeoptimizeIf(zero, instr, "division by zero"); |
1361 } | 1355 } |
1362 | 1356 |
1363 // Check for (0 / -x) that will produce negative zero. | 1357 // Check for (0 / -x) that will produce negative zero. |
1364 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1358 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1365 Label dividend_not_zero; | 1359 Label dividend_not_zero; |
1366 __ testl(dividend, dividend); | 1360 __ testl(dividend, dividend); |
1367 __ j(not_zero, ÷nd_not_zero, Label::kNear); | 1361 __ j(not_zero, ÷nd_not_zero, Label::kNear); |
1368 __ testl(divisor, divisor); | 1362 __ testl(divisor, divisor); |
1369 DeoptimizeIf(sign, instr); | 1363 DeoptimizeIf(sign, instr, "minus zero"); |
1370 __ bind(÷nd_not_zero); | 1364 __ bind(÷nd_not_zero); |
1371 } | 1365 } |
1372 | 1366 |
1373 // Check for (kMinInt / -1). | 1367 // Check for (kMinInt / -1). |
1374 if (hdiv->CheckFlag(HValue::kCanOverflow)) { | 1368 if (hdiv->CheckFlag(HValue::kCanOverflow)) { |
1375 Label dividend_not_min_int; | 1369 Label dividend_not_min_int; |
1376 __ cmpl(dividend, Immediate(kMinInt)); | 1370 __ cmpl(dividend, Immediate(kMinInt)); |
1377 __ j(not_zero, ÷nd_not_min_int, Label::kNear); | 1371 __ j(not_zero, ÷nd_not_min_int, Label::kNear); |
1378 __ cmpl(divisor, Immediate(-1)); | 1372 __ cmpl(divisor, Immediate(-1)); |
1379 DeoptimizeIf(zero, instr); | 1373 DeoptimizeIf(zero, instr, "overflow"); |
1380 __ bind(÷nd_not_min_int); | 1374 __ bind(÷nd_not_min_int); |
1381 } | 1375 } |
1382 | 1376 |
1383 // Sign extend to rdx (= remainder). | 1377 // Sign extend to rdx (= remainder). |
1384 __ cdq(); | 1378 __ cdq(); |
1385 __ idivl(divisor); | 1379 __ idivl(divisor); |
1386 | 1380 |
1387 if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { | 1381 if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { |
1388 // Deoptimize if remainder is not 0. | 1382 // Deoptimize if remainder is not 0. |
1389 __ testl(remainder, remainder); | 1383 __ testl(remainder, remainder); |
1390 DeoptimizeIf(not_zero, instr); | 1384 DeoptimizeIf(not_zero, instr, "remainder not zero"); |
1391 } | 1385 } |
1392 } | 1386 } |
1393 | 1387 |
1394 | 1388 |
1395 void LCodeGen::DoMulI(LMulI* instr) { | 1389 void LCodeGen::DoMulI(LMulI* instr) { |
1396 Register left = ToRegister(instr->left()); | 1390 Register left = ToRegister(instr->left()); |
1397 LOperand* right = instr->right(); | 1391 LOperand* right = instr->right(); |
1398 | 1392 |
1399 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1393 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1400 if (instr->hydrogen_value()->representation().IsSmi()) { | 1394 if (instr->hydrogen_value()->representation().IsSmi()) { |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1457 } else { | 1451 } else { |
1458 if (instr->hydrogen_value()->representation().IsSmi()) { | 1452 if (instr->hydrogen_value()->representation().IsSmi()) { |
1459 __ SmiToInteger64(left, left); | 1453 __ SmiToInteger64(left, left); |
1460 __ imulp(left, ToRegister(right)); | 1454 __ imulp(left, ToRegister(right)); |
1461 } else { | 1455 } else { |
1462 __ imull(left, ToRegister(right)); | 1456 __ imull(left, ToRegister(right)); |
1463 } | 1457 } |
1464 } | 1458 } |
1465 | 1459 |
1466 if (can_overflow) { | 1460 if (can_overflow) { |
1467 DeoptimizeIf(overflow, instr); | 1461 DeoptimizeIf(overflow, instr, "overflow"); |
1468 } | 1462 } |
1469 | 1463 |
1470 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 1464 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
1471 // Bail out if the result is supposed to be negative zero. | 1465 // Bail out if the result is supposed to be negative zero. |
1472 Label done; | 1466 Label done; |
1473 if (instr->hydrogen_value()->representation().IsSmi()) { | 1467 if (instr->hydrogen_value()->representation().IsSmi()) { |
1474 __ testp(left, left); | 1468 __ testp(left, left); |
1475 } else { | 1469 } else { |
1476 __ testl(left, left); | 1470 __ testl(left, left); |
1477 } | 1471 } |
1478 __ j(not_zero, &done, Label::kNear); | 1472 __ j(not_zero, &done, Label::kNear); |
1479 if (right->IsConstantOperand()) { | 1473 if (right->IsConstantOperand()) { |
1480 // Constant can't be represented as 32-bit Smi due to immediate size | 1474 // Constant can't be represented as 32-bit Smi due to immediate size |
1481 // limit. | 1475 // limit. |
1482 DCHECK(SmiValuesAre32Bits() | 1476 DCHECK(SmiValuesAre32Bits() |
1483 ? !instr->hydrogen_value()->representation().IsSmi() | 1477 ? !instr->hydrogen_value()->representation().IsSmi() |
1484 : SmiValuesAre31Bits()); | 1478 : SmiValuesAre31Bits()); |
1485 if (ToInteger32(LConstantOperand::cast(right)) < 0) { | 1479 if (ToInteger32(LConstantOperand::cast(right)) < 0) { |
1486 DeoptimizeIf(no_condition, instr); | 1480 DeoptimizeIf(no_condition, instr, "minus zero"); |
1487 } else if (ToInteger32(LConstantOperand::cast(right)) == 0) { | 1481 } else if (ToInteger32(LConstantOperand::cast(right)) == 0) { |
1488 __ cmpl(kScratchRegister, Immediate(0)); | 1482 __ cmpl(kScratchRegister, Immediate(0)); |
1489 DeoptimizeIf(less, instr); | 1483 DeoptimizeIf(less, instr, "minus zero"); |
1490 } | 1484 } |
1491 } else if (right->IsStackSlot()) { | 1485 } else if (right->IsStackSlot()) { |
1492 if (instr->hydrogen_value()->representation().IsSmi()) { | 1486 if (instr->hydrogen_value()->representation().IsSmi()) { |
1493 __ orp(kScratchRegister, ToOperand(right)); | 1487 __ orp(kScratchRegister, ToOperand(right)); |
1494 } else { | 1488 } else { |
1495 __ orl(kScratchRegister, ToOperand(right)); | 1489 __ orl(kScratchRegister, ToOperand(right)); |
1496 } | 1490 } |
1497 DeoptimizeIf(sign, instr); | 1491 DeoptimizeIf(sign, instr, "minus zero"); |
1498 } else { | 1492 } else { |
1499 // Test the non-zero operand for negative sign. | 1493 // Test the non-zero operand for negative sign. |
1500 if (instr->hydrogen_value()->representation().IsSmi()) { | 1494 if (instr->hydrogen_value()->representation().IsSmi()) { |
1501 __ orp(kScratchRegister, ToRegister(right)); | 1495 __ orp(kScratchRegister, ToRegister(right)); |
1502 } else { | 1496 } else { |
1503 __ orl(kScratchRegister, ToRegister(right)); | 1497 __ orl(kScratchRegister, ToRegister(right)); |
1504 } | 1498 } |
1505 DeoptimizeIf(sign, instr); | 1499 DeoptimizeIf(sign, instr, "minus zero"); |
1506 } | 1500 } |
1507 __ bind(&done); | 1501 __ bind(&done); |
1508 } | 1502 } |
1509 } | 1503 } |
1510 | 1504 |
1511 | 1505 |
1512 void LCodeGen::DoBitI(LBitI* instr) { | 1506 void LCodeGen::DoBitI(LBitI* instr) { |
1513 LOperand* left = instr->left(); | 1507 LOperand* left = instr->left(); |
1514 LOperand* right = instr->right(); | 1508 LOperand* right = instr->right(); |
1515 DCHECK(left->Equals(instr->result())); | 1509 DCHECK(left->Equals(instr->result())); |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1608 case Token::ROR: | 1602 case Token::ROR: |
1609 __ rorl_cl(ToRegister(left)); | 1603 __ rorl_cl(ToRegister(left)); |
1610 break; | 1604 break; |
1611 case Token::SAR: | 1605 case Token::SAR: |
1612 __ sarl_cl(ToRegister(left)); | 1606 __ sarl_cl(ToRegister(left)); |
1613 break; | 1607 break; |
1614 case Token::SHR: | 1608 case Token::SHR: |
1615 __ shrl_cl(ToRegister(left)); | 1609 __ shrl_cl(ToRegister(left)); |
1616 if (instr->can_deopt()) { | 1610 if (instr->can_deopt()) { |
1617 __ testl(ToRegister(left), ToRegister(left)); | 1611 __ testl(ToRegister(left), ToRegister(left)); |
1618 DeoptimizeIf(negative, instr); | 1612 DeoptimizeIf(negative, instr, "value to shift was negative"); |
1619 } | 1613 } |
1620 break; | 1614 break; |
1621 case Token::SHL: | 1615 case Token::SHL: |
1622 __ shll_cl(ToRegister(left)); | 1616 __ shll_cl(ToRegister(left)); |
1623 break; | 1617 break; |
1624 default: | 1618 default: |
1625 UNREACHABLE(); | 1619 UNREACHABLE(); |
1626 break; | 1620 break; |
1627 } | 1621 } |
1628 } else { | 1622 } else { |
1629 int32_t value = ToInteger32(LConstantOperand::cast(right)); | 1623 int32_t value = ToInteger32(LConstantOperand::cast(right)); |
1630 uint8_t shift_count = static_cast<uint8_t>(value & 0x1F); | 1624 uint8_t shift_count = static_cast<uint8_t>(value & 0x1F); |
1631 switch (instr->op()) { | 1625 switch (instr->op()) { |
1632 case Token::ROR: | 1626 case Token::ROR: |
1633 if (shift_count != 0) { | 1627 if (shift_count != 0) { |
1634 __ rorl(ToRegister(left), Immediate(shift_count)); | 1628 __ rorl(ToRegister(left), Immediate(shift_count)); |
1635 } | 1629 } |
1636 break; | 1630 break; |
1637 case Token::SAR: | 1631 case Token::SAR: |
1638 if (shift_count != 0) { | 1632 if (shift_count != 0) { |
1639 __ sarl(ToRegister(left), Immediate(shift_count)); | 1633 __ sarl(ToRegister(left), Immediate(shift_count)); |
1640 } | 1634 } |
1641 break; | 1635 break; |
1642 case Token::SHR: | 1636 case Token::SHR: |
1643 if (shift_count != 0) { | 1637 if (shift_count != 0) { |
1644 __ shrl(ToRegister(left), Immediate(shift_count)); | 1638 __ shrl(ToRegister(left), Immediate(shift_count)); |
1645 } else if (instr->can_deopt()) { | 1639 } else if (instr->can_deopt()) { |
1646 __ testl(ToRegister(left), ToRegister(left)); | 1640 __ testl(ToRegister(left), ToRegister(left)); |
1647 DeoptimizeIf(negative, instr); | 1641 DeoptimizeIf(negative, instr, "value to shift was negative"); |
1648 } | 1642 } |
1649 break; | 1643 break; |
1650 case Token::SHL: | 1644 case Token::SHL: |
1651 if (shift_count != 0) { | 1645 if (shift_count != 0) { |
1652 if (instr->hydrogen_value()->representation().IsSmi()) { | 1646 if (instr->hydrogen_value()->representation().IsSmi()) { |
1653 if (SmiValuesAre32Bits()) { | 1647 if (SmiValuesAre32Bits()) { |
1654 __ shlp(ToRegister(left), Immediate(shift_count)); | 1648 __ shlp(ToRegister(left), Immediate(shift_count)); |
1655 } else { | 1649 } else { |
1656 DCHECK(SmiValuesAre31Bits()); | 1650 DCHECK(SmiValuesAre31Bits()); |
1657 if (instr->can_deopt()) { | 1651 if (instr->can_deopt()) { |
1658 if (shift_count != 1) { | 1652 if (shift_count != 1) { |
1659 __ shll(ToRegister(left), Immediate(shift_count - 1)); | 1653 __ shll(ToRegister(left), Immediate(shift_count - 1)); |
1660 } | 1654 } |
1661 __ Integer32ToSmi(ToRegister(left), ToRegister(left)); | 1655 __ Integer32ToSmi(ToRegister(left), ToRegister(left)); |
1662 DeoptimizeIf(overflow, instr); | 1656 DeoptimizeIf(overflow, instr, "overflow"); |
1663 } else { | 1657 } else { |
1664 __ shll(ToRegister(left), Immediate(shift_count)); | 1658 __ shll(ToRegister(left), Immediate(shift_count)); |
1665 } | 1659 } |
1666 } | 1660 } |
1667 } else { | 1661 } else { |
1668 __ shll(ToRegister(left), Immediate(shift_count)); | 1662 __ shll(ToRegister(left), Immediate(shift_count)); |
1669 } | 1663 } |
1670 } | 1664 } |
1671 break; | 1665 break; |
1672 default: | 1666 default: |
(...skipping 22 matching lines...) Expand all Loading... |
1695 } | 1689 } |
1696 } else { | 1690 } else { |
1697 if (instr->hydrogen_value()->representation().IsSmi()) { | 1691 if (instr->hydrogen_value()->representation().IsSmi()) { |
1698 __ subp(ToRegister(left), ToOperand(right)); | 1692 __ subp(ToRegister(left), ToOperand(right)); |
1699 } else { | 1693 } else { |
1700 __ subl(ToRegister(left), ToOperand(right)); | 1694 __ subl(ToRegister(left), ToOperand(right)); |
1701 } | 1695 } |
1702 } | 1696 } |
1703 | 1697 |
1704 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { | 1698 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |
1705 DeoptimizeIf(overflow, instr); | 1699 DeoptimizeIf(overflow, instr, "overflow"); |
1706 } | 1700 } |
1707 } | 1701 } |
1708 | 1702 |
1709 | 1703 |
1710 void LCodeGen::DoConstantI(LConstantI* instr) { | 1704 void LCodeGen::DoConstantI(LConstantI* instr) { |
1711 Register dst = ToRegister(instr->result()); | 1705 Register dst = ToRegister(instr->result()); |
1712 if (instr->value() == 0) { | 1706 if (instr->value() == 0) { |
1713 __ xorl(dst, dst); | 1707 __ xorl(dst, dst); |
1714 } else { | 1708 } else { |
1715 __ movl(dst, Immediate(instr->value())); | 1709 __ movl(dst, Immediate(instr->value())); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1760 | 1754 |
1761 void LCodeGen::DoDateField(LDateField* instr) { | 1755 void LCodeGen::DoDateField(LDateField* instr) { |
1762 Register object = ToRegister(instr->date()); | 1756 Register object = ToRegister(instr->date()); |
1763 Register result = ToRegister(instr->result()); | 1757 Register result = ToRegister(instr->result()); |
1764 Smi* index = instr->index(); | 1758 Smi* index = instr->index(); |
1765 Label runtime, done, not_date_object; | 1759 Label runtime, done, not_date_object; |
1766 DCHECK(object.is(result)); | 1760 DCHECK(object.is(result)); |
1767 DCHECK(object.is(rax)); | 1761 DCHECK(object.is(rax)); |
1768 | 1762 |
1769 Condition cc = masm()->CheckSmi(object); | 1763 Condition cc = masm()->CheckSmi(object); |
1770 DeoptimizeIf(cc, instr); | 1764 DeoptimizeIf(cc, instr, "not an object"); |
1771 __ CmpObjectType(object, JS_DATE_TYPE, kScratchRegister); | 1765 __ CmpObjectType(object, JS_DATE_TYPE, kScratchRegister); |
1772 DeoptimizeIf(not_equal, instr); | 1766 DeoptimizeIf(not_equal, instr, "not a date object"); |
1773 | 1767 |
1774 if (index->value() == 0) { | 1768 if (index->value() == 0) { |
1775 __ movp(result, FieldOperand(object, JSDate::kValueOffset)); | 1769 __ movp(result, FieldOperand(object, JSDate::kValueOffset)); |
1776 } else { | 1770 } else { |
1777 if (index->value() < JSDate::kFirstUncachedField) { | 1771 if (index->value() < JSDate::kFirstUncachedField) { |
1778 ExternalReference stamp = ExternalReference::date_cache_stamp(isolate()); | 1772 ExternalReference stamp = ExternalReference::date_cache_stamp(isolate()); |
1779 Operand stamp_operand = __ ExternalOperand(stamp); | 1773 Operand stamp_operand = __ ExternalOperand(stamp); |
1780 __ movp(kScratchRegister, stamp_operand); | 1774 __ movp(kScratchRegister, stamp_operand); |
1781 __ cmpp(kScratchRegister, FieldOperand(object, | 1775 __ cmpp(kScratchRegister, FieldOperand(object, |
1782 JSDate::kCacheStampOffset)); | 1776 JSDate::kCacheStampOffset)); |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1926 __ addl(ToRegister(left), ToRegister(right)); | 1920 __ addl(ToRegister(left), ToRegister(right)); |
1927 } | 1921 } |
1928 } else { | 1922 } else { |
1929 if (is_p) { | 1923 if (is_p) { |
1930 __ addp(ToRegister(left), ToOperand(right)); | 1924 __ addp(ToRegister(left), ToOperand(right)); |
1931 } else { | 1925 } else { |
1932 __ addl(ToRegister(left), ToOperand(right)); | 1926 __ addl(ToRegister(left), ToOperand(right)); |
1933 } | 1927 } |
1934 } | 1928 } |
1935 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { | 1929 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |
1936 DeoptimizeIf(overflow, instr); | 1930 DeoptimizeIf(overflow, instr, "overflow"); |
1937 } | 1931 } |
1938 } | 1932 } |
1939 } | 1933 } |
1940 | 1934 |
1941 | 1935 |
1942 void LCodeGen::DoMathMinMax(LMathMinMax* instr) { | 1936 void LCodeGen::DoMathMinMax(LMathMinMax* instr) { |
1943 LOperand* left = instr->left(); | 1937 LOperand* left = instr->left(); |
1944 LOperand* right = instr->right(); | 1938 LOperand* right = instr->right(); |
1945 DCHECK(left->Equals(instr->result())); | 1939 DCHECK(left->Equals(instr->result())); |
1946 HMathMinMax::Operation operation = instr->hydrogen()->operation(); | 1940 HMathMinMax::Operation operation = instr->hydrogen()->operation(); |
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2171 } | 2165 } |
2172 | 2166 |
2173 if (expected.Contains(ToBooleanStub::SMI)) { | 2167 if (expected.Contains(ToBooleanStub::SMI)) { |
2174 // Smis: 0 -> false, all other -> true. | 2168 // Smis: 0 -> false, all other -> true. |
2175 __ Cmp(reg, Smi::FromInt(0)); | 2169 __ Cmp(reg, Smi::FromInt(0)); |
2176 __ j(equal, instr->FalseLabel(chunk_)); | 2170 __ j(equal, instr->FalseLabel(chunk_)); |
2177 __ JumpIfSmi(reg, instr->TrueLabel(chunk_)); | 2171 __ JumpIfSmi(reg, instr->TrueLabel(chunk_)); |
2178 } else if (expected.NeedsMap()) { | 2172 } else if (expected.NeedsMap()) { |
2179 // If we need a map later and have a Smi -> deopt. | 2173 // If we need a map later and have a Smi -> deopt. |
2180 __ testb(reg, Immediate(kSmiTagMask)); | 2174 __ testb(reg, Immediate(kSmiTagMask)); |
2181 DeoptimizeIf(zero, instr); | 2175 DeoptimizeIf(zero, instr, "Smi"); |
2182 } | 2176 } |
2183 | 2177 |
2184 const Register map = kScratchRegister; | 2178 const Register map = kScratchRegister; |
2185 if (expected.NeedsMap()) { | 2179 if (expected.NeedsMap()) { |
2186 __ movp(map, FieldOperand(reg, HeapObject::kMapOffset)); | 2180 __ movp(map, FieldOperand(reg, HeapObject::kMapOffset)); |
2187 | 2181 |
2188 if (expected.CanBeUndetectable()) { | 2182 if (expected.CanBeUndetectable()) { |
2189 // Undetectable -> false. | 2183 // Undetectable -> false. |
2190 __ testb(FieldOperand(map, Map::kBitFieldOffset), | 2184 __ testb(FieldOperand(map, Map::kBitFieldOffset), |
2191 Immediate(1 << Map::kIsUndetectable)); | 2185 Immediate(1 << Map::kIsUndetectable)); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2225 __ xorps(xmm_scratch, xmm_scratch); | 2219 __ xorps(xmm_scratch, xmm_scratch); |
2226 __ ucomisd(xmm_scratch, FieldOperand(reg, HeapNumber::kValueOffset)); | 2220 __ ucomisd(xmm_scratch, FieldOperand(reg, HeapNumber::kValueOffset)); |
2227 __ j(zero, instr->FalseLabel(chunk_)); | 2221 __ j(zero, instr->FalseLabel(chunk_)); |
2228 __ jmp(instr->TrueLabel(chunk_)); | 2222 __ jmp(instr->TrueLabel(chunk_)); |
2229 __ bind(¬_heap_number); | 2223 __ bind(¬_heap_number); |
2230 } | 2224 } |
2231 | 2225 |
2232 if (!expected.IsGeneric()) { | 2226 if (!expected.IsGeneric()) { |
2233 // We've seen something for the first time -> deopt. | 2227 // We've seen something for the first time -> deopt. |
2234 // This can only happen if we are not generic already. | 2228 // This can only happen if we are not generic already. |
2235 DeoptimizeIf(no_condition, instr); | 2229 DeoptimizeIf(no_condition, instr, "unexpected object"); |
2236 } | 2230 } |
2237 } | 2231 } |
2238 } | 2232 } |
2239 } | 2233 } |
2240 | 2234 |
2241 | 2235 |
2242 void LCodeGen::EmitGoto(int block) { | 2236 void LCodeGen::EmitGoto(int block) { |
2243 if (!IsNextEmittedBlock(block)) { | 2237 if (!IsNextEmittedBlock(block)) { |
2244 __ jmp(chunk_->GetAssemblyLabel(chunk_->LookupDestination(block))); | 2238 __ jmp(chunk_->GetAssemblyLabel(chunk_->LookupDestination(block))); |
2245 } | 2239 } |
(...skipping 595 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2841 info_->AddNoFrameRange(no_frame_start, masm_->pc_offset()); | 2835 info_->AddNoFrameRange(no_frame_start, masm_->pc_offset()); |
2842 } | 2836 } |
2843 } | 2837 } |
2844 | 2838 |
2845 | 2839 |
2846 void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) { | 2840 void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) { |
2847 Register result = ToRegister(instr->result()); | 2841 Register result = ToRegister(instr->result()); |
2848 __ LoadGlobalCell(result, instr->hydrogen()->cell().handle()); | 2842 __ LoadGlobalCell(result, instr->hydrogen()->cell().handle()); |
2849 if (instr->hydrogen()->RequiresHoleCheck()) { | 2843 if (instr->hydrogen()->RequiresHoleCheck()) { |
2850 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); | 2844 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); |
2851 DeoptimizeIf(equal, instr); | 2845 DeoptimizeIf(equal, instr, "hole"); |
2852 } | 2846 } |
2853 } | 2847 } |
2854 | 2848 |
2855 | 2849 |
2856 template <class T> | 2850 template <class T> |
2857 void LCodeGen::EmitVectorLoadICRegisters(T* instr) { | 2851 void LCodeGen::EmitVectorLoadICRegisters(T* instr) { |
2858 DCHECK(FLAG_vector_ics); | 2852 DCHECK(FLAG_vector_ics); |
2859 Register vector = ToRegister(instr->temp_vector()); | 2853 Register vector = ToRegister(instr->temp_vector()); |
2860 DCHECK(vector.is(VectorLoadICDescriptor::VectorRegister())); | 2854 DCHECK(vector.is(VectorLoadICDescriptor::VectorRegister())); |
2861 __ Move(vector, instr->hydrogen()->feedback_vector()); | 2855 __ Move(vector, instr->hydrogen()->feedback_vector()); |
(...skipping 27 matching lines...) Expand all Loading... |
2889 // If the cell we are storing to contains the hole it could have | 2883 // If the cell we are storing to contains the hole it could have |
2890 // been deleted from the property dictionary. In that case, we need | 2884 // been deleted from the property dictionary. In that case, we need |
2891 // to update the property details in the property dictionary to mark | 2885 // to update the property details in the property dictionary to mark |
2892 // it as no longer deleted. We deoptimize in that case. | 2886 // it as no longer deleted. We deoptimize in that case. |
2893 if (instr->hydrogen()->RequiresHoleCheck()) { | 2887 if (instr->hydrogen()->RequiresHoleCheck()) { |
2894 // We have a temp because CompareRoot might clobber kScratchRegister. | 2888 // We have a temp because CompareRoot might clobber kScratchRegister. |
2895 Register cell = ToRegister(instr->temp()); | 2889 Register cell = ToRegister(instr->temp()); |
2896 DCHECK(!value.is(cell)); | 2890 DCHECK(!value.is(cell)); |
2897 __ Move(cell, cell_handle, RelocInfo::CELL); | 2891 __ Move(cell, cell_handle, RelocInfo::CELL); |
2898 __ CompareRoot(Operand(cell, 0), Heap::kTheHoleValueRootIndex); | 2892 __ CompareRoot(Operand(cell, 0), Heap::kTheHoleValueRootIndex); |
2899 DeoptimizeIf(equal, instr); | 2893 DeoptimizeIf(equal, instr, "hole"); |
2900 // Store the value. | 2894 // Store the value. |
2901 __ movp(Operand(cell, 0), value); | 2895 __ movp(Operand(cell, 0), value); |
2902 } else { | 2896 } else { |
2903 // Store the value. | 2897 // Store the value. |
2904 __ Move(kScratchRegister, cell_handle, RelocInfo::CELL); | 2898 __ Move(kScratchRegister, cell_handle, RelocInfo::CELL); |
2905 __ movp(Operand(kScratchRegister, 0), value); | 2899 __ movp(Operand(kScratchRegister, 0), value); |
2906 } | 2900 } |
2907 // Cells are always rescanned, so no write barrier here. | 2901 // Cells are always rescanned, so no write barrier here. |
2908 } | 2902 } |
2909 | 2903 |
2910 | 2904 |
2911 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { | 2905 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { |
2912 Register context = ToRegister(instr->context()); | 2906 Register context = ToRegister(instr->context()); |
2913 Register result = ToRegister(instr->result()); | 2907 Register result = ToRegister(instr->result()); |
2914 __ movp(result, ContextOperand(context, instr->slot_index())); | 2908 __ movp(result, ContextOperand(context, instr->slot_index())); |
2915 if (instr->hydrogen()->RequiresHoleCheck()) { | 2909 if (instr->hydrogen()->RequiresHoleCheck()) { |
2916 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); | 2910 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); |
2917 if (instr->hydrogen()->DeoptimizesOnHole()) { | 2911 if (instr->hydrogen()->DeoptimizesOnHole()) { |
2918 DeoptimizeIf(equal, instr); | 2912 DeoptimizeIf(equal, instr, "hole"); |
2919 } else { | 2913 } else { |
2920 Label is_not_hole; | 2914 Label is_not_hole; |
2921 __ j(not_equal, &is_not_hole, Label::kNear); | 2915 __ j(not_equal, &is_not_hole, Label::kNear); |
2922 __ LoadRoot(result, Heap::kUndefinedValueRootIndex); | 2916 __ LoadRoot(result, Heap::kUndefinedValueRootIndex); |
2923 __ bind(&is_not_hole); | 2917 __ bind(&is_not_hole); |
2924 } | 2918 } |
2925 } | 2919 } |
2926 } | 2920 } |
2927 | 2921 |
2928 | 2922 |
2929 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { | 2923 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { |
2930 Register context = ToRegister(instr->context()); | 2924 Register context = ToRegister(instr->context()); |
2931 Register value = ToRegister(instr->value()); | 2925 Register value = ToRegister(instr->value()); |
2932 | 2926 |
2933 Operand target = ContextOperand(context, instr->slot_index()); | 2927 Operand target = ContextOperand(context, instr->slot_index()); |
2934 | 2928 |
2935 Label skip_assignment; | 2929 Label skip_assignment; |
2936 if (instr->hydrogen()->RequiresHoleCheck()) { | 2930 if (instr->hydrogen()->RequiresHoleCheck()) { |
2937 __ CompareRoot(target, Heap::kTheHoleValueRootIndex); | 2931 __ CompareRoot(target, Heap::kTheHoleValueRootIndex); |
2938 if (instr->hydrogen()->DeoptimizesOnHole()) { | 2932 if (instr->hydrogen()->DeoptimizesOnHole()) { |
2939 DeoptimizeIf(equal, instr); | 2933 DeoptimizeIf(equal, instr, "hole"); |
2940 } else { | 2934 } else { |
2941 __ j(not_equal, &skip_assignment); | 2935 __ j(not_equal, &skip_assignment); |
2942 } | 2936 } |
2943 } | 2937 } |
2944 __ movp(target, value); | 2938 __ movp(target, value); |
2945 | 2939 |
2946 if (instr->hydrogen()->NeedsWriteBarrier()) { | 2940 if (instr->hydrogen()->NeedsWriteBarrier()) { |
2947 SmiCheck check_needed = | 2941 SmiCheck check_needed = |
2948 instr->hydrogen()->value()->type().IsHeapObject() | 2942 instr->hydrogen()->value()->type().IsHeapObject() |
2949 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; | 2943 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3027 void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { | 3021 void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { |
3028 Register function = ToRegister(instr->function()); | 3022 Register function = ToRegister(instr->function()); |
3029 Register result = ToRegister(instr->result()); | 3023 Register result = ToRegister(instr->result()); |
3030 | 3024 |
3031 // Get the prototype or initial map from the function. | 3025 // Get the prototype or initial map from the function. |
3032 __ movp(result, | 3026 __ movp(result, |
3033 FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); | 3027 FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); |
3034 | 3028 |
3035 // Check that the function has a prototype or an initial map. | 3029 // Check that the function has a prototype or an initial map. |
3036 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); | 3030 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); |
3037 DeoptimizeIf(equal, instr); | 3031 DeoptimizeIf(equal, instr, "hole"); |
3038 | 3032 |
3039 // If the function does not have an initial map, we're done. | 3033 // If the function does not have an initial map, we're done. |
3040 Label done; | 3034 Label done; |
3041 __ CmpObjectType(result, MAP_TYPE, kScratchRegister); | 3035 __ CmpObjectType(result, MAP_TYPE, kScratchRegister); |
3042 __ j(not_equal, &done, Label::kNear); | 3036 __ j(not_equal, &done, Label::kNear); |
3043 | 3037 |
3044 // Get the prototype from the initial map. | 3038 // Get the prototype from the initial map. |
3045 __ movp(result, FieldOperand(result, Map::kPrototypeOffset)); | 3039 __ movp(result, FieldOperand(result, Map::kPrototypeOffset)); |
3046 | 3040 |
3047 // All done. | 3041 // All done. |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3139 break; | 3133 break; |
3140 case EXTERNAL_INT32_ELEMENTS: | 3134 case EXTERNAL_INT32_ELEMENTS: |
3141 case INT32_ELEMENTS: | 3135 case INT32_ELEMENTS: |
3142 __ movl(result, operand); | 3136 __ movl(result, operand); |
3143 break; | 3137 break; |
3144 case EXTERNAL_UINT32_ELEMENTS: | 3138 case EXTERNAL_UINT32_ELEMENTS: |
3145 case UINT32_ELEMENTS: | 3139 case UINT32_ELEMENTS: |
3146 __ movl(result, operand); | 3140 __ movl(result, operand); |
3147 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) { | 3141 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) { |
3148 __ testl(result, result); | 3142 __ testl(result, result); |
3149 DeoptimizeIf(negative, instr); | 3143 DeoptimizeIf(negative, instr, "negative value"); |
3150 } | 3144 } |
3151 break; | 3145 break; |
3152 case EXTERNAL_FLOAT32_ELEMENTS: | 3146 case EXTERNAL_FLOAT32_ELEMENTS: |
3153 case EXTERNAL_FLOAT64_ELEMENTS: | 3147 case EXTERNAL_FLOAT64_ELEMENTS: |
3154 case FLOAT32_ELEMENTS: | 3148 case FLOAT32_ELEMENTS: |
3155 case FLOAT64_ELEMENTS: | 3149 case FLOAT64_ELEMENTS: |
3156 case FAST_ELEMENTS: | 3150 case FAST_ELEMENTS: |
3157 case FAST_SMI_ELEMENTS: | 3151 case FAST_SMI_ELEMENTS: |
3158 case FAST_DOUBLE_ELEMENTS: | 3152 case FAST_DOUBLE_ELEMENTS: |
3159 case FAST_HOLEY_ELEMENTS: | 3153 case FAST_HOLEY_ELEMENTS: |
(...skipping 18 matching lines...) Expand all Loading... |
3178 __ movsxlq(ToRegister(key), ToRegister(key)); | 3172 __ movsxlq(ToRegister(key), ToRegister(key)); |
3179 } | 3173 } |
3180 if (instr->hydrogen()->RequiresHoleCheck()) { | 3174 if (instr->hydrogen()->RequiresHoleCheck()) { |
3181 Operand hole_check_operand = BuildFastArrayOperand( | 3175 Operand hole_check_operand = BuildFastArrayOperand( |
3182 instr->elements(), | 3176 instr->elements(), |
3183 key, | 3177 key, |
3184 instr->hydrogen()->key()->representation(), | 3178 instr->hydrogen()->key()->representation(), |
3185 FAST_DOUBLE_ELEMENTS, | 3179 FAST_DOUBLE_ELEMENTS, |
3186 instr->base_offset() + sizeof(kHoleNanLower32)); | 3180 instr->base_offset() + sizeof(kHoleNanLower32)); |
3187 __ cmpl(hole_check_operand, Immediate(kHoleNanUpper32)); | 3181 __ cmpl(hole_check_operand, Immediate(kHoleNanUpper32)); |
3188 DeoptimizeIf(equal, instr); | 3182 DeoptimizeIf(equal, instr, "hole"); |
3189 } | 3183 } |
3190 | 3184 |
3191 Operand double_load_operand = BuildFastArrayOperand( | 3185 Operand double_load_operand = BuildFastArrayOperand( |
3192 instr->elements(), | 3186 instr->elements(), |
3193 key, | 3187 key, |
3194 instr->hydrogen()->key()->representation(), | 3188 instr->hydrogen()->key()->representation(), |
3195 FAST_DOUBLE_ELEMENTS, | 3189 FAST_DOUBLE_ELEMENTS, |
3196 instr->base_offset()); | 3190 instr->base_offset()); |
3197 __ movsd(result, double_load_operand); | 3191 __ movsd(result, double_load_operand); |
3198 } | 3192 } |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3235 __ Load(result, | 3229 __ Load(result, |
3236 BuildFastArrayOperand(instr->elements(), key, | 3230 BuildFastArrayOperand(instr->elements(), key, |
3237 instr->hydrogen()->key()->representation(), | 3231 instr->hydrogen()->key()->representation(), |
3238 FAST_ELEMENTS, offset), | 3232 FAST_ELEMENTS, offset), |
3239 representation); | 3233 representation); |
3240 | 3234 |
3241 // Check for the hole value. | 3235 // Check for the hole value. |
3242 if (requires_hole_check) { | 3236 if (requires_hole_check) { |
3243 if (IsFastSmiElementsKind(hinstr->elements_kind())) { | 3237 if (IsFastSmiElementsKind(hinstr->elements_kind())) { |
3244 Condition smi = __ CheckSmi(result); | 3238 Condition smi = __ CheckSmi(result); |
3245 DeoptimizeIf(NegateCondition(smi), instr); | 3239 DeoptimizeIf(NegateCondition(smi), instr, "not a Smi"); |
3246 } else { | 3240 } else { |
3247 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); | 3241 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); |
3248 DeoptimizeIf(equal, instr); | 3242 DeoptimizeIf(equal, instr, "hole"); |
3249 } | 3243 } |
3250 } | 3244 } |
3251 } | 3245 } |
3252 | 3246 |
3253 | 3247 |
3254 void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) { | 3248 void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) { |
3255 if (instr->is_typed_elements()) { | 3249 if (instr->is_typed_elements()) { |
3256 DoLoadKeyedExternalArray(instr); | 3250 DoLoadKeyedExternalArray(instr); |
3257 } else if (instr->hydrogen()->representation().IsDouble()) { | 3251 } else if (instr->hydrogen()->representation().IsDouble()) { |
3258 DoLoadKeyedFixedDoubleArray(instr); | 3252 DoLoadKeyedFixedDoubleArray(instr); |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3387 } | 3381 } |
3388 | 3382 |
3389 // Normal function. Replace undefined or null with global receiver. | 3383 // Normal function. Replace undefined or null with global receiver. |
3390 __ CompareRoot(receiver, Heap::kNullValueRootIndex); | 3384 __ CompareRoot(receiver, Heap::kNullValueRootIndex); |
3391 __ j(equal, &global_object, Label::kNear); | 3385 __ j(equal, &global_object, Label::kNear); |
3392 __ CompareRoot(receiver, Heap::kUndefinedValueRootIndex); | 3386 __ CompareRoot(receiver, Heap::kUndefinedValueRootIndex); |
3393 __ j(equal, &global_object, Label::kNear); | 3387 __ j(equal, &global_object, Label::kNear); |
3394 | 3388 |
3395 // The receiver should be a JS object. | 3389 // The receiver should be a JS object. |
3396 Condition is_smi = __ CheckSmi(receiver); | 3390 Condition is_smi = __ CheckSmi(receiver); |
3397 DeoptimizeIf(is_smi, instr); | 3391 DeoptimizeIf(is_smi, instr, "not an object"); |
3398 __ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, kScratchRegister); | 3392 __ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, kScratchRegister); |
3399 DeoptimizeIf(below, instr); | 3393 DeoptimizeIf(below, instr, "not a spec object"); |
3400 | 3394 |
3401 __ jmp(&receiver_ok, Label::kNear); | 3395 __ jmp(&receiver_ok, Label::kNear); |
3402 __ bind(&global_object); | 3396 __ bind(&global_object); |
3403 __ movp(receiver, FieldOperand(function, JSFunction::kContextOffset)); | 3397 __ movp(receiver, FieldOperand(function, JSFunction::kContextOffset)); |
3404 __ movp(receiver, | 3398 __ movp(receiver, |
3405 Operand(receiver, | 3399 Operand(receiver, |
3406 Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); | 3400 Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); |
3407 __ movp(receiver, FieldOperand(receiver, GlobalObject::kGlobalProxyOffset)); | 3401 __ movp(receiver, FieldOperand(receiver, GlobalObject::kGlobalProxyOffset)); |
3408 | 3402 |
3409 __ bind(&receiver_ok); | 3403 __ bind(&receiver_ok); |
3410 } | 3404 } |
3411 | 3405 |
3412 | 3406 |
3413 void LCodeGen::DoApplyArguments(LApplyArguments* instr) { | 3407 void LCodeGen::DoApplyArguments(LApplyArguments* instr) { |
3414 Register receiver = ToRegister(instr->receiver()); | 3408 Register receiver = ToRegister(instr->receiver()); |
3415 Register function = ToRegister(instr->function()); | 3409 Register function = ToRegister(instr->function()); |
3416 Register length = ToRegister(instr->length()); | 3410 Register length = ToRegister(instr->length()); |
3417 Register elements = ToRegister(instr->elements()); | 3411 Register elements = ToRegister(instr->elements()); |
3418 DCHECK(receiver.is(rax)); // Used for parameter count. | 3412 DCHECK(receiver.is(rax)); // Used for parameter count. |
3419 DCHECK(function.is(rdi)); // Required by InvokeFunction. | 3413 DCHECK(function.is(rdi)); // Required by InvokeFunction. |
3420 DCHECK(ToRegister(instr->result()).is(rax)); | 3414 DCHECK(ToRegister(instr->result()).is(rax)); |
3421 | 3415 |
3422 // Copy the arguments to this function possibly from the | 3416 // Copy the arguments to this function possibly from the |
3423 // adaptor frame below it. | 3417 // adaptor frame below it. |
3424 const uint32_t kArgumentsLimit = 1 * KB; | 3418 const uint32_t kArgumentsLimit = 1 * KB; |
3425 __ cmpp(length, Immediate(kArgumentsLimit)); | 3419 __ cmpp(length, Immediate(kArgumentsLimit)); |
3426 DeoptimizeIf(above, instr); | 3420 DeoptimizeIf(above, instr, "too many arguments"); |
3427 | 3421 |
3428 __ Push(receiver); | 3422 __ Push(receiver); |
3429 __ movp(receiver, length); | 3423 __ movp(receiver, length); |
3430 | 3424 |
3431 // Loop through the arguments pushing them onto the execution | 3425 // Loop through the arguments pushing them onto the execution |
3432 // stack. | 3426 // stack. |
3433 Label invoke, loop; | 3427 Label invoke, loop; |
3434 // length is a small non-negative integer, due to the test above. | 3428 // length is a small non-negative integer, due to the test above. |
3435 __ testl(length, length); | 3429 __ testl(length, length); |
3436 __ j(zero, &invoke, Label::kNear); | 3430 __ j(zero, &invoke, Label::kNear); |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3611 __ Call(target); | 3605 __ Call(target); |
3612 } | 3606 } |
3613 generator.AfterCall(); | 3607 generator.AfterCall(); |
3614 } | 3608 } |
3615 | 3609 |
3616 | 3610 |
3617 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { | 3611 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { |
3618 Register input_reg = ToRegister(instr->value()); | 3612 Register input_reg = ToRegister(instr->value()); |
3619 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), | 3613 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), |
3620 Heap::kHeapNumberMapRootIndex); | 3614 Heap::kHeapNumberMapRootIndex); |
3621 DeoptimizeIf(not_equal, instr); | 3615 DeoptimizeIf(not_equal, instr, "not a heap number"); |
3622 | 3616 |
3623 Label slow, allocated, done; | 3617 Label slow, allocated, done; |
3624 Register tmp = input_reg.is(rax) ? rcx : rax; | 3618 Register tmp = input_reg.is(rax) ? rcx : rax; |
3625 Register tmp2 = tmp.is(rcx) ? rdx : input_reg.is(rcx) ? rdx : rcx; | 3619 Register tmp2 = tmp.is(rcx) ? rdx : input_reg.is(rcx) ? rdx : rcx; |
3626 | 3620 |
3627 // Preserve the value of all registers. | 3621 // Preserve the value of all registers. |
3628 PushSafepointRegistersScope scope(this); | 3622 PushSafepointRegistersScope scope(this); |
3629 | 3623 |
3630 __ movl(tmp, FieldOperand(input_reg, HeapNumber::kExponentOffset)); | 3624 __ movl(tmp, FieldOperand(input_reg, HeapNumber::kExponentOffset)); |
3631 // Check the sign of the argument. If the argument is positive, just | 3625 // Check the sign of the argument. If the argument is positive, just |
(...skipping 25 matching lines...) Expand all Loading... |
3657 __ bind(&done); | 3651 __ bind(&done); |
3658 } | 3652 } |
3659 | 3653 |
3660 | 3654 |
3661 void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) { | 3655 void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) { |
3662 Register input_reg = ToRegister(instr->value()); | 3656 Register input_reg = ToRegister(instr->value()); |
3663 __ testl(input_reg, input_reg); | 3657 __ testl(input_reg, input_reg); |
3664 Label is_positive; | 3658 Label is_positive; |
3665 __ j(not_sign, &is_positive, Label::kNear); | 3659 __ j(not_sign, &is_positive, Label::kNear); |
3666 __ negl(input_reg); // Sets flags. | 3660 __ negl(input_reg); // Sets flags. |
3667 DeoptimizeIf(negative, instr); | 3661 DeoptimizeIf(negative, instr, "overflow"); |
3668 __ bind(&is_positive); | 3662 __ bind(&is_positive); |
3669 } | 3663 } |
3670 | 3664 |
3671 | 3665 |
3672 void LCodeGen::EmitSmiMathAbs(LMathAbs* instr) { | 3666 void LCodeGen::EmitSmiMathAbs(LMathAbs* instr) { |
3673 Register input_reg = ToRegister(instr->value()); | 3667 Register input_reg = ToRegister(instr->value()); |
3674 __ testp(input_reg, input_reg); | 3668 __ testp(input_reg, input_reg); |
3675 Label is_positive; | 3669 Label is_positive; |
3676 __ j(not_sign, &is_positive, Label::kNear); | 3670 __ j(not_sign, &is_positive, Label::kNear); |
3677 __ negp(input_reg); // Sets flags. | 3671 __ negp(input_reg); // Sets flags. |
3678 DeoptimizeIf(negative, instr); | 3672 DeoptimizeIf(negative, instr, "overflow"); |
3679 __ bind(&is_positive); | 3673 __ bind(&is_positive); |
3680 } | 3674 } |
3681 | 3675 |
3682 | 3676 |
3683 void LCodeGen::DoMathAbs(LMathAbs* instr) { | 3677 void LCodeGen::DoMathAbs(LMathAbs* instr) { |
3684 // Class for deferred case. | 3678 // Class for deferred case. |
3685 class DeferredMathAbsTaggedHeapNumber FINAL : public LDeferredCode { | 3679 class DeferredMathAbsTaggedHeapNumber FINAL : public LDeferredCode { |
3686 public: | 3680 public: |
3687 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, LMathAbs* instr) | 3681 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, LMathAbs* instr) |
3688 : LDeferredCode(codegen), instr_(instr) { } | 3682 : LDeferredCode(codegen), instr_(instr) { } |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3723 XMMRegister xmm_scratch = double_scratch0(); | 3717 XMMRegister xmm_scratch = double_scratch0(); |
3724 Register output_reg = ToRegister(instr->result()); | 3718 Register output_reg = ToRegister(instr->result()); |
3725 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 3719 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
3726 | 3720 |
3727 if (CpuFeatures::IsSupported(SSE4_1)) { | 3721 if (CpuFeatures::IsSupported(SSE4_1)) { |
3728 CpuFeatureScope scope(masm(), SSE4_1); | 3722 CpuFeatureScope scope(masm(), SSE4_1); |
3729 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3723 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
3730 // Deoptimize if minus zero. | 3724 // Deoptimize if minus zero. |
3731 __ movq(output_reg, input_reg); | 3725 __ movq(output_reg, input_reg); |
3732 __ subq(output_reg, Immediate(1)); | 3726 __ subq(output_reg, Immediate(1)); |
3733 DeoptimizeIf(overflow, instr); | 3727 DeoptimizeIf(overflow, instr, "minus zero"); |
3734 } | 3728 } |
3735 __ roundsd(xmm_scratch, input_reg, Assembler::kRoundDown); | 3729 __ roundsd(xmm_scratch, input_reg, Assembler::kRoundDown); |
3736 __ cvttsd2si(output_reg, xmm_scratch); | 3730 __ cvttsd2si(output_reg, xmm_scratch); |
3737 __ cmpl(output_reg, Immediate(0x1)); | 3731 __ cmpl(output_reg, Immediate(0x1)); |
3738 DeoptimizeIf(overflow, instr); | 3732 DeoptimizeIf(overflow, instr, "overflow"); |
3739 } else { | 3733 } else { |
3740 Label negative_sign, done; | 3734 Label negative_sign, done; |
3741 // Deoptimize on unordered. | 3735 // Deoptimize on unordered. |
3742 __ xorps(xmm_scratch, xmm_scratch); // Zero the register. | 3736 __ xorps(xmm_scratch, xmm_scratch); // Zero the register. |
3743 __ ucomisd(input_reg, xmm_scratch); | 3737 __ ucomisd(input_reg, xmm_scratch); |
3744 DeoptimizeIf(parity_even, instr); | 3738 DeoptimizeIf(parity_even, instr, "unordered"); |
3745 __ j(below, &negative_sign, Label::kNear); | 3739 __ j(below, &negative_sign, Label::kNear); |
3746 | 3740 |
3747 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 3741 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
3748 // Check for negative zero. | 3742 // Check for negative zero. |
3749 Label positive_sign; | 3743 Label positive_sign; |
3750 __ j(above, &positive_sign, Label::kNear); | 3744 __ j(above, &positive_sign, Label::kNear); |
3751 __ movmskpd(output_reg, input_reg); | 3745 __ movmskpd(output_reg, input_reg); |
3752 __ testq(output_reg, Immediate(1)); | 3746 __ testq(output_reg, Immediate(1)); |
3753 DeoptimizeIf(not_zero, instr); | 3747 DeoptimizeIf(not_zero, instr, "minus zero"); |
3754 __ Set(output_reg, 0); | 3748 __ Set(output_reg, 0); |
3755 __ jmp(&done); | 3749 __ jmp(&done); |
3756 __ bind(&positive_sign); | 3750 __ bind(&positive_sign); |
3757 } | 3751 } |
3758 | 3752 |
3759 // Use truncating instruction (OK because input is positive). | 3753 // Use truncating instruction (OK because input is positive). |
3760 __ cvttsd2si(output_reg, input_reg); | 3754 __ cvttsd2si(output_reg, input_reg); |
3761 // Overflow is signalled with minint. | 3755 // Overflow is signalled with minint. |
3762 __ cmpl(output_reg, Immediate(0x1)); | 3756 __ cmpl(output_reg, Immediate(0x1)); |
3763 DeoptimizeIf(overflow, instr); | 3757 DeoptimizeIf(overflow, instr, "overflow"); |
3764 __ jmp(&done, Label::kNear); | 3758 __ jmp(&done, Label::kNear); |
3765 | 3759 |
3766 // Non-zero negative reaches here. | 3760 // Non-zero negative reaches here. |
3767 __ bind(&negative_sign); | 3761 __ bind(&negative_sign); |
3768 // Truncate, then compare and compensate. | 3762 // Truncate, then compare and compensate. |
3769 __ cvttsd2si(output_reg, input_reg); | 3763 __ cvttsd2si(output_reg, input_reg); |
3770 __ Cvtlsi2sd(xmm_scratch, output_reg); | 3764 __ Cvtlsi2sd(xmm_scratch, output_reg); |
3771 __ ucomisd(input_reg, xmm_scratch); | 3765 __ ucomisd(input_reg, xmm_scratch); |
3772 __ j(equal, &done, Label::kNear); | 3766 __ j(equal, &done, Label::kNear); |
3773 __ subl(output_reg, Immediate(1)); | 3767 __ subl(output_reg, Immediate(1)); |
3774 DeoptimizeIf(overflow, instr); | 3768 DeoptimizeIf(overflow, instr, "overflow"); |
3775 | 3769 |
3776 __ bind(&done); | 3770 __ bind(&done); |
3777 } | 3771 } |
3778 } | 3772 } |
3779 | 3773 |
3780 | 3774 |
3781 void LCodeGen::DoMathRound(LMathRound* instr) { | 3775 void LCodeGen::DoMathRound(LMathRound* instr) { |
3782 const XMMRegister xmm_scratch = double_scratch0(); | 3776 const XMMRegister xmm_scratch = double_scratch0(); |
3783 Register output_reg = ToRegister(instr->result()); | 3777 Register output_reg = ToRegister(instr->result()); |
3784 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 3778 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3901 DCHECK(ToDoubleRegister(instr->left()).is(xmm2)); | 3895 DCHECK(ToDoubleRegister(instr->left()).is(xmm2)); |
3902 DCHECK(ToDoubleRegister(instr->result()).is(xmm3)); | 3896 DCHECK(ToDoubleRegister(instr->result()).is(xmm3)); |
3903 | 3897 |
3904 if (exponent_type.IsSmi()) { | 3898 if (exponent_type.IsSmi()) { |
3905 MathPowStub stub(isolate(), MathPowStub::TAGGED); | 3899 MathPowStub stub(isolate(), MathPowStub::TAGGED); |
3906 __ CallStub(&stub); | 3900 __ CallStub(&stub); |
3907 } else if (exponent_type.IsTagged()) { | 3901 } else if (exponent_type.IsTagged()) { |
3908 Label no_deopt; | 3902 Label no_deopt; |
3909 __ JumpIfSmi(tagged_exponent, &no_deopt, Label::kNear); | 3903 __ JumpIfSmi(tagged_exponent, &no_deopt, Label::kNear); |
3910 __ CmpObjectType(tagged_exponent, HEAP_NUMBER_TYPE, rcx); | 3904 __ CmpObjectType(tagged_exponent, HEAP_NUMBER_TYPE, rcx); |
3911 DeoptimizeIf(not_equal, instr); | 3905 DeoptimizeIf(not_equal, instr, "not a heap number"); |
3912 __ bind(&no_deopt); | 3906 __ bind(&no_deopt); |
3913 MathPowStub stub(isolate(), MathPowStub::TAGGED); | 3907 MathPowStub stub(isolate(), MathPowStub::TAGGED); |
3914 __ CallStub(&stub); | 3908 __ CallStub(&stub); |
3915 } else if (exponent_type.IsInteger32()) { | 3909 } else if (exponent_type.IsInteger32()) { |
3916 MathPowStub stub(isolate(), MathPowStub::INTEGER); | 3910 MathPowStub stub(isolate(), MathPowStub::INTEGER); |
3917 __ CallStub(&stub); | 3911 __ CallStub(&stub); |
3918 } else { | 3912 } else { |
3919 DCHECK(exponent_type.IsDouble()); | 3913 DCHECK(exponent_type.IsDouble()); |
3920 MathPowStub stub(isolate(), MathPowStub::DOUBLE); | 3914 MathPowStub stub(isolate(), MathPowStub::DOUBLE); |
3921 __ CallStub(&stub); | 3915 __ CallStub(&stub); |
(...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4273 __ cmpl(length, index); | 4267 __ cmpl(length, index); |
4274 } | 4268 } |
4275 } | 4269 } |
4276 } | 4270 } |
4277 if (FLAG_debug_code && instr->hydrogen()->skip_check()) { | 4271 if (FLAG_debug_code && instr->hydrogen()->skip_check()) { |
4278 Label done; | 4272 Label done; |
4279 __ j(NegateCondition(cc), &done, Label::kNear); | 4273 __ j(NegateCondition(cc), &done, Label::kNear); |
4280 __ int3(); | 4274 __ int3(); |
4281 __ bind(&done); | 4275 __ bind(&done); |
4282 } else { | 4276 } else { |
4283 DeoptimizeIf(cc, instr); | 4277 DeoptimizeIf(cc, instr, "out of bounds"); |
4284 } | 4278 } |
4285 } | 4279 } |
4286 | 4280 |
4287 | 4281 |
4288 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) { | 4282 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) { |
4289 ElementsKind elements_kind = instr->elements_kind(); | 4283 ElementsKind elements_kind = instr->elements_kind(); |
4290 LOperand* key = instr->key(); | 4284 LOperand* key = instr->key(); |
4291 if (kPointerSize == kInt32Size && !key->IsConstantOperand()) { | 4285 if (kPointerSize == kInt32Size && !key->IsConstantOperand()) { |
4292 Register key_reg = ToRegister(key); | 4286 Register key_reg = ToRegister(key); |
4293 Representation key_representation = | 4287 Representation key_representation = |
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4521 } | 4515 } |
4522 __ bind(¬_applicable); | 4516 __ bind(¬_applicable); |
4523 } | 4517 } |
4524 | 4518 |
4525 | 4519 |
4526 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) { | 4520 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) { |
4527 Register object = ToRegister(instr->object()); | 4521 Register object = ToRegister(instr->object()); |
4528 Register temp = ToRegister(instr->temp()); | 4522 Register temp = ToRegister(instr->temp()); |
4529 Label no_memento_found; | 4523 Label no_memento_found; |
4530 __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found); | 4524 __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found); |
4531 DeoptimizeIf(equal, instr); | 4525 DeoptimizeIf(equal, instr, "memento found"); |
4532 __ bind(&no_memento_found); | 4526 __ bind(&no_memento_found); |
4533 } | 4527 } |
4534 | 4528 |
4535 | 4529 |
4536 void LCodeGen::DoStringAdd(LStringAdd* instr) { | 4530 void LCodeGen::DoStringAdd(LStringAdd* instr) { |
4537 DCHECK(ToRegister(instr->context()).is(rsi)); | 4531 DCHECK(ToRegister(instr->context()).is(rsi)); |
4538 DCHECK(ToRegister(instr->left()).is(rdx)); | 4532 DCHECK(ToRegister(instr->left()).is(rdx)); |
4539 DCHECK(ToRegister(instr->right()).is(rax)); | 4533 DCHECK(ToRegister(instr->right()).is(rax)); |
4540 StringAddStub stub(isolate(), | 4534 StringAddStub stub(isolate(), |
4541 instr->hydrogen()->flags(), | 4535 instr->hydrogen()->flags(), |
(...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4840 } | 4834 } |
4841 | 4835 |
4842 | 4836 |
4843 void LCodeGen::DoSmiTag(LSmiTag* instr) { | 4837 void LCodeGen::DoSmiTag(LSmiTag* instr) { |
4844 HChange* hchange = instr->hydrogen(); | 4838 HChange* hchange = instr->hydrogen(); |
4845 Register input = ToRegister(instr->value()); | 4839 Register input = ToRegister(instr->value()); |
4846 Register output = ToRegister(instr->result()); | 4840 Register output = ToRegister(instr->result()); |
4847 if (hchange->CheckFlag(HValue::kCanOverflow) && | 4841 if (hchange->CheckFlag(HValue::kCanOverflow) && |
4848 hchange->value()->CheckFlag(HValue::kUint32)) { | 4842 hchange->value()->CheckFlag(HValue::kUint32)) { |
4849 Condition is_smi = __ CheckUInteger32ValidSmiValue(input); | 4843 Condition is_smi = __ CheckUInteger32ValidSmiValue(input); |
4850 DeoptimizeIf(NegateCondition(is_smi), instr); | 4844 DeoptimizeIf(NegateCondition(is_smi), instr, "not a smi"); |
4851 } | 4845 } |
4852 __ Integer32ToSmi(output, input); | 4846 __ Integer32ToSmi(output, input); |
4853 if (hchange->CheckFlag(HValue::kCanOverflow) && | 4847 if (hchange->CheckFlag(HValue::kCanOverflow) && |
4854 !hchange->value()->CheckFlag(HValue::kUint32)) { | 4848 !hchange->value()->CheckFlag(HValue::kUint32)) { |
4855 DeoptimizeIf(overflow, instr); | 4849 DeoptimizeIf(overflow, instr, "overflow"); |
4856 } | 4850 } |
4857 } | 4851 } |
4858 | 4852 |
4859 | 4853 |
4860 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { | 4854 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { |
4861 DCHECK(instr->value()->Equals(instr->result())); | 4855 DCHECK(instr->value()->Equals(instr->result())); |
4862 Register input = ToRegister(instr->value()); | 4856 Register input = ToRegister(instr->value()); |
4863 if (instr->needs_check()) { | 4857 if (instr->needs_check()) { |
4864 Condition is_smi = __ CheckSmi(input); | 4858 Condition is_smi = __ CheckSmi(input); |
4865 DeoptimizeIf(NegateCondition(is_smi), instr); | 4859 DeoptimizeIf(NegateCondition(is_smi), instr, "not a smi"); |
4866 } else { | 4860 } else { |
4867 __ AssertSmi(input); | 4861 __ AssertSmi(input); |
4868 } | 4862 } |
4869 __ SmiToInteger32(input, input); | 4863 __ SmiToInteger32(input, input); |
4870 } | 4864 } |
4871 | 4865 |
4872 | 4866 |
4873 void LCodeGen::EmitNumberUntagD(LNumberUntagD* instr, Register input_reg, | 4867 void LCodeGen::EmitNumberUntagD(LNumberUntagD* instr, Register input_reg, |
4874 XMMRegister result_reg, NumberUntagDMode mode) { | 4868 XMMRegister result_reg, NumberUntagDMode mode) { |
4875 bool can_convert_undefined_to_nan = | 4869 bool can_convert_undefined_to_nan = |
(...skipping 10 matching lines...) Expand all Loading... |
4886 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), | 4880 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), |
4887 Heap::kHeapNumberMapRootIndex); | 4881 Heap::kHeapNumberMapRootIndex); |
4888 | 4882 |
4889 // On x64 it is safe to load at heap number offset before evaluating the map | 4883 // On x64 it is safe to load at heap number offset before evaluating the map |
4890 // check, since all heap objects are at least two words long. | 4884 // check, since all heap objects are at least two words long. |
4891 __ movsd(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset)); | 4885 __ movsd(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
4892 | 4886 |
4893 if (can_convert_undefined_to_nan) { | 4887 if (can_convert_undefined_to_nan) { |
4894 __ j(not_equal, &convert, Label::kNear); | 4888 __ j(not_equal, &convert, Label::kNear); |
4895 } else { | 4889 } else { |
4896 DeoptimizeIf(not_equal, instr); | 4890 DeoptimizeIf(not_equal, instr, "not a heap number"); |
4897 } | 4891 } |
4898 | 4892 |
4899 if (deoptimize_on_minus_zero) { | 4893 if (deoptimize_on_minus_zero) { |
4900 XMMRegister xmm_scratch = double_scratch0(); | 4894 XMMRegister xmm_scratch = double_scratch0(); |
4901 __ xorps(xmm_scratch, xmm_scratch); | 4895 __ xorps(xmm_scratch, xmm_scratch); |
4902 __ ucomisd(xmm_scratch, result_reg); | 4896 __ ucomisd(xmm_scratch, result_reg); |
4903 __ j(not_equal, &done, Label::kNear); | 4897 __ j(not_equal, &done, Label::kNear); |
4904 __ movmskpd(kScratchRegister, result_reg); | 4898 __ movmskpd(kScratchRegister, result_reg); |
4905 __ testq(kScratchRegister, Immediate(1)); | 4899 __ testq(kScratchRegister, Immediate(1)); |
4906 DeoptimizeIf(not_zero, instr); | 4900 DeoptimizeIf(not_zero, instr, "minus zero"); |
4907 } | 4901 } |
4908 __ jmp(&done, Label::kNear); | 4902 __ jmp(&done, Label::kNear); |
4909 | 4903 |
4910 if (can_convert_undefined_to_nan) { | 4904 if (can_convert_undefined_to_nan) { |
4911 __ bind(&convert); | 4905 __ bind(&convert); |
4912 | 4906 |
4913 // Convert undefined (and hole) to NaN. Compute NaN as 0/0. | 4907 // Convert undefined (and hole) to NaN. Compute NaN as 0/0. |
4914 __ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex); | 4908 __ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex); |
4915 DeoptimizeIf(not_equal, instr); | 4909 DeoptimizeIf(not_equal, instr, "neither a heap number nor undefined"); |
4916 | 4910 |
4917 __ xorps(result_reg, result_reg); | 4911 __ xorps(result_reg, result_reg); |
4918 __ divsd(result_reg, result_reg); | 4912 __ divsd(result_reg, result_reg); |
4919 __ jmp(&done, Label::kNear); | 4913 __ jmp(&done, Label::kNear); |
4920 } | 4914 } |
4921 } else { | 4915 } else { |
4922 DCHECK(mode == NUMBER_CANDIDATE_IS_SMI); | 4916 DCHECK(mode == NUMBER_CANDIDATE_IS_SMI); |
4923 } | 4917 } |
4924 | 4918 |
4925 // Smi to XMM conversion | 4919 // Smi to XMM conversion |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5042 if (instr->truncating()) { | 5036 if (instr->truncating()) { |
5043 __ TruncateDoubleToI(result_reg, input_reg); | 5037 __ TruncateDoubleToI(result_reg, input_reg); |
5044 } else { | 5038 } else { |
5045 Label bailout, done; | 5039 Label bailout, done; |
5046 XMMRegister xmm_scratch = double_scratch0(); | 5040 XMMRegister xmm_scratch = double_scratch0(); |
5047 __ DoubleToI(result_reg, input_reg, xmm_scratch, | 5041 __ DoubleToI(result_reg, input_reg, xmm_scratch, |
5048 instr->hydrogen()->GetMinusZeroMode(), &bailout, Label::kNear); | 5042 instr->hydrogen()->GetMinusZeroMode(), &bailout, Label::kNear); |
5049 | 5043 |
5050 __ jmp(&done, Label::kNear); | 5044 __ jmp(&done, Label::kNear); |
5051 __ bind(&bailout); | 5045 __ bind(&bailout); |
5052 DeoptimizeIf(no_condition, instr); | 5046 DeoptimizeIf(no_condition, instr, "conversion failed"); |
5053 __ bind(&done); | 5047 __ bind(&done); |
5054 } | 5048 } |
5055 } | 5049 } |
5056 | 5050 |
5057 | 5051 |
5058 void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) { | 5052 void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) { |
5059 LOperand* input = instr->value(); | 5053 LOperand* input = instr->value(); |
5060 DCHECK(input->IsDoubleRegister()); | 5054 DCHECK(input->IsDoubleRegister()); |
5061 LOperand* result = instr->result(); | 5055 LOperand* result = instr->result(); |
5062 DCHECK(result->IsRegister()); | 5056 DCHECK(result->IsRegister()); |
5063 | 5057 |
5064 XMMRegister input_reg = ToDoubleRegister(input); | 5058 XMMRegister input_reg = ToDoubleRegister(input); |
5065 Register result_reg = ToRegister(result); | 5059 Register result_reg = ToRegister(result); |
5066 | 5060 |
5067 Label bailout, done; | 5061 Label bailout, done; |
5068 XMMRegister xmm_scratch = double_scratch0(); | 5062 XMMRegister xmm_scratch = double_scratch0(); |
5069 __ DoubleToI(result_reg, input_reg, xmm_scratch, | 5063 __ DoubleToI(result_reg, input_reg, xmm_scratch, |
5070 instr->hydrogen()->GetMinusZeroMode(), &bailout, Label::kNear); | 5064 instr->hydrogen()->GetMinusZeroMode(), &bailout, Label::kNear); |
5071 | 5065 |
5072 __ jmp(&done, Label::kNear); | 5066 __ jmp(&done, Label::kNear); |
5073 __ bind(&bailout); | 5067 __ bind(&bailout); |
5074 DeoptimizeIf(no_condition, instr); | 5068 DeoptimizeIf(no_condition, instr, "conversion failed"); |
5075 __ bind(&done); | 5069 __ bind(&done); |
5076 | 5070 |
5077 __ Integer32ToSmi(result_reg, result_reg); | 5071 __ Integer32ToSmi(result_reg, result_reg); |
5078 DeoptimizeIf(overflow, instr); | 5072 DeoptimizeIf(overflow, instr, "overflow"); |
5079 } | 5073 } |
5080 | 5074 |
5081 | 5075 |
5082 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { | 5076 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { |
5083 LOperand* input = instr->value(); | 5077 LOperand* input = instr->value(); |
5084 Condition cc = masm()->CheckSmi(ToRegister(input)); | 5078 Condition cc = masm()->CheckSmi(ToRegister(input)); |
5085 DeoptimizeIf(NegateCondition(cc), instr); | 5079 DeoptimizeIf(NegateCondition(cc), instr, "not a Smi"); |
5086 } | 5080 } |
5087 | 5081 |
5088 | 5082 |
5089 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { | 5083 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { |
5090 if (!instr->hydrogen()->value()->type().IsHeapObject()) { | 5084 if (!instr->hydrogen()->value()->type().IsHeapObject()) { |
5091 LOperand* input = instr->value(); | 5085 LOperand* input = instr->value(); |
5092 Condition cc = masm()->CheckSmi(ToRegister(input)); | 5086 Condition cc = masm()->CheckSmi(ToRegister(input)); |
5093 DeoptimizeIf(cc, instr); | 5087 DeoptimizeIf(cc, instr, "Smi"); |
5094 } | 5088 } |
5095 } | 5089 } |
5096 | 5090 |
5097 | 5091 |
5098 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { | 5092 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { |
5099 Register input = ToRegister(instr->value()); | 5093 Register input = ToRegister(instr->value()); |
5100 | 5094 |
5101 __ movp(kScratchRegister, FieldOperand(input, HeapObject::kMapOffset)); | 5095 __ movp(kScratchRegister, FieldOperand(input, HeapObject::kMapOffset)); |
5102 | 5096 |
5103 if (instr->hydrogen()->is_interval_check()) { | 5097 if (instr->hydrogen()->is_interval_check()) { |
5104 InstanceType first; | 5098 InstanceType first; |
5105 InstanceType last; | 5099 InstanceType last; |
5106 instr->hydrogen()->GetCheckInterval(&first, &last); | 5100 instr->hydrogen()->GetCheckInterval(&first, &last); |
5107 | 5101 |
5108 __ cmpb(FieldOperand(kScratchRegister, Map::kInstanceTypeOffset), | 5102 __ cmpb(FieldOperand(kScratchRegister, Map::kInstanceTypeOffset), |
5109 Immediate(static_cast<int8_t>(first))); | 5103 Immediate(static_cast<int8_t>(first))); |
5110 | 5104 |
5111 // If there is only one type in the interval check for equality. | 5105 // If there is only one type in the interval check for equality. |
5112 if (first == last) { | 5106 if (first == last) { |
5113 DeoptimizeIf(not_equal, instr); | 5107 DeoptimizeIf(not_equal, instr, "wrong instance type"); |
5114 } else { | 5108 } else { |
5115 DeoptimizeIf(below, instr); | 5109 DeoptimizeIf(below, instr, "wrong instance type"); |
5116 // Omit check for the last type. | 5110 // Omit check for the last type. |
5117 if (last != LAST_TYPE) { | 5111 if (last != LAST_TYPE) { |
5118 __ cmpb(FieldOperand(kScratchRegister, Map::kInstanceTypeOffset), | 5112 __ cmpb(FieldOperand(kScratchRegister, Map::kInstanceTypeOffset), |
5119 Immediate(static_cast<int8_t>(last))); | 5113 Immediate(static_cast<int8_t>(last))); |
5120 DeoptimizeIf(above, instr); | 5114 DeoptimizeIf(above, instr, "wrong instance type"); |
5121 } | 5115 } |
5122 } | 5116 } |
5123 } else { | 5117 } else { |
5124 uint8_t mask; | 5118 uint8_t mask; |
5125 uint8_t tag; | 5119 uint8_t tag; |
5126 instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag); | 5120 instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag); |
5127 | 5121 |
5128 if (base::bits::IsPowerOfTwo32(mask)) { | 5122 if (base::bits::IsPowerOfTwo32(mask)) { |
5129 DCHECK(tag == 0 || base::bits::IsPowerOfTwo32(tag)); | 5123 DCHECK(tag == 0 || base::bits::IsPowerOfTwo32(tag)); |
5130 __ testb(FieldOperand(kScratchRegister, Map::kInstanceTypeOffset), | 5124 __ testb(FieldOperand(kScratchRegister, Map::kInstanceTypeOffset), |
5131 Immediate(mask)); | 5125 Immediate(mask)); |
5132 DeoptimizeIf(tag == 0 ? not_zero : zero, instr); | 5126 DeoptimizeIf(tag == 0 ? not_zero : zero, instr, "wrong instance type"); |
5133 } else { | 5127 } else { |
5134 __ movzxbl(kScratchRegister, | 5128 __ movzxbl(kScratchRegister, |
5135 FieldOperand(kScratchRegister, Map::kInstanceTypeOffset)); | 5129 FieldOperand(kScratchRegister, Map::kInstanceTypeOffset)); |
5136 __ andb(kScratchRegister, Immediate(mask)); | 5130 __ andb(kScratchRegister, Immediate(mask)); |
5137 __ cmpb(kScratchRegister, Immediate(tag)); | 5131 __ cmpb(kScratchRegister, Immediate(tag)); |
5138 DeoptimizeIf(not_equal, instr); | 5132 DeoptimizeIf(not_equal, instr, "wrong instance type"); |
5139 } | 5133 } |
5140 } | 5134 } |
5141 } | 5135 } |
5142 | 5136 |
5143 | 5137 |
5144 void LCodeGen::DoCheckValue(LCheckValue* instr) { | 5138 void LCodeGen::DoCheckValue(LCheckValue* instr) { |
5145 Register reg = ToRegister(instr->value()); | 5139 Register reg = ToRegister(instr->value()); |
5146 __ Cmp(reg, instr->hydrogen()->object().handle()); | 5140 __ Cmp(reg, instr->hydrogen()->object().handle()); |
5147 DeoptimizeIf(not_equal, instr); | 5141 DeoptimizeIf(not_equal, instr, "value mismatch"); |
5148 } | 5142 } |
5149 | 5143 |
5150 | 5144 |
5151 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) { | 5145 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) { |
5152 { | 5146 { |
5153 PushSafepointRegistersScope scope(this); | 5147 PushSafepointRegistersScope scope(this); |
5154 __ Push(object); | 5148 __ Push(object); |
5155 __ Set(rsi, 0); | 5149 __ Set(rsi, 0); |
5156 __ CallRuntimeSaveDoubles(Runtime::kTryMigrateInstance); | 5150 __ CallRuntimeSaveDoubles(Runtime::kTryMigrateInstance); |
5157 RecordSafepointWithRegisters( | 5151 RecordSafepointWithRegisters( |
5158 instr->pointer_map(), 1, Safepoint::kNoLazyDeopt); | 5152 instr->pointer_map(), 1, Safepoint::kNoLazyDeopt); |
5159 | 5153 |
5160 __ testp(rax, Immediate(kSmiTagMask)); | 5154 __ testp(rax, Immediate(kSmiTagMask)); |
5161 } | 5155 } |
5162 DeoptimizeIf(zero, instr); | 5156 DeoptimizeIf(zero, instr, "instance migration failed"); |
5163 } | 5157 } |
5164 | 5158 |
5165 | 5159 |
5166 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { | 5160 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { |
5167 class DeferredCheckMaps FINAL : public LDeferredCode { | 5161 class DeferredCheckMaps FINAL : public LDeferredCode { |
5168 public: | 5162 public: |
5169 DeferredCheckMaps(LCodeGen* codegen, LCheckMaps* instr, Register object) | 5163 DeferredCheckMaps(LCodeGen* codegen, LCheckMaps* instr, Register object) |
5170 : LDeferredCode(codegen), instr_(instr), object_(object) { | 5164 : LDeferredCode(codegen), instr_(instr), object_(object) { |
5171 SetExit(check_maps()); | 5165 SetExit(check_maps()); |
5172 } | 5166 } |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5205 Handle<Map> map = maps->at(i).handle(); | 5199 Handle<Map> map = maps->at(i).handle(); |
5206 __ CompareMap(reg, map); | 5200 __ CompareMap(reg, map); |
5207 __ j(equal, &success, Label::kNear); | 5201 __ j(equal, &success, Label::kNear); |
5208 } | 5202 } |
5209 | 5203 |
5210 Handle<Map> map = maps->at(maps->size() - 1).handle(); | 5204 Handle<Map> map = maps->at(maps->size() - 1).handle(); |
5211 __ CompareMap(reg, map); | 5205 __ CompareMap(reg, map); |
5212 if (instr->hydrogen()->HasMigrationTarget()) { | 5206 if (instr->hydrogen()->HasMigrationTarget()) { |
5213 __ j(not_equal, deferred->entry()); | 5207 __ j(not_equal, deferred->entry()); |
5214 } else { | 5208 } else { |
5215 DeoptimizeIf(not_equal, instr); | 5209 DeoptimizeIf(not_equal, instr, "wrong map"); |
5216 } | 5210 } |
5217 | 5211 |
5218 __ bind(&success); | 5212 __ bind(&success); |
5219 } | 5213 } |
5220 | 5214 |
5221 | 5215 |
5222 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { | 5216 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { |
5223 XMMRegister value_reg = ToDoubleRegister(instr->unclamped()); | 5217 XMMRegister value_reg = ToDoubleRegister(instr->unclamped()); |
5224 XMMRegister xmm_scratch = double_scratch0(); | 5218 XMMRegister xmm_scratch = double_scratch0(); |
5225 Register result_reg = ToRegister(instr->result()); | 5219 Register result_reg = ToRegister(instr->result()); |
(...skipping 18 matching lines...) Expand all Loading... |
5244 __ JumpIfSmi(input_reg, &is_smi, dist); | 5238 __ JumpIfSmi(input_reg, &is_smi, dist); |
5245 | 5239 |
5246 // Check for heap number | 5240 // Check for heap number |
5247 __ Cmp(FieldOperand(input_reg, HeapObject::kMapOffset), | 5241 __ Cmp(FieldOperand(input_reg, HeapObject::kMapOffset), |
5248 factory()->heap_number_map()); | 5242 factory()->heap_number_map()); |
5249 __ j(equal, &heap_number, Label::kNear); | 5243 __ j(equal, &heap_number, Label::kNear); |
5250 | 5244 |
5251 // Check for undefined. Undefined is converted to zero for clamping | 5245 // Check for undefined. Undefined is converted to zero for clamping |
5252 // conversions. | 5246 // conversions. |
5253 __ Cmp(input_reg, factory()->undefined_value()); | 5247 __ Cmp(input_reg, factory()->undefined_value()); |
5254 DeoptimizeIf(not_equal, instr); | 5248 DeoptimizeIf(not_equal, instr, "neither a heap number nor undefined"); |
5255 __ xorl(input_reg, input_reg); | 5249 __ xorl(input_reg, input_reg); |
5256 __ jmp(&done, Label::kNear); | 5250 __ jmp(&done, Label::kNear); |
5257 | 5251 |
5258 // Heap number | 5252 // Heap number |
5259 __ bind(&heap_number); | 5253 __ bind(&heap_number); |
5260 __ movsd(xmm_scratch, FieldOperand(input_reg, HeapNumber::kValueOffset)); | 5254 __ movsd(xmm_scratch, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
5261 __ ClampDoubleToUint8(xmm_scratch, temp_xmm_reg, input_reg); | 5255 __ ClampDoubleToUint8(xmm_scratch, temp_xmm_reg, input_reg); |
5262 __ jmp(&done, Label::kNear); | 5256 __ jmp(&done, Label::kNear); |
5263 | 5257 |
5264 // smi | 5258 // smi |
(...skipping 460 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5725 DCHECK(!environment->HasBeenRegistered()); | 5719 DCHECK(!environment->HasBeenRegistered()); |
5726 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); | 5720 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); |
5727 | 5721 |
5728 GenerateOsrPrologue(); | 5722 GenerateOsrPrologue(); |
5729 } | 5723 } |
5730 | 5724 |
5731 | 5725 |
5732 void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) { | 5726 void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) { |
5733 DCHECK(ToRegister(instr->context()).is(rsi)); | 5727 DCHECK(ToRegister(instr->context()).is(rsi)); |
5734 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); | 5728 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); |
5735 DeoptimizeIf(equal, instr); | 5729 DeoptimizeIf(equal, instr, "undefined"); |
5736 | 5730 |
5737 Register null_value = rdi; | 5731 Register null_value = rdi; |
5738 __ LoadRoot(null_value, Heap::kNullValueRootIndex); | 5732 __ LoadRoot(null_value, Heap::kNullValueRootIndex); |
5739 __ cmpp(rax, null_value); | 5733 __ cmpp(rax, null_value); |
5740 DeoptimizeIf(equal, instr); | 5734 DeoptimizeIf(equal, instr, "null"); |
5741 | 5735 |
5742 Condition cc = masm()->CheckSmi(rax); | 5736 Condition cc = masm()->CheckSmi(rax); |
5743 DeoptimizeIf(cc, instr); | 5737 DeoptimizeIf(cc, instr, "Smi"); |
5744 | 5738 |
5745 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); | 5739 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); |
5746 __ CmpObjectType(rax, LAST_JS_PROXY_TYPE, rcx); | 5740 __ CmpObjectType(rax, LAST_JS_PROXY_TYPE, rcx); |
5747 DeoptimizeIf(below_equal, instr); | 5741 DeoptimizeIf(below_equal, instr, "wrong instance type"); |
5748 | 5742 |
5749 Label use_cache, call_runtime; | 5743 Label use_cache, call_runtime; |
5750 __ CheckEnumCache(null_value, &call_runtime); | 5744 __ CheckEnumCache(null_value, &call_runtime); |
5751 | 5745 |
5752 __ movp(rax, FieldOperand(rax, HeapObject::kMapOffset)); | 5746 __ movp(rax, FieldOperand(rax, HeapObject::kMapOffset)); |
5753 __ jmp(&use_cache, Label::kNear); | 5747 __ jmp(&use_cache, Label::kNear); |
5754 | 5748 |
5755 // Get the set of properties to enumerate. | 5749 // Get the set of properties to enumerate. |
5756 __ bind(&call_runtime); | 5750 __ bind(&call_runtime); |
5757 __ Push(rax); | 5751 __ Push(rax); |
5758 CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr); | 5752 CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr); |
5759 | 5753 |
5760 __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset), | 5754 __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset), |
5761 Heap::kMetaMapRootIndex); | 5755 Heap::kMetaMapRootIndex); |
5762 DeoptimizeIf(not_equal, instr); | 5756 DeoptimizeIf(not_equal, instr, "not a meta map"); |
5763 __ bind(&use_cache); | 5757 __ bind(&use_cache); |
5764 } | 5758 } |
5765 | 5759 |
5766 | 5760 |
5767 void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) { | 5761 void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) { |
5768 Register map = ToRegister(instr->map()); | 5762 Register map = ToRegister(instr->map()); |
5769 Register result = ToRegister(instr->result()); | 5763 Register result = ToRegister(instr->result()); |
5770 Label load_cache, done; | 5764 Label load_cache, done; |
5771 __ EnumLength(result, map); | 5765 __ EnumLength(result, map); |
5772 __ Cmp(result, Smi::FromInt(0)); | 5766 __ Cmp(result, Smi::FromInt(0)); |
5773 __ j(not_equal, &load_cache, Label::kNear); | 5767 __ j(not_equal, &load_cache, Label::kNear); |
5774 __ LoadRoot(result, Heap::kEmptyFixedArrayRootIndex); | 5768 __ LoadRoot(result, Heap::kEmptyFixedArrayRootIndex); |
5775 __ jmp(&done, Label::kNear); | 5769 __ jmp(&done, Label::kNear); |
5776 __ bind(&load_cache); | 5770 __ bind(&load_cache); |
5777 __ LoadInstanceDescriptors(map, result); | 5771 __ LoadInstanceDescriptors(map, result); |
5778 __ movp(result, | 5772 __ movp(result, |
5779 FieldOperand(result, DescriptorArray::kEnumCacheOffset)); | 5773 FieldOperand(result, DescriptorArray::kEnumCacheOffset)); |
5780 __ movp(result, | 5774 __ movp(result, |
5781 FieldOperand(result, FixedArray::SizeFor(instr->idx()))); | 5775 FieldOperand(result, FixedArray::SizeFor(instr->idx()))); |
5782 __ bind(&done); | 5776 __ bind(&done); |
5783 Condition cc = masm()->CheckSmi(result); | 5777 Condition cc = masm()->CheckSmi(result); |
5784 DeoptimizeIf(cc, instr); | 5778 DeoptimizeIf(cc, instr, "Smi"); |
5785 } | 5779 } |
5786 | 5780 |
5787 | 5781 |
5788 void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) { | 5782 void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) { |
5789 Register object = ToRegister(instr->value()); | 5783 Register object = ToRegister(instr->value()); |
5790 __ cmpp(ToRegister(instr->map()), | 5784 __ cmpp(ToRegister(instr->map()), |
5791 FieldOperand(object, HeapObject::kMapOffset)); | 5785 FieldOperand(object, HeapObject::kMapOffset)); |
5792 DeoptimizeIf(not_equal, instr); | 5786 DeoptimizeIf(not_equal, instr, "wrong map"); |
5793 } | 5787 } |
5794 | 5788 |
5795 | 5789 |
5796 void LCodeGen::DoDeferredLoadMutableDouble(LLoadFieldByIndex* instr, | 5790 void LCodeGen::DoDeferredLoadMutableDouble(LLoadFieldByIndex* instr, |
5797 Register object, | 5791 Register object, |
5798 Register index) { | 5792 Register index) { |
5799 PushSafepointRegistersScope scope(this); | 5793 PushSafepointRegistersScope scope(this); |
5800 __ Push(object); | 5794 __ Push(object); |
5801 __ Push(index); | 5795 __ Push(index); |
5802 __ xorp(rsi, rsi); | 5796 __ xorp(rsi, rsi); |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5877 CallRuntime(Runtime::kPushBlockContext, 2, instr); | 5871 CallRuntime(Runtime::kPushBlockContext, 2, instr); |
5878 RecordSafepoint(Safepoint::kNoLazyDeopt); | 5872 RecordSafepoint(Safepoint::kNoLazyDeopt); |
5879 } | 5873 } |
5880 | 5874 |
5881 | 5875 |
5882 #undef __ | 5876 #undef __ |
5883 | 5877 |
5884 } } // namespace v8::internal | 5878 } } // namespace v8::internal |
5885 | 5879 |
5886 #endif // V8_TARGET_ARCH_X64 | 5880 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |