Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(216)

Side by Side Diff: src/x64/lithium-codegen-x64.cc

Issue 595513002: Further improve deopt reason output. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/x64/lithium-codegen-x64.h ('k') | src/x87/lithium-codegen-x87.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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, &dividend_is_not_negative, Label::kNear); 1030 __ j(not_sign, &dividend_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(&dividend_is_not_negative); 1041 __ bind(&dividend_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, &not_kmin_int, Label::kNear); 1165 __ j(no_overflow, &not_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(&not_kmin_int); 1168 __ bind(&not_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
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, &dividend_not_zero, Label::kNear); 1242 __ j(not_zero, &dividend_not_zero, Label::kNear);
1249 __ testl(divisor, divisor); 1243 __ testl(divisor, divisor);
1250 DeoptimizeIf(sign, instr); 1244 DeoptimizeIf(sign, instr, "minus zero");
1251 __ bind(&dividend_not_zero); 1245 __ bind(&dividend_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, &dividend_not_min_int, Label::kNear); 1252 __ j(not_zero, &dividend_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(&dividend_not_min_int); 1255 __ bind(&dividend_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, &dividend_not_zero, Label::kNear); 1361 __ j(not_zero, &dividend_not_zero, Label::kNear);
1368 __ testl(divisor, divisor); 1362 __ testl(divisor, divisor);
1369 DeoptimizeIf(sign, instr); 1363 DeoptimizeIf(sign, instr, "minus zero");
1370 __ bind(&dividend_not_zero); 1364 __ bind(&dividend_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, &dividend_not_min_int, Label::kNear); 1371 __ j(not_zero, &dividend_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(&dividend_not_min_int); 1374 __ bind(&dividend_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
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
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
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
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
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
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
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(&not_heap_number); 2223 __ bind(&not_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
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
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
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
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
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
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
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
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
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
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
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
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
4521 } 4515 }
4522 __ bind(&not_applicable); 4516 __ bind(&not_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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/x64/lithium-codegen-x64.h ('k') | src/x87/lithium-codegen-x87.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698