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

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

Issue 559143003: Thread the Lithium instruction down to DeoptimizeIf and friends. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Rebased 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.h » ('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 711 matching lines...) Expand 10 before | Expand all | Expand 10 after
722 int deoptimization_index = deoptimizations_.length(); 722 int deoptimization_index = deoptimizations_.length();
723 int pc_offset = masm()->pc_offset(); 723 int pc_offset = masm()->pc_offset();
724 environment->Register(deoptimization_index, 724 environment->Register(deoptimization_index,
725 translation.index(), 725 translation.index(),
726 (mode == Safepoint::kLazyDeopt) ? pc_offset : -1); 726 (mode == Safepoint::kLazyDeopt) ? pc_offset : -1);
727 deoptimizations_.Add(environment, environment->zone()); 727 deoptimizations_.Add(environment, environment->zone());
728 } 728 }
729 } 729 }
730 730
731 731
732 void LCodeGen::DeoptimizeIf(Condition cc, 732 void LCodeGen::DeoptimizeIf(Condition cc, LInstruction* instr,
733 LEnvironment* environment,
734 Deoptimizer::BailoutType bailout_type) { 733 Deoptimizer::BailoutType bailout_type) {
734 LEnvironment* environment = instr->environment();
735 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); 735 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
736 DCHECK(environment->HasBeenRegistered()); 736 DCHECK(environment->HasBeenRegistered());
737 int id = environment->deoptimization_index(); 737 int id = environment->deoptimization_index();
738 DCHECK(info()->IsOptimizing() || info()->IsStub()); 738 DCHECK(info()->IsOptimizing() || info()->IsStub());
739 Address entry = 739 Address entry =
740 Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type); 740 Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type);
741 if (entry == NULL) { 741 if (entry == NULL) {
742 Abort(kBailoutWasNotPrepared); 742 Abort(kBailoutWasNotPrepared);
743 return; 743 return;
744 } 744 }
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
794 } 794 }
795 if (cc == no_condition) { 795 if (cc == no_condition) {
796 __ jmp(&jump_table_.last().label); 796 __ jmp(&jump_table_.last().label);
797 } else { 797 } else {
798 __ j(cc, &jump_table_.last().label); 798 __ j(cc, &jump_table_.last().label);
799 } 799 }
800 } 800 }
801 } 801 }
802 802
803 803
804 void LCodeGen::DeoptimizeIf(Condition cc, 804 void LCodeGen::DeoptimizeIf(Condition cc, LInstruction* instr) {
805 LEnvironment* environment) {
806 Deoptimizer::BailoutType bailout_type = info()->IsStub() 805 Deoptimizer::BailoutType bailout_type = info()->IsStub()
807 ? Deoptimizer::LAZY 806 ? Deoptimizer::LAZY
808 : Deoptimizer::EAGER; 807 : Deoptimizer::EAGER;
809 DeoptimizeIf(cc, environment, bailout_type); 808 DeoptimizeIf(cc, instr, bailout_type);
810 } 809 }
811 810
812 811
813 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { 812 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) {
814 int length = deoptimizations_.length(); 813 int length = deoptimizations_.length();
815 if (length == 0) return; 814 if (length == 0) return;
816 Handle<DeoptimizationInputData> data = 815 Handle<DeoptimizationInputData> data =
817 DeoptimizationInputData::New(isolate(), length, TENURED); 816 DeoptimizationInputData::New(isolate(), length, TENURED);
818 817
819 Handle<ByteArray> translations = 818 Handle<ByteArray> translations =
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after
1030 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); 1029 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1);
1031 Label dividend_is_not_negative, done; 1030 Label dividend_is_not_negative, done;
1032 if (hmod->CheckFlag(HValue::kLeftCanBeNegative)) { 1031 if (hmod->CheckFlag(HValue::kLeftCanBeNegative)) {
1033 __ testl(dividend, dividend); 1032 __ testl(dividend, dividend);
1034 __ j(not_sign, &dividend_is_not_negative, Label::kNear); 1033 __ j(not_sign, &dividend_is_not_negative, Label::kNear);
1035 // Note that this is correct even for kMinInt operands. 1034 // Note that this is correct even for kMinInt operands.
1036 __ negl(dividend); 1035 __ negl(dividend);
1037 __ andl(dividend, Immediate(mask)); 1036 __ andl(dividend, Immediate(mask));
1038 __ negl(dividend); 1037 __ negl(dividend);
1039 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { 1038 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1040 DeoptimizeIf(zero, instr->environment()); 1039 DeoptimizeIf(zero, instr);
1041 } 1040 }
1042 __ jmp(&done, Label::kNear); 1041 __ jmp(&done, Label::kNear);
1043 } 1042 }
1044 1043
1045 __ bind(&dividend_is_not_negative); 1044 __ bind(&dividend_is_not_negative);
1046 __ andl(dividend, Immediate(mask)); 1045 __ andl(dividend, Immediate(mask));
1047 __ bind(&done); 1046 __ bind(&done);
1048 } 1047 }
1049 1048
1050 1049
1051 void LCodeGen::DoModByConstI(LModByConstI* instr) { 1050 void LCodeGen::DoModByConstI(LModByConstI* instr) {
1052 Register dividend = ToRegister(instr->dividend()); 1051 Register dividend = ToRegister(instr->dividend());
1053 int32_t divisor = instr->divisor(); 1052 int32_t divisor = instr->divisor();
1054 DCHECK(ToRegister(instr->result()).is(rax)); 1053 DCHECK(ToRegister(instr->result()).is(rax));
1055 1054
1056 if (divisor == 0) { 1055 if (divisor == 0) {
1057 DeoptimizeIf(no_condition, instr->environment()); 1056 DeoptimizeIf(no_condition, instr);
1058 return; 1057 return;
1059 } 1058 }
1060 1059
1061 __ TruncatingDiv(dividend, Abs(divisor)); 1060 __ TruncatingDiv(dividend, Abs(divisor));
1062 __ imull(rdx, rdx, Immediate(Abs(divisor))); 1061 __ imull(rdx, rdx, Immediate(Abs(divisor)));
1063 __ movl(rax, dividend); 1062 __ movl(rax, dividend);
1064 __ subl(rax, rdx); 1063 __ subl(rax, rdx);
1065 1064
1066 // Check for negative zero. 1065 // Check for negative zero.
1067 HMod* hmod = instr->hydrogen(); 1066 HMod* hmod = instr->hydrogen();
1068 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { 1067 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1069 Label remainder_not_zero; 1068 Label remainder_not_zero;
1070 __ j(not_zero, &remainder_not_zero, Label::kNear); 1069 __ j(not_zero, &remainder_not_zero, Label::kNear);
1071 __ cmpl(dividend, Immediate(0)); 1070 __ cmpl(dividend, Immediate(0));
1072 DeoptimizeIf(less, instr->environment()); 1071 DeoptimizeIf(less, instr);
1073 __ bind(&remainder_not_zero); 1072 __ bind(&remainder_not_zero);
1074 } 1073 }
1075 } 1074 }
1076 1075
1077 1076
1078 void LCodeGen::DoModI(LModI* instr) { 1077 void LCodeGen::DoModI(LModI* instr) {
1079 HMod* hmod = instr->hydrogen(); 1078 HMod* hmod = instr->hydrogen();
1080 1079
1081 Register left_reg = ToRegister(instr->left()); 1080 Register left_reg = ToRegister(instr->left());
1082 DCHECK(left_reg.is(rax)); 1081 DCHECK(left_reg.is(rax));
1083 Register right_reg = ToRegister(instr->right()); 1082 Register right_reg = ToRegister(instr->right());
1084 DCHECK(!right_reg.is(rax)); 1083 DCHECK(!right_reg.is(rax));
1085 DCHECK(!right_reg.is(rdx)); 1084 DCHECK(!right_reg.is(rdx));
1086 Register result_reg = ToRegister(instr->result()); 1085 Register result_reg = ToRegister(instr->result());
1087 DCHECK(result_reg.is(rdx)); 1086 DCHECK(result_reg.is(rdx));
1088 1087
1089 Label done; 1088 Label done;
1090 // Check for x % 0, idiv would signal a divide error. We have to 1089 // Check for x % 0, idiv would signal a divide error. We have to
1091 // deopt in this case because we can't return a NaN. 1090 // deopt in this case because we can't return a NaN.
1092 if (hmod->CheckFlag(HValue::kCanBeDivByZero)) { 1091 if (hmod->CheckFlag(HValue::kCanBeDivByZero)) {
1093 __ testl(right_reg, right_reg); 1092 __ testl(right_reg, right_reg);
1094 DeoptimizeIf(zero, instr->environment()); 1093 DeoptimizeIf(zero, instr);
1095 } 1094 }
1096 1095
1097 // Check for kMinInt % -1, idiv would signal a divide error. We 1096 // Check for kMinInt % -1, idiv would signal a divide error. We
1098 // have to deopt if we care about -0, because we can't return that. 1097 // have to deopt if we care about -0, because we can't return that.
1099 if (hmod->CheckFlag(HValue::kCanOverflow)) { 1098 if (hmod->CheckFlag(HValue::kCanOverflow)) {
1100 Label no_overflow_possible; 1099 Label no_overflow_possible;
1101 __ cmpl(left_reg, Immediate(kMinInt)); 1100 __ cmpl(left_reg, Immediate(kMinInt));
1102 __ j(not_zero, &no_overflow_possible, Label::kNear); 1101 __ j(not_zero, &no_overflow_possible, Label::kNear);
1103 __ cmpl(right_reg, Immediate(-1)); 1102 __ cmpl(right_reg, Immediate(-1));
1104 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { 1103 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1105 DeoptimizeIf(equal, instr->environment()); 1104 DeoptimizeIf(equal, instr);
1106 } else { 1105 } else {
1107 __ j(not_equal, &no_overflow_possible, Label::kNear); 1106 __ j(not_equal, &no_overflow_possible, Label::kNear);
1108 __ Set(result_reg, 0); 1107 __ Set(result_reg, 0);
1109 __ jmp(&done, Label::kNear); 1108 __ jmp(&done, Label::kNear);
1110 } 1109 }
1111 __ bind(&no_overflow_possible); 1110 __ bind(&no_overflow_possible);
1112 } 1111 }
1113 1112
1114 // Sign extend dividend in eax into edx:eax, since we are using only the low 1113 // Sign extend dividend in eax into edx:eax, since we are using only the low
1115 // 32 bits of the values. 1114 // 32 bits of the values.
1116 __ cdq(); 1115 __ cdq();
1117 1116
1118 // If we care about -0, test if the dividend is <0 and the result is 0. 1117 // If we care about -0, test if the dividend is <0 and the result is 0.
1119 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { 1118 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1120 Label positive_left; 1119 Label positive_left;
1121 __ testl(left_reg, left_reg); 1120 __ testl(left_reg, left_reg);
1122 __ j(not_sign, &positive_left, Label::kNear); 1121 __ j(not_sign, &positive_left, Label::kNear);
1123 __ idivl(right_reg); 1122 __ idivl(right_reg);
1124 __ testl(result_reg, result_reg); 1123 __ testl(result_reg, result_reg);
1125 DeoptimizeIf(zero, instr->environment()); 1124 DeoptimizeIf(zero, instr);
1126 __ jmp(&done, Label::kNear); 1125 __ jmp(&done, Label::kNear);
1127 __ bind(&positive_left); 1126 __ bind(&positive_left);
1128 } 1127 }
1129 __ idivl(right_reg); 1128 __ idivl(right_reg);
1130 __ bind(&done); 1129 __ bind(&done);
1131 } 1130 }
1132 1131
1133 1132
1134 void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) { 1133 void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) {
1135 Register dividend = ToRegister(instr->dividend()); 1134 Register dividend = ToRegister(instr->dividend());
1136 int32_t divisor = instr->divisor(); 1135 int32_t divisor = instr->divisor();
1137 DCHECK(dividend.is(ToRegister(instr->result()))); 1136 DCHECK(dividend.is(ToRegister(instr->result())));
1138 1137
1139 // If the divisor is positive, things are easy: There can be no deopts and we 1138 // If the divisor is positive, things are easy: There can be no deopts and we
1140 // can simply do an arithmetic right shift. 1139 // can simply do an arithmetic right shift.
1141 if (divisor == 1) return; 1140 if (divisor == 1) return;
1142 int32_t shift = WhichPowerOf2Abs(divisor); 1141 int32_t shift = WhichPowerOf2Abs(divisor);
1143 if (divisor > 1) { 1142 if (divisor > 1) {
1144 __ sarl(dividend, Immediate(shift)); 1143 __ sarl(dividend, Immediate(shift));
1145 return; 1144 return;
1146 } 1145 }
1147 1146
1148 // If the divisor is negative, we have to negate and handle edge cases. 1147 // If the divisor is negative, we have to negate and handle edge cases.
1149 __ negl(dividend); 1148 __ negl(dividend);
1150 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 1149 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
1151 DeoptimizeIf(zero, instr->environment()); 1150 DeoptimizeIf(zero, instr);
1152 } 1151 }
1153 1152
1154 // Dividing by -1 is basically negation, unless we overflow. 1153 // Dividing by -1 is basically negation, unless we overflow.
1155 if (divisor == -1) { 1154 if (divisor == -1) {
1156 if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { 1155 if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) {
1157 DeoptimizeIf(overflow, instr->environment()); 1156 DeoptimizeIf(overflow, instr);
1158 } 1157 }
1159 return; 1158 return;
1160 } 1159 }
1161 1160
1162 // If the negation could not overflow, simply shifting is OK. 1161 // If the negation could not overflow, simply shifting is OK.
1163 if (!instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { 1162 if (!instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) {
1164 __ sarl(dividend, Immediate(shift)); 1163 __ sarl(dividend, Immediate(shift));
1165 return; 1164 return;
1166 } 1165 }
1167 1166
1168 Label not_kmin_int, done; 1167 Label not_kmin_int, done;
1169 __ j(no_overflow, &not_kmin_int, Label::kNear); 1168 __ j(no_overflow, &not_kmin_int, Label::kNear);
1170 __ movl(dividend, Immediate(kMinInt / divisor)); 1169 __ movl(dividend, Immediate(kMinInt / divisor));
1171 __ jmp(&done, Label::kNear); 1170 __ jmp(&done, Label::kNear);
1172 __ bind(&not_kmin_int); 1171 __ bind(&not_kmin_int);
1173 __ sarl(dividend, Immediate(shift)); 1172 __ sarl(dividend, Immediate(shift));
1174 __ bind(&done); 1173 __ bind(&done);
1175 } 1174 }
1176 1175
1177 1176
1178 void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) { 1177 void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) {
1179 Register dividend = ToRegister(instr->dividend()); 1178 Register dividend = ToRegister(instr->dividend());
1180 int32_t divisor = instr->divisor(); 1179 int32_t divisor = instr->divisor();
1181 DCHECK(ToRegister(instr->result()).is(rdx)); 1180 DCHECK(ToRegister(instr->result()).is(rdx));
1182 1181
1183 if (divisor == 0) { 1182 if (divisor == 0) {
1184 DeoptimizeIf(no_condition, instr->environment()); 1183 DeoptimizeIf(no_condition, instr);
1185 return; 1184 return;
1186 } 1185 }
1187 1186
1188 // Check for (0 / -x) that will produce negative zero. 1187 // Check for (0 / -x) that will produce negative zero.
1189 HMathFloorOfDiv* hdiv = instr->hydrogen(); 1188 HMathFloorOfDiv* hdiv = instr->hydrogen();
1190 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { 1189 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
1191 __ testl(dividend, dividend); 1190 __ testl(dividend, dividend);
1192 DeoptimizeIf(zero, instr->environment()); 1191 DeoptimizeIf(zero, instr);
1193 } 1192 }
1194 1193
1195 // Easy case: We need no dynamic check for the dividend and the flooring 1194 // Easy case: We need no dynamic check for the dividend and the flooring
1196 // division is the same as the truncating division. 1195 // division is the same as the truncating division.
1197 if ((divisor > 0 && !hdiv->CheckFlag(HValue::kLeftCanBeNegative)) || 1196 if ((divisor > 0 && !hdiv->CheckFlag(HValue::kLeftCanBeNegative)) ||
1198 (divisor < 0 && !hdiv->CheckFlag(HValue::kLeftCanBePositive))) { 1197 (divisor < 0 && !hdiv->CheckFlag(HValue::kLeftCanBePositive))) {
1199 __ TruncatingDiv(dividend, Abs(divisor)); 1198 __ TruncatingDiv(dividend, Abs(divisor));
1200 if (divisor < 0) __ negl(rdx); 1199 if (divisor < 0) __ negl(rdx);
1201 return; 1200 return;
1202 } 1201 }
(...skipping 26 matching lines...) Expand all
1229 Register result = ToRegister(instr->result()); 1228 Register result = ToRegister(instr->result());
1230 DCHECK(dividend.is(rax)); 1229 DCHECK(dividend.is(rax));
1231 DCHECK(remainder.is(rdx)); 1230 DCHECK(remainder.is(rdx));
1232 DCHECK(result.is(rax)); 1231 DCHECK(result.is(rax));
1233 DCHECK(!divisor.is(rax)); 1232 DCHECK(!divisor.is(rax));
1234 DCHECK(!divisor.is(rdx)); 1233 DCHECK(!divisor.is(rdx));
1235 1234
1236 // Check for x / 0. 1235 // Check for x / 0.
1237 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { 1236 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
1238 __ testl(divisor, divisor); 1237 __ testl(divisor, divisor);
1239 DeoptimizeIf(zero, instr->environment()); 1238 DeoptimizeIf(zero, instr);
1240 } 1239 }
1241 1240
1242 // Check for (0 / -x) that will produce negative zero. 1241 // Check for (0 / -x) that will produce negative zero.
1243 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { 1242 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) {
1244 Label dividend_not_zero; 1243 Label dividend_not_zero;
1245 __ testl(dividend, dividend); 1244 __ testl(dividend, dividend);
1246 __ j(not_zero, &dividend_not_zero, Label::kNear); 1245 __ j(not_zero, &dividend_not_zero, Label::kNear);
1247 __ testl(divisor, divisor); 1246 __ testl(divisor, divisor);
1248 DeoptimizeIf(sign, instr->environment()); 1247 DeoptimizeIf(sign, instr);
1249 __ bind(&dividend_not_zero); 1248 __ bind(&dividend_not_zero);
1250 } 1249 }
1251 1250
1252 // Check for (kMinInt / -1). 1251 // Check for (kMinInt / -1).
1253 if (hdiv->CheckFlag(HValue::kCanOverflow)) { 1252 if (hdiv->CheckFlag(HValue::kCanOverflow)) {
1254 Label dividend_not_min_int; 1253 Label dividend_not_min_int;
1255 __ cmpl(dividend, Immediate(kMinInt)); 1254 __ cmpl(dividend, Immediate(kMinInt));
1256 __ j(not_zero, &dividend_not_min_int, Label::kNear); 1255 __ j(not_zero, &dividend_not_min_int, Label::kNear);
1257 __ cmpl(divisor, Immediate(-1)); 1256 __ cmpl(divisor, Immediate(-1));
1258 DeoptimizeIf(zero, instr->environment()); 1257 DeoptimizeIf(zero, instr);
1259 __ bind(&dividend_not_min_int); 1258 __ bind(&dividend_not_min_int);
1260 } 1259 }
1261 1260
1262 // Sign extend to rdx (= remainder). 1261 // Sign extend to rdx (= remainder).
1263 __ cdq(); 1262 __ cdq();
1264 __ idivl(divisor); 1263 __ idivl(divisor);
1265 1264
1266 Label done; 1265 Label done;
1267 __ testl(remainder, remainder); 1266 __ testl(remainder, remainder);
1268 __ j(zero, &done, Label::kNear); 1267 __ j(zero, &done, Label::kNear);
1269 __ xorl(remainder, divisor); 1268 __ xorl(remainder, divisor);
1270 __ sarl(remainder, Immediate(31)); 1269 __ sarl(remainder, Immediate(31));
1271 __ addl(result, remainder); 1270 __ addl(result, remainder);
1272 __ bind(&done); 1271 __ bind(&done);
1273 } 1272 }
1274 1273
1275 1274
1276 void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) { 1275 void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) {
1277 Register dividend = ToRegister(instr->dividend()); 1276 Register dividend = ToRegister(instr->dividend());
1278 int32_t divisor = instr->divisor(); 1277 int32_t divisor = instr->divisor();
1279 Register result = ToRegister(instr->result()); 1278 Register result = ToRegister(instr->result());
1280 DCHECK(divisor == kMinInt || base::bits::IsPowerOfTwo32(Abs(divisor))); 1279 DCHECK(divisor == kMinInt || base::bits::IsPowerOfTwo32(Abs(divisor)));
1281 DCHECK(!result.is(dividend)); 1280 DCHECK(!result.is(dividend));
1282 1281
1283 // Check for (0 / -x) that will produce negative zero. 1282 // Check for (0 / -x) that will produce negative zero.
1284 HDiv* hdiv = instr->hydrogen(); 1283 HDiv* hdiv = instr->hydrogen();
1285 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { 1284 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
1286 __ testl(dividend, dividend); 1285 __ testl(dividend, dividend);
1287 DeoptimizeIf(zero, instr->environment()); 1286 DeoptimizeIf(zero, instr);
1288 } 1287 }
1289 // Check for (kMinInt / -1). 1288 // Check for (kMinInt / -1).
1290 if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) { 1289 if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) {
1291 __ cmpl(dividend, Immediate(kMinInt)); 1290 __ cmpl(dividend, Immediate(kMinInt));
1292 DeoptimizeIf(zero, instr->environment()); 1291 DeoptimizeIf(zero, instr);
1293 } 1292 }
1294 // Deoptimize if remainder will not be 0. 1293 // Deoptimize if remainder will not be 0.
1295 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) && 1294 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) &&
1296 divisor != 1 && divisor != -1) { 1295 divisor != 1 && divisor != -1) {
1297 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); 1296 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1);
1298 __ testl(dividend, Immediate(mask)); 1297 __ testl(dividend, Immediate(mask));
1299 DeoptimizeIf(not_zero, instr->environment()); 1298 DeoptimizeIf(not_zero, instr);
1300 } 1299 }
1301 __ Move(result, dividend); 1300 __ Move(result, dividend);
1302 int32_t shift = WhichPowerOf2Abs(divisor); 1301 int32_t shift = WhichPowerOf2Abs(divisor);
1303 if (shift > 0) { 1302 if (shift > 0) {
1304 // The arithmetic shift is always OK, the 'if' is an optimization only. 1303 // The arithmetic shift is always OK, the 'if' is an optimization only.
1305 if (shift > 1) __ sarl(result, Immediate(31)); 1304 if (shift > 1) __ sarl(result, Immediate(31));
1306 __ shrl(result, Immediate(32 - shift)); 1305 __ shrl(result, Immediate(32 - shift));
1307 __ addl(result, dividend); 1306 __ addl(result, dividend);
1308 __ sarl(result, Immediate(shift)); 1307 __ sarl(result, Immediate(shift));
1309 } 1308 }
1310 if (divisor < 0) __ negl(result); 1309 if (divisor < 0) __ negl(result);
1311 } 1310 }
1312 1311
1313 1312
1314 void LCodeGen::DoDivByConstI(LDivByConstI* instr) { 1313 void LCodeGen::DoDivByConstI(LDivByConstI* instr) {
1315 Register dividend = ToRegister(instr->dividend()); 1314 Register dividend = ToRegister(instr->dividend());
1316 int32_t divisor = instr->divisor(); 1315 int32_t divisor = instr->divisor();
1317 DCHECK(ToRegister(instr->result()).is(rdx)); 1316 DCHECK(ToRegister(instr->result()).is(rdx));
1318 1317
1319 if (divisor == 0) { 1318 if (divisor == 0) {
1320 DeoptimizeIf(no_condition, instr->environment()); 1319 DeoptimizeIf(no_condition, instr);
1321 return; 1320 return;
1322 } 1321 }
1323 1322
1324 // Check for (0 / -x) that will produce negative zero. 1323 // Check for (0 / -x) that will produce negative zero.
1325 HDiv* hdiv = instr->hydrogen(); 1324 HDiv* hdiv = instr->hydrogen();
1326 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { 1325 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
1327 __ testl(dividend, dividend); 1326 __ testl(dividend, dividend);
1328 DeoptimizeIf(zero, instr->environment()); 1327 DeoptimizeIf(zero, instr);
1329 } 1328 }
1330 1329
1331 __ TruncatingDiv(dividend, Abs(divisor)); 1330 __ TruncatingDiv(dividend, Abs(divisor));
1332 if (divisor < 0) __ negl(rdx); 1331 if (divisor < 0) __ negl(rdx);
1333 1332
1334 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) { 1333 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) {
1335 __ movl(rax, rdx); 1334 __ movl(rax, rdx);
1336 __ imull(rax, rax, Immediate(divisor)); 1335 __ imull(rax, rax, Immediate(divisor));
1337 __ subl(rax, dividend); 1336 __ subl(rax, dividend);
1338 DeoptimizeIf(not_equal, instr->environment()); 1337 DeoptimizeIf(not_equal, instr);
1339 } 1338 }
1340 } 1339 }
1341 1340
1342 1341
1343 // TODO(svenpanne) Refactor this to avoid code duplication with DoFlooringDivI. 1342 // TODO(svenpanne) Refactor this to avoid code duplication with DoFlooringDivI.
1344 void LCodeGen::DoDivI(LDivI* instr) { 1343 void LCodeGen::DoDivI(LDivI* instr) {
1345 HBinaryOperation* hdiv = instr->hydrogen(); 1344 HBinaryOperation* hdiv = instr->hydrogen();
1346 Register dividend = ToRegister(instr->dividend()); 1345 Register dividend = ToRegister(instr->dividend());
1347 Register divisor = ToRegister(instr->divisor()); 1346 Register divisor = ToRegister(instr->divisor());
1348 Register remainder = ToRegister(instr->temp()); 1347 Register remainder = ToRegister(instr->temp());
1349 DCHECK(dividend.is(rax)); 1348 DCHECK(dividend.is(rax));
1350 DCHECK(remainder.is(rdx)); 1349 DCHECK(remainder.is(rdx));
1351 DCHECK(ToRegister(instr->result()).is(rax)); 1350 DCHECK(ToRegister(instr->result()).is(rax));
1352 DCHECK(!divisor.is(rax)); 1351 DCHECK(!divisor.is(rax));
1353 DCHECK(!divisor.is(rdx)); 1352 DCHECK(!divisor.is(rdx));
1354 1353
1355 // Check for x / 0. 1354 // Check for x / 0.
1356 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { 1355 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
1357 __ testl(divisor, divisor); 1356 __ testl(divisor, divisor);
1358 DeoptimizeIf(zero, instr->environment()); 1357 DeoptimizeIf(zero, instr);
1359 } 1358 }
1360 1359
1361 // Check for (0 / -x) that will produce negative zero. 1360 // Check for (0 / -x) that will produce negative zero.
1362 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { 1361 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) {
1363 Label dividend_not_zero; 1362 Label dividend_not_zero;
1364 __ testl(dividend, dividend); 1363 __ testl(dividend, dividend);
1365 __ j(not_zero, &dividend_not_zero, Label::kNear); 1364 __ j(not_zero, &dividend_not_zero, Label::kNear);
1366 __ testl(divisor, divisor); 1365 __ testl(divisor, divisor);
1367 DeoptimizeIf(sign, instr->environment()); 1366 DeoptimizeIf(sign, instr);
1368 __ bind(&dividend_not_zero); 1367 __ bind(&dividend_not_zero);
1369 } 1368 }
1370 1369
1371 // Check for (kMinInt / -1). 1370 // Check for (kMinInt / -1).
1372 if (hdiv->CheckFlag(HValue::kCanOverflow)) { 1371 if (hdiv->CheckFlag(HValue::kCanOverflow)) {
1373 Label dividend_not_min_int; 1372 Label dividend_not_min_int;
1374 __ cmpl(dividend, Immediate(kMinInt)); 1373 __ cmpl(dividend, Immediate(kMinInt));
1375 __ j(not_zero, &dividend_not_min_int, Label::kNear); 1374 __ j(not_zero, &dividend_not_min_int, Label::kNear);
1376 __ cmpl(divisor, Immediate(-1)); 1375 __ cmpl(divisor, Immediate(-1));
1377 DeoptimizeIf(zero, instr->environment()); 1376 DeoptimizeIf(zero, instr);
1378 __ bind(&dividend_not_min_int); 1377 __ bind(&dividend_not_min_int);
1379 } 1378 }
1380 1379
1381 // Sign extend to rdx (= remainder). 1380 // Sign extend to rdx (= remainder).
1382 __ cdq(); 1381 __ cdq();
1383 __ idivl(divisor); 1382 __ idivl(divisor);
1384 1383
1385 if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { 1384 if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
1386 // Deoptimize if remainder is not 0. 1385 // Deoptimize if remainder is not 0.
1387 __ testl(remainder, remainder); 1386 __ testl(remainder, remainder);
1388 DeoptimizeIf(not_zero, instr->environment()); 1387 DeoptimizeIf(not_zero, instr);
1389 } 1388 }
1390 } 1389 }
1391 1390
1392 1391
1393 void LCodeGen::DoMulI(LMulI* instr) { 1392 void LCodeGen::DoMulI(LMulI* instr) {
1394 Register left = ToRegister(instr->left()); 1393 Register left = ToRegister(instr->left());
1395 LOperand* right = instr->right(); 1394 LOperand* right = instr->right();
1396 1395
1397 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 1396 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
1398 if (instr->hydrogen_value()->representation().IsSmi()) { 1397 if (instr->hydrogen_value()->representation().IsSmi()) {
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
1455 } else { 1454 } else {
1456 if (instr->hydrogen_value()->representation().IsSmi()) { 1455 if (instr->hydrogen_value()->representation().IsSmi()) {
1457 __ SmiToInteger64(left, left); 1456 __ SmiToInteger64(left, left);
1458 __ imulp(left, ToRegister(right)); 1457 __ imulp(left, ToRegister(right));
1459 } else { 1458 } else {
1460 __ imull(left, ToRegister(right)); 1459 __ imull(left, ToRegister(right));
1461 } 1460 }
1462 } 1461 }
1463 1462
1464 if (can_overflow) { 1463 if (can_overflow) {
1465 DeoptimizeIf(overflow, instr->environment()); 1464 DeoptimizeIf(overflow, instr);
1466 } 1465 }
1467 1466
1468 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 1467 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
1469 // Bail out if the result is supposed to be negative zero. 1468 // Bail out if the result is supposed to be negative zero.
1470 Label done; 1469 Label done;
1471 if (instr->hydrogen_value()->representation().IsSmi()) { 1470 if (instr->hydrogen_value()->representation().IsSmi()) {
1472 __ testp(left, left); 1471 __ testp(left, left);
1473 } else { 1472 } else {
1474 __ testl(left, left); 1473 __ testl(left, left);
1475 } 1474 }
1476 __ j(not_zero, &done, Label::kNear); 1475 __ j(not_zero, &done, Label::kNear);
1477 if (right->IsConstantOperand()) { 1476 if (right->IsConstantOperand()) {
1478 // Constant can't be represented as 32-bit Smi due to immediate size 1477 // Constant can't be represented as 32-bit Smi due to immediate size
1479 // limit. 1478 // limit.
1480 DCHECK(SmiValuesAre32Bits() 1479 DCHECK(SmiValuesAre32Bits()
1481 ? !instr->hydrogen_value()->representation().IsSmi() 1480 ? !instr->hydrogen_value()->representation().IsSmi()
1482 : SmiValuesAre31Bits()); 1481 : SmiValuesAre31Bits());
1483 if (ToInteger32(LConstantOperand::cast(right)) < 0) { 1482 if (ToInteger32(LConstantOperand::cast(right)) < 0) {
1484 DeoptimizeIf(no_condition, instr->environment()); 1483 DeoptimizeIf(no_condition, instr);
1485 } else if (ToInteger32(LConstantOperand::cast(right)) == 0) { 1484 } else if (ToInteger32(LConstantOperand::cast(right)) == 0) {
1486 __ cmpl(kScratchRegister, Immediate(0)); 1485 __ cmpl(kScratchRegister, Immediate(0));
1487 DeoptimizeIf(less, instr->environment()); 1486 DeoptimizeIf(less, instr);
1488 } 1487 }
1489 } else if (right->IsStackSlot()) { 1488 } else if (right->IsStackSlot()) {
1490 if (instr->hydrogen_value()->representation().IsSmi()) { 1489 if (instr->hydrogen_value()->representation().IsSmi()) {
1491 __ orp(kScratchRegister, ToOperand(right)); 1490 __ orp(kScratchRegister, ToOperand(right));
1492 } else { 1491 } else {
1493 __ orl(kScratchRegister, ToOperand(right)); 1492 __ orl(kScratchRegister, ToOperand(right));
1494 } 1493 }
1495 DeoptimizeIf(sign, instr->environment()); 1494 DeoptimizeIf(sign, instr);
1496 } else { 1495 } else {
1497 // Test the non-zero operand for negative sign. 1496 // Test the non-zero operand for negative sign.
1498 if (instr->hydrogen_value()->representation().IsSmi()) { 1497 if (instr->hydrogen_value()->representation().IsSmi()) {
1499 __ orp(kScratchRegister, ToRegister(right)); 1498 __ orp(kScratchRegister, ToRegister(right));
1500 } else { 1499 } else {
1501 __ orl(kScratchRegister, ToRegister(right)); 1500 __ orl(kScratchRegister, ToRegister(right));
1502 } 1501 }
1503 DeoptimizeIf(sign, instr->environment()); 1502 DeoptimizeIf(sign, instr);
1504 } 1503 }
1505 __ bind(&done); 1504 __ bind(&done);
1506 } 1505 }
1507 } 1506 }
1508 1507
1509 1508
1510 void LCodeGen::DoBitI(LBitI* instr) { 1509 void LCodeGen::DoBitI(LBitI* instr) {
1511 LOperand* left = instr->left(); 1510 LOperand* left = instr->left();
1512 LOperand* right = instr->right(); 1511 LOperand* right = instr->right();
1513 DCHECK(left->Equals(instr->result())); 1512 DCHECK(left->Equals(instr->result()));
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
1606 case Token::ROR: 1605 case Token::ROR:
1607 __ rorl_cl(ToRegister(left)); 1606 __ rorl_cl(ToRegister(left));
1608 break; 1607 break;
1609 case Token::SAR: 1608 case Token::SAR:
1610 __ sarl_cl(ToRegister(left)); 1609 __ sarl_cl(ToRegister(left));
1611 break; 1610 break;
1612 case Token::SHR: 1611 case Token::SHR:
1613 __ shrl_cl(ToRegister(left)); 1612 __ shrl_cl(ToRegister(left));
1614 if (instr->can_deopt()) { 1613 if (instr->can_deopt()) {
1615 __ testl(ToRegister(left), ToRegister(left)); 1614 __ testl(ToRegister(left), ToRegister(left));
1616 DeoptimizeIf(negative, instr->environment()); 1615 DeoptimizeIf(negative, instr);
1617 } 1616 }
1618 break; 1617 break;
1619 case Token::SHL: 1618 case Token::SHL:
1620 __ shll_cl(ToRegister(left)); 1619 __ shll_cl(ToRegister(left));
1621 break; 1620 break;
1622 default: 1621 default:
1623 UNREACHABLE(); 1622 UNREACHABLE();
1624 break; 1623 break;
1625 } 1624 }
1626 } else { 1625 } else {
1627 int32_t value = ToInteger32(LConstantOperand::cast(right)); 1626 int32_t value = ToInteger32(LConstantOperand::cast(right));
1628 uint8_t shift_count = static_cast<uint8_t>(value & 0x1F); 1627 uint8_t shift_count = static_cast<uint8_t>(value & 0x1F);
1629 switch (instr->op()) { 1628 switch (instr->op()) {
1630 case Token::ROR: 1629 case Token::ROR:
1631 if (shift_count != 0) { 1630 if (shift_count != 0) {
1632 __ rorl(ToRegister(left), Immediate(shift_count)); 1631 __ rorl(ToRegister(left), Immediate(shift_count));
1633 } 1632 }
1634 break; 1633 break;
1635 case Token::SAR: 1634 case Token::SAR:
1636 if (shift_count != 0) { 1635 if (shift_count != 0) {
1637 __ sarl(ToRegister(left), Immediate(shift_count)); 1636 __ sarl(ToRegister(left), Immediate(shift_count));
1638 } 1637 }
1639 break; 1638 break;
1640 case Token::SHR: 1639 case Token::SHR:
1641 if (shift_count != 0) { 1640 if (shift_count != 0) {
1642 __ shrl(ToRegister(left), Immediate(shift_count)); 1641 __ shrl(ToRegister(left), Immediate(shift_count));
1643 } else if (instr->can_deopt()) { 1642 } else if (instr->can_deopt()) {
1644 __ testl(ToRegister(left), ToRegister(left)); 1643 __ testl(ToRegister(left), ToRegister(left));
1645 DeoptimizeIf(negative, instr->environment()); 1644 DeoptimizeIf(negative, instr);
1646 } 1645 }
1647 break; 1646 break;
1648 case Token::SHL: 1647 case Token::SHL:
1649 if (shift_count != 0) { 1648 if (shift_count != 0) {
1650 if (instr->hydrogen_value()->representation().IsSmi()) { 1649 if (instr->hydrogen_value()->representation().IsSmi()) {
1651 if (SmiValuesAre32Bits()) { 1650 if (SmiValuesAre32Bits()) {
1652 __ shlp(ToRegister(left), Immediate(shift_count)); 1651 __ shlp(ToRegister(left), Immediate(shift_count));
1653 } else { 1652 } else {
1654 DCHECK(SmiValuesAre31Bits()); 1653 DCHECK(SmiValuesAre31Bits());
1655 if (instr->can_deopt()) { 1654 if (instr->can_deopt()) {
1656 if (shift_count != 1) { 1655 if (shift_count != 1) {
1657 __ shll(ToRegister(left), Immediate(shift_count - 1)); 1656 __ shll(ToRegister(left), Immediate(shift_count - 1));
1658 } 1657 }
1659 __ Integer32ToSmi(ToRegister(left), ToRegister(left)); 1658 __ Integer32ToSmi(ToRegister(left), ToRegister(left));
1660 DeoptimizeIf(overflow, instr->environment()); 1659 DeoptimizeIf(overflow, instr);
1661 } else { 1660 } else {
1662 __ shll(ToRegister(left), Immediate(shift_count)); 1661 __ shll(ToRegister(left), Immediate(shift_count));
1663 } 1662 }
1664 } 1663 }
1665 } else { 1664 } else {
1666 __ shll(ToRegister(left), Immediate(shift_count)); 1665 __ shll(ToRegister(left), Immediate(shift_count));
1667 } 1666 }
1668 } 1667 }
1669 break; 1668 break;
1670 default: 1669 default:
(...skipping 22 matching lines...) Expand all
1693 } 1692 }
1694 } else { 1693 } else {
1695 if (instr->hydrogen_value()->representation().IsSmi()) { 1694 if (instr->hydrogen_value()->representation().IsSmi()) {
1696 __ subp(ToRegister(left), ToOperand(right)); 1695 __ subp(ToRegister(left), ToOperand(right));
1697 } else { 1696 } else {
1698 __ subl(ToRegister(left), ToOperand(right)); 1697 __ subl(ToRegister(left), ToOperand(right));
1699 } 1698 }
1700 } 1699 }
1701 1700
1702 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { 1701 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
1703 DeoptimizeIf(overflow, instr->environment()); 1702 DeoptimizeIf(overflow, instr);
1704 } 1703 }
1705 } 1704 }
1706 1705
1707 1706
1708 void LCodeGen::DoConstantI(LConstantI* instr) { 1707 void LCodeGen::DoConstantI(LConstantI* instr) {
1709 Register dst = ToRegister(instr->result()); 1708 Register dst = ToRegister(instr->result());
1710 if (instr->value() == 0) { 1709 if (instr->value() == 0) {
1711 __ xorl(dst, dst); 1710 __ xorl(dst, dst);
1712 } else { 1711 } else {
1713 __ movl(dst, Immediate(instr->value())); 1712 __ movl(dst, Immediate(instr->value()));
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
1758 1757
1759 void LCodeGen::DoDateField(LDateField* instr) { 1758 void LCodeGen::DoDateField(LDateField* instr) {
1760 Register object = ToRegister(instr->date()); 1759 Register object = ToRegister(instr->date());
1761 Register result = ToRegister(instr->result()); 1760 Register result = ToRegister(instr->result());
1762 Smi* index = instr->index(); 1761 Smi* index = instr->index();
1763 Label runtime, done, not_date_object; 1762 Label runtime, done, not_date_object;
1764 DCHECK(object.is(result)); 1763 DCHECK(object.is(result));
1765 DCHECK(object.is(rax)); 1764 DCHECK(object.is(rax));
1766 1765
1767 Condition cc = masm()->CheckSmi(object); 1766 Condition cc = masm()->CheckSmi(object);
1768 DeoptimizeIf(cc, instr->environment()); 1767 DeoptimizeIf(cc, instr);
1769 __ CmpObjectType(object, JS_DATE_TYPE, kScratchRegister); 1768 __ CmpObjectType(object, JS_DATE_TYPE, kScratchRegister);
1770 DeoptimizeIf(not_equal, instr->environment()); 1769 DeoptimizeIf(not_equal, instr);
1771 1770
1772 if (index->value() == 0) { 1771 if (index->value() == 0) {
1773 __ movp(result, FieldOperand(object, JSDate::kValueOffset)); 1772 __ movp(result, FieldOperand(object, JSDate::kValueOffset));
1774 } else { 1773 } else {
1775 if (index->value() < JSDate::kFirstUncachedField) { 1774 if (index->value() < JSDate::kFirstUncachedField) {
1776 ExternalReference stamp = ExternalReference::date_cache_stamp(isolate()); 1775 ExternalReference stamp = ExternalReference::date_cache_stamp(isolate());
1777 Operand stamp_operand = __ ExternalOperand(stamp); 1776 Operand stamp_operand = __ ExternalOperand(stamp);
1778 __ movp(kScratchRegister, stamp_operand); 1777 __ movp(kScratchRegister, stamp_operand);
1779 __ cmpp(kScratchRegister, FieldOperand(object, 1778 __ cmpp(kScratchRegister, FieldOperand(object,
1780 JSDate::kCacheStampOffset)); 1779 JSDate::kCacheStampOffset));
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
1924 __ addl(ToRegister(left), ToRegister(right)); 1923 __ addl(ToRegister(left), ToRegister(right));
1925 } 1924 }
1926 } else { 1925 } else {
1927 if (is_p) { 1926 if (is_p) {
1928 __ addp(ToRegister(left), ToOperand(right)); 1927 __ addp(ToRegister(left), ToOperand(right));
1929 } else { 1928 } else {
1930 __ addl(ToRegister(left), ToOperand(right)); 1929 __ addl(ToRegister(left), ToOperand(right));
1931 } 1930 }
1932 } 1931 }
1933 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { 1932 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
1934 DeoptimizeIf(overflow, instr->environment()); 1933 DeoptimizeIf(overflow, instr);
1935 } 1934 }
1936 } 1935 }
1937 } 1936 }
1938 1937
1939 1938
1940 void LCodeGen::DoMathMinMax(LMathMinMax* instr) { 1939 void LCodeGen::DoMathMinMax(LMathMinMax* instr) {
1941 LOperand* left = instr->left(); 1940 LOperand* left = instr->left();
1942 LOperand* right = instr->right(); 1941 LOperand* right = instr->right();
1943 DCHECK(left->Equals(instr->result())); 1942 DCHECK(left->Equals(instr->result()));
1944 HMathMinMax::Operation operation = instr->hydrogen()->operation(); 1943 HMathMinMax::Operation operation = instr->hydrogen()->operation();
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after
2169 } 2168 }
2170 2169
2171 if (expected.Contains(ToBooleanStub::SMI)) { 2170 if (expected.Contains(ToBooleanStub::SMI)) {
2172 // Smis: 0 -> false, all other -> true. 2171 // Smis: 0 -> false, all other -> true.
2173 __ Cmp(reg, Smi::FromInt(0)); 2172 __ Cmp(reg, Smi::FromInt(0));
2174 __ j(equal, instr->FalseLabel(chunk_)); 2173 __ j(equal, instr->FalseLabel(chunk_));
2175 __ JumpIfSmi(reg, instr->TrueLabel(chunk_)); 2174 __ JumpIfSmi(reg, instr->TrueLabel(chunk_));
2176 } else if (expected.NeedsMap()) { 2175 } else if (expected.NeedsMap()) {
2177 // If we need a map later and have a Smi -> deopt. 2176 // If we need a map later and have a Smi -> deopt.
2178 __ testb(reg, Immediate(kSmiTagMask)); 2177 __ testb(reg, Immediate(kSmiTagMask));
2179 DeoptimizeIf(zero, instr->environment()); 2178 DeoptimizeIf(zero, instr);
2180 } 2179 }
2181 2180
2182 const Register map = kScratchRegister; 2181 const Register map = kScratchRegister;
2183 if (expected.NeedsMap()) { 2182 if (expected.NeedsMap()) {
2184 __ movp(map, FieldOperand(reg, HeapObject::kMapOffset)); 2183 __ movp(map, FieldOperand(reg, HeapObject::kMapOffset));
2185 2184
2186 if (expected.CanBeUndetectable()) { 2185 if (expected.CanBeUndetectable()) {
2187 // Undetectable -> false. 2186 // Undetectable -> false.
2188 __ testb(FieldOperand(map, Map::kBitFieldOffset), 2187 __ testb(FieldOperand(map, Map::kBitFieldOffset),
2189 Immediate(1 << Map::kIsUndetectable)); 2188 Immediate(1 << Map::kIsUndetectable));
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
2223 __ xorps(xmm_scratch, xmm_scratch); 2222 __ xorps(xmm_scratch, xmm_scratch);
2224 __ ucomisd(xmm_scratch, FieldOperand(reg, HeapNumber::kValueOffset)); 2223 __ ucomisd(xmm_scratch, FieldOperand(reg, HeapNumber::kValueOffset));
2225 __ j(zero, instr->FalseLabel(chunk_)); 2224 __ j(zero, instr->FalseLabel(chunk_));
2226 __ jmp(instr->TrueLabel(chunk_)); 2225 __ jmp(instr->TrueLabel(chunk_));
2227 __ bind(&not_heap_number); 2226 __ bind(&not_heap_number);
2228 } 2227 }
2229 2228
2230 if (!expected.IsGeneric()) { 2229 if (!expected.IsGeneric()) {
2231 // We've seen something for the first time -> deopt. 2230 // We've seen something for the first time -> deopt.
2232 // This can only happen if we are not generic already. 2231 // This can only happen if we are not generic already.
2233 DeoptimizeIf(no_condition, instr->environment()); 2232 DeoptimizeIf(no_condition, instr);
2234 } 2233 }
2235 } 2234 }
2236 } 2235 }
2237 } 2236 }
2238 2237
2239 2238
2240 void LCodeGen::EmitGoto(int block) { 2239 void LCodeGen::EmitGoto(int block) {
2241 if (!IsNextEmittedBlock(block)) { 2240 if (!IsNextEmittedBlock(block)) {
2242 __ jmp(chunk_->GetAssemblyLabel(chunk_->LookupDestination(block))); 2241 __ jmp(chunk_->GetAssemblyLabel(chunk_->LookupDestination(block)));
2243 } 2242 }
(...skipping 595 matching lines...) Expand 10 before | Expand all | Expand 10 after
2839 info_->AddNoFrameRange(no_frame_start, masm_->pc_offset()); 2838 info_->AddNoFrameRange(no_frame_start, masm_->pc_offset());
2840 } 2839 }
2841 } 2840 }
2842 2841
2843 2842
2844 void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) { 2843 void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) {
2845 Register result = ToRegister(instr->result()); 2844 Register result = ToRegister(instr->result());
2846 __ LoadGlobalCell(result, instr->hydrogen()->cell().handle()); 2845 __ LoadGlobalCell(result, instr->hydrogen()->cell().handle());
2847 if (instr->hydrogen()->RequiresHoleCheck()) { 2846 if (instr->hydrogen()->RequiresHoleCheck()) {
2848 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); 2847 __ CompareRoot(result, Heap::kTheHoleValueRootIndex);
2849 DeoptimizeIf(equal, instr->environment()); 2848 DeoptimizeIf(equal, instr);
2850 } 2849 }
2851 } 2850 }
2852 2851
2853 2852
2854 template <class T> 2853 template <class T>
2855 void LCodeGen::EmitVectorLoadICRegisters(T* instr) { 2854 void LCodeGen::EmitVectorLoadICRegisters(T* instr) {
2856 DCHECK(FLAG_vector_ics); 2855 DCHECK(FLAG_vector_ics);
2857 Register vector = ToRegister(instr->temp_vector()); 2856 Register vector = ToRegister(instr->temp_vector());
2858 DCHECK(vector.is(VectorLoadICDescriptor::VectorRegister())); 2857 DCHECK(vector.is(VectorLoadICDescriptor::VectorRegister()));
2859 __ Move(vector, instr->hydrogen()->feedback_vector()); 2858 __ Move(vector, instr->hydrogen()->feedback_vector());
(...skipping 27 matching lines...) Expand all
2887 // If the cell we are storing to contains the hole it could have 2886 // If the cell we are storing to contains the hole it could have
2888 // been deleted from the property dictionary. In that case, we need 2887 // been deleted from the property dictionary. In that case, we need
2889 // to update the property details in the property dictionary to mark 2888 // to update the property details in the property dictionary to mark
2890 // it as no longer deleted. We deoptimize in that case. 2889 // it as no longer deleted. We deoptimize in that case.
2891 if (instr->hydrogen()->RequiresHoleCheck()) { 2890 if (instr->hydrogen()->RequiresHoleCheck()) {
2892 // We have a temp because CompareRoot might clobber kScratchRegister. 2891 // We have a temp because CompareRoot might clobber kScratchRegister.
2893 Register cell = ToRegister(instr->temp()); 2892 Register cell = ToRegister(instr->temp());
2894 DCHECK(!value.is(cell)); 2893 DCHECK(!value.is(cell));
2895 __ Move(cell, cell_handle, RelocInfo::CELL); 2894 __ Move(cell, cell_handle, RelocInfo::CELL);
2896 __ CompareRoot(Operand(cell, 0), Heap::kTheHoleValueRootIndex); 2895 __ CompareRoot(Operand(cell, 0), Heap::kTheHoleValueRootIndex);
2897 DeoptimizeIf(equal, instr->environment()); 2896 DeoptimizeIf(equal, instr);
2898 // Store the value. 2897 // Store the value.
2899 __ movp(Operand(cell, 0), value); 2898 __ movp(Operand(cell, 0), value);
2900 } else { 2899 } else {
2901 // Store the value. 2900 // Store the value.
2902 __ Move(kScratchRegister, cell_handle, RelocInfo::CELL); 2901 __ Move(kScratchRegister, cell_handle, RelocInfo::CELL);
2903 __ movp(Operand(kScratchRegister, 0), value); 2902 __ movp(Operand(kScratchRegister, 0), value);
2904 } 2903 }
2905 // Cells are always rescanned, so no write barrier here. 2904 // Cells are always rescanned, so no write barrier here.
2906 } 2905 }
2907 2906
2908 2907
2909 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { 2908 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
2910 Register context = ToRegister(instr->context()); 2909 Register context = ToRegister(instr->context());
2911 Register result = ToRegister(instr->result()); 2910 Register result = ToRegister(instr->result());
2912 __ movp(result, ContextOperand(context, instr->slot_index())); 2911 __ movp(result, ContextOperand(context, instr->slot_index()));
2913 if (instr->hydrogen()->RequiresHoleCheck()) { 2912 if (instr->hydrogen()->RequiresHoleCheck()) {
2914 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); 2913 __ CompareRoot(result, Heap::kTheHoleValueRootIndex);
2915 if (instr->hydrogen()->DeoptimizesOnHole()) { 2914 if (instr->hydrogen()->DeoptimizesOnHole()) {
2916 DeoptimizeIf(equal, instr->environment()); 2915 DeoptimizeIf(equal, instr);
2917 } else { 2916 } else {
2918 Label is_not_hole; 2917 Label is_not_hole;
2919 __ j(not_equal, &is_not_hole, Label::kNear); 2918 __ j(not_equal, &is_not_hole, Label::kNear);
2920 __ LoadRoot(result, Heap::kUndefinedValueRootIndex); 2919 __ LoadRoot(result, Heap::kUndefinedValueRootIndex);
2921 __ bind(&is_not_hole); 2920 __ bind(&is_not_hole);
2922 } 2921 }
2923 } 2922 }
2924 } 2923 }
2925 2924
2926 2925
2927 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { 2926 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) {
2928 Register context = ToRegister(instr->context()); 2927 Register context = ToRegister(instr->context());
2929 Register value = ToRegister(instr->value()); 2928 Register value = ToRegister(instr->value());
2930 2929
2931 Operand target = ContextOperand(context, instr->slot_index()); 2930 Operand target = ContextOperand(context, instr->slot_index());
2932 2931
2933 Label skip_assignment; 2932 Label skip_assignment;
2934 if (instr->hydrogen()->RequiresHoleCheck()) { 2933 if (instr->hydrogen()->RequiresHoleCheck()) {
2935 __ CompareRoot(target, Heap::kTheHoleValueRootIndex); 2934 __ CompareRoot(target, Heap::kTheHoleValueRootIndex);
2936 if (instr->hydrogen()->DeoptimizesOnHole()) { 2935 if (instr->hydrogen()->DeoptimizesOnHole()) {
2937 DeoptimizeIf(equal, instr->environment()); 2936 DeoptimizeIf(equal, instr);
2938 } else { 2937 } else {
2939 __ j(not_equal, &skip_assignment); 2938 __ j(not_equal, &skip_assignment);
2940 } 2939 }
2941 } 2940 }
2942 __ movp(target, value); 2941 __ movp(target, value);
2943 2942
2944 if (instr->hydrogen()->NeedsWriteBarrier()) { 2943 if (instr->hydrogen()->NeedsWriteBarrier()) {
2945 SmiCheck check_needed = 2944 SmiCheck check_needed =
2946 instr->hydrogen()->value()->type().IsHeapObject() 2945 instr->hydrogen()->value()->type().IsHeapObject()
2947 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; 2946 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
3025 void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { 3024 void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) {
3026 Register function = ToRegister(instr->function()); 3025 Register function = ToRegister(instr->function());
3027 Register result = ToRegister(instr->result()); 3026 Register result = ToRegister(instr->result());
3028 3027
3029 // Get the prototype or initial map from the function. 3028 // Get the prototype or initial map from the function.
3030 __ movp(result, 3029 __ movp(result,
3031 FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); 3030 FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
3032 3031
3033 // Check that the function has a prototype or an initial map. 3032 // Check that the function has a prototype or an initial map.
3034 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); 3033 __ CompareRoot(result, Heap::kTheHoleValueRootIndex);
3035 DeoptimizeIf(equal, instr->environment()); 3034 DeoptimizeIf(equal, instr);
3036 3035
3037 // If the function does not have an initial map, we're done. 3036 // If the function does not have an initial map, we're done.
3038 Label done; 3037 Label done;
3039 __ CmpObjectType(result, MAP_TYPE, kScratchRegister); 3038 __ CmpObjectType(result, MAP_TYPE, kScratchRegister);
3040 __ j(not_equal, &done, Label::kNear); 3039 __ j(not_equal, &done, Label::kNear);
3041 3040
3042 // Get the prototype from the initial map. 3041 // Get the prototype from the initial map.
3043 __ movp(result, FieldOperand(result, Map::kPrototypeOffset)); 3042 __ movp(result, FieldOperand(result, Map::kPrototypeOffset));
3044 3043
3045 // All done. 3044 // All done.
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
3137 break; 3136 break;
3138 case EXTERNAL_INT32_ELEMENTS: 3137 case EXTERNAL_INT32_ELEMENTS:
3139 case INT32_ELEMENTS: 3138 case INT32_ELEMENTS:
3140 __ movl(result, operand); 3139 __ movl(result, operand);
3141 break; 3140 break;
3142 case EXTERNAL_UINT32_ELEMENTS: 3141 case EXTERNAL_UINT32_ELEMENTS:
3143 case UINT32_ELEMENTS: 3142 case UINT32_ELEMENTS:
3144 __ movl(result, operand); 3143 __ movl(result, operand);
3145 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) { 3144 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) {
3146 __ testl(result, result); 3145 __ testl(result, result);
3147 DeoptimizeIf(negative, instr->environment()); 3146 DeoptimizeIf(negative, instr);
3148 } 3147 }
3149 break; 3148 break;
3150 case EXTERNAL_FLOAT32_ELEMENTS: 3149 case EXTERNAL_FLOAT32_ELEMENTS:
3151 case EXTERNAL_FLOAT64_ELEMENTS: 3150 case EXTERNAL_FLOAT64_ELEMENTS:
3152 case FLOAT32_ELEMENTS: 3151 case FLOAT32_ELEMENTS:
3153 case FLOAT64_ELEMENTS: 3152 case FLOAT64_ELEMENTS:
3154 case FAST_ELEMENTS: 3153 case FAST_ELEMENTS:
3155 case FAST_SMI_ELEMENTS: 3154 case FAST_SMI_ELEMENTS:
3156 case FAST_DOUBLE_ELEMENTS: 3155 case FAST_DOUBLE_ELEMENTS:
3157 case FAST_HOLEY_ELEMENTS: 3156 case FAST_HOLEY_ELEMENTS:
(...skipping 18 matching lines...) Expand all
3176 __ movsxlq(ToRegister(key), ToRegister(key)); 3175 __ movsxlq(ToRegister(key), ToRegister(key));
3177 } 3176 }
3178 if (instr->hydrogen()->RequiresHoleCheck()) { 3177 if (instr->hydrogen()->RequiresHoleCheck()) {
3179 Operand hole_check_operand = BuildFastArrayOperand( 3178 Operand hole_check_operand = BuildFastArrayOperand(
3180 instr->elements(), 3179 instr->elements(),
3181 key, 3180 key,
3182 instr->hydrogen()->key()->representation(), 3181 instr->hydrogen()->key()->representation(),
3183 FAST_DOUBLE_ELEMENTS, 3182 FAST_DOUBLE_ELEMENTS,
3184 instr->base_offset() + sizeof(kHoleNanLower32)); 3183 instr->base_offset() + sizeof(kHoleNanLower32));
3185 __ cmpl(hole_check_operand, Immediate(kHoleNanUpper32)); 3184 __ cmpl(hole_check_operand, Immediate(kHoleNanUpper32));
3186 DeoptimizeIf(equal, instr->environment()); 3185 DeoptimizeIf(equal, instr);
3187 } 3186 }
3188 3187
3189 Operand double_load_operand = BuildFastArrayOperand( 3188 Operand double_load_operand = BuildFastArrayOperand(
3190 instr->elements(), 3189 instr->elements(),
3191 key, 3190 key,
3192 instr->hydrogen()->key()->representation(), 3191 instr->hydrogen()->key()->representation(),
3193 FAST_DOUBLE_ELEMENTS, 3192 FAST_DOUBLE_ELEMENTS,
3194 instr->base_offset()); 3193 instr->base_offset());
3195 __ movsd(result, double_load_operand); 3194 __ movsd(result, double_load_operand);
3196 } 3195 }
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
3233 __ Load(result, 3232 __ Load(result,
3234 BuildFastArrayOperand(instr->elements(), key, 3233 BuildFastArrayOperand(instr->elements(), key,
3235 instr->hydrogen()->key()->representation(), 3234 instr->hydrogen()->key()->representation(),
3236 FAST_ELEMENTS, offset), 3235 FAST_ELEMENTS, offset),
3237 representation); 3236 representation);
3238 3237
3239 // Check for the hole value. 3238 // Check for the hole value.
3240 if (requires_hole_check) { 3239 if (requires_hole_check) {
3241 if (IsFastSmiElementsKind(hinstr->elements_kind())) { 3240 if (IsFastSmiElementsKind(hinstr->elements_kind())) {
3242 Condition smi = __ CheckSmi(result); 3241 Condition smi = __ CheckSmi(result);
3243 DeoptimizeIf(NegateCondition(smi), instr->environment()); 3242 DeoptimizeIf(NegateCondition(smi), instr);
3244 } else { 3243 } else {
3245 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); 3244 __ CompareRoot(result, Heap::kTheHoleValueRootIndex);
3246 DeoptimizeIf(equal, instr->environment()); 3245 DeoptimizeIf(equal, instr);
3247 } 3246 }
3248 } 3247 }
3249 } 3248 }
3250 3249
3251 3250
3252 void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) { 3251 void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) {
3253 if (instr->is_typed_elements()) { 3252 if (instr->is_typed_elements()) {
3254 DoLoadKeyedExternalArray(instr); 3253 DoLoadKeyedExternalArray(instr);
3255 } else if (instr->hydrogen()->representation().IsDouble()) { 3254 } else if (instr->hydrogen()->representation().IsDouble()) {
3256 DoLoadKeyedFixedDoubleArray(instr); 3255 DoLoadKeyedFixedDoubleArray(instr);
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
3385 } 3384 }
3386 3385
3387 // Normal function. Replace undefined or null with global receiver. 3386 // Normal function. Replace undefined or null with global receiver.
3388 __ CompareRoot(receiver, Heap::kNullValueRootIndex); 3387 __ CompareRoot(receiver, Heap::kNullValueRootIndex);
3389 __ j(equal, &global_object, Label::kNear); 3388 __ j(equal, &global_object, Label::kNear);
3390 __ CompareRoot(receiver, Heap::kUndefinedValueRootIndex); 3389 __ CompareRoot(receiver, Heap::kUndefinedValueRootIndex);
3391 __ j(equal, &global_object, Label::kNear); 3390 __ j(equal, &global_object, Label::kNear);
3392 3391
3393 // The receiver should be a JS object. 3392 // The receiver should be a JS object.
3394 Condition is_smi = __ CheckSmi(receiver); 3393 Condition is_smi = __ CheckSmi(receiver);
3395 DeoptimizeIf(is_smi, instr->environment()); 3394 DeoptimizeIf(is_smi, instr);
3396 __ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, kScratchRegister); 3395 __ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, kScratchRegister);
3397 DeoptimizeIf(below, instr->environment()); 3396 DeoptimizeIf(below, instr);
3398 3397
3399 __ jmp(&receiver_ok, Label::kNear); 3398 __ jmp(&receiver_ok, Label::kNear);
3400 __ bind(&global_object); 3399 __ bind(&global_object);
3401 __ movp(receiver, FieldOperand(function, JSFunction::kContextOffset)); 3400 __ movp(receiver, FieldOperand(function, JSFunction::kContextOffset));
3402 __ movp(receiver, 3401 __ movp(receiver,
3403 Operand(receiver, 3402 Operand(receiver,
3404 Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); 3403 Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
3405 __ movp(receiver, FieldOperand(receiver, GlobalObject::kGlobalProxyOffset)); 3404 __ movp(receiver, FieldOperand(receiver, GlobalObject::kGlobalProxyOffset));
3406 3405
3407 __ bind(&receiver_ok); 3406 __ bind(&receiver_ok);
3408 } 3407 }
3409 3408
3410 3409
3411 void LCodeGen::DoApplyArguments(LApplyArguments* instr) { 3410 void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
3412 Register receiver = ToRegister(instr->receiver()); 3411 Register receiver = ToRegister(instr->receiver());
3413 Register function = ToRegister(instr->function()); 3412 Register function = ToRegister(instr->function());
3414 Register length = ToRegister(instr->length()); 3413 Register length = ToRegister(instr->length());
3415 Register elements = ToRegister(instr->elements()); 3414 Register elements = ToRegister(instr->elements());
3416 DCHECK(receiver.is(rax)); // Used for parameter count. 3415 DCHECK(receiver.is(rax)); // Used for parameter count.
3417 DCHECK(function.is(rdi)); // Required by InvokeFunction. 3416 DCHECK(function.is(rdi)); // Required by InvokeFunction.
3418 DCHECK(ToRegister(instr->result()).is(rax)); 3417 DCHECK(ToRegister(instr->result()).is(rax));
3419 3418
3420 // Copy the arguments to this function possibly from the 3419 // Copy the arguments to this function possibly from the
3421 // adaptor frame below it. 3420 // adaptor frame below it.
3422 const uint32_t kArgumentsLimit = 1 * KB; 3421 const uint32_t kArgumentsLimit = 1 * KB;
3423 __ cmpp(length, Immediate(kArgumentsLimit)); 3422 __ cmpp(length, Immediate(kArgumentsLimit));
3424 DeoptimizeIf(above, instr->environment()); 3423 DeoptimizeIf(above, instr);
3425 3424
3426 __ Push(receiver); 3425 __ Push(receiver);
3427 __ movp(receiver, length); 3426 __ movp(receiver, length);
3428 3427
3429 // Loop through the arguments pushing them onto the execution 3428 // Loop through the arguments pushing them onto the execution
3430 // stack. 3429 // stack.
3431 Label invoke, loop; 3430 Label invoke, loop;
3432 // length is a small non-negative integer, due to the test above. 3431 // length is a small non-negative integer, due to the test above.
3433 __ testl(length, length); 3432 __ testl(length, length);
3434 __ j(zero, &invoke, Label::kNear); 3433 __ j(zero, &invoke, Label::kNear);
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
3609 __ Call(target); 3608 __ Call(target);
3610 } 3609 }
3611 generator.AfterCall(); 3610 generator.AfterCall();
3612 } 3611 }
3613 3612
3614 3613
3615 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { 3614 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) {
3616 Register input_reg = ToRegister(instr->value()); 3615 Register input_reg = ToRegister(instr->value());
3617 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), 3616 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset),
3618 Heap::kHeapNumberMapRootIndex); 3617 Heap::kHeapNumberMapRootIndex);
3619 DeoptimizeIf(not_equal, instr->environment()); 3618 DeoptimizeIf(not_equal, instr);
3620 3619
3621 Label slow, allocated, done; 3620 Label slow, allocated, done;
3622 Register tmp = input_reg.is(rax) ? rcx : rax; 3621 Register tmp = input_reg.is(rax) ? rcx : rax;
3623 Register tmp2 = tmp.is(rcx) ? rdx : input_reg.is(rcx) ? rdx : rcx; 3622 Register tmp2 = tmp.is(rcx) ? rdx : input_reg.is(rcx) ? rdx : rcx;
3624 3623
3625 // Preserve the value of all registers. 3624 // Preserve the value of all registers.
3626 PushSafepointRegistersScope scope(this); 3625 PushSafepointRegistersScope scope(this);
3627 3626
3628 __ movl(tmp, FieldOperand(input_reg, HeapNumber::kExponentOffset)); 3627 __ movl(tmp, FieldOperand(input_reg, HeapNumber::kExponentOffset));
3629 // Check the sign of the argument. If the argument is positive, just 3628 // Check the sign of the argument. If the argument is positive, just
(...skipping 25 matching lines...) Expand all
3655 __ bind(&done); 3654 __ bind(&done);
3656 } 3655 }
3657 3656
3658 3657
3659 void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) { 3658 void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) {
3660 Register input_reg = ToRegister(instr->value()); 3659 Register input_reg = ToRegister(instr->value());
3661 __ testl(input_reg, input_reg); 3660 __ testl(input_reg, input_reg);
3662 Label is_positive; 3661 Label is_positive;
3663 __ j(not_sign, &is_positive, Label::kNear); 3662 __ j(not_sign, &is_positive, Label::kNear);
3664 __ negl(input_reg); // Sets flags. 3663 __ negl(input_reg); // Sets flags.
3665 DeoptimizeIf(negative, instr->environment()); 3664 DeoptimizeIf(negative, instr);
3666 __ bind(&is_positive); 3665 __ bind(&is_positive);
3667 } 3666 }
3668 3667
3669 3668
3670 void LCodeGen::EmitSmiMathAbs(LMathAbs* instr) { 3669 void LCodeGen::EmitSmiMathAbs(LMathAbs* instr) {
3671 Register input_reg = ToRegister(instr->value()); 3670 Register input_reg = ToRegister(instr->value());
3672 __ testp(input_reg, input_reg); 3671 __ testp(input_reg, input_reg);
3673 Label is_positive; 3672 Label is_positive;
3674 __ j(not_sign, &is_positive, Label::kNear); 3673 __ j(not_sign, &is_positive, Label::kNear);
3675 __ negp(input_reg); // Sets flags. 3674 __ negp(input_reg); // Sets flags.
3676 DeoptimizeIf(negative, instr->environment()); 3675 DeoptimizeIf(negative, instr);
3677 __ bind(&is_positive); 3676 __ bind(&is_positive);
3678 } 3677 }
3679 3678
3680 3679
3681 void LCodeGen::DoMathAbs(LMathAbs* instr) { 3680 void LCodeGen::DoMathAbs(LMathAbs* instr) {
3682 // Class for deferred case. 3681 // Class for deferred case.
3683 class DeferredMathAbsTaggedHeapNumber FINAL : public LDeferredCode { 3682 class DeferredMathAbsTaggedHeapNumber FINAL : public LDeferredCode {
3684 public: 3683 public:
3685 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, LMathAbs* instr) 3684 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, LMathAbs* instr)
3686 : LDeferredCode(codegen), instr_(instr) { } 3685 : LDeferredCode(codegen), instr_(instr) { }
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
3721 XMMRegister xmm_scratch = double_scratch0(); 3720 XMMRegister xmm_scratch = double_scratch0();
3722 Register output_reg = ToRegister(instr->result()); 3721 Register output_reg = ToRegister(instr->result());
3723 XMMRegister input_reg = ToDoubleRegister(instr->value()); 3722 XMMRegister input_reg = ToDoubleRegister(instr->value());
3724 3723
3725 if (CpuFeatures::IsSupported(SSE4_1)) { 3724 if (CpuFeatures::IsSupported(SSE4_1)) {
3726 CpuFeatureScope scope(masm(), SSE4_1); 3725 CpuFeatureScope scope(masm(), SSE4_1);
3727 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 3726 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
3728 // Deoptimize if minus zero. 3727 // Deoptimize if minus zero.
3729 __ movq(output_reg, input_reg); 3728 __ movq(output_reg, input_reg);
3730 __ subq(output_reg, Immediate(1)); 3729 __ subq(output_reg, Immediate(1));
3731 DeoptimizeIf(overflow, instr->environment()); 3730 DeoptimizeIf(overflow, instr);
3732 } 3731 }
3733 __ roundsd(xmm_scratch, input_reg, Assembler::kRoundDown); 3732 __ roundsd(xmm_scratch, input_reg, Assembler::kRoundDown);
3734 __ cvttsd2si(output_reg, xmm_scratch); 3733 __ cvttsd2si(output_reg, xmm_scratch);
3735 __ cmpl(output_reg, Immediate(0x1)); 3734 __ cmpl(output_reg, Immediate(0x1));
3736 DeoptimizeIf(overflow, instr->environment()); 3735 DeoptimizeIf(overflow, instr);
3737 } else { 3736 } else {
3738 Label negative_sign, done; 3737 Label negative_sign, done;
3739 // Deoptimize on unordered. 3738 // Deoptimize on unordered.
3740 __ xorps(xmm_scratch, xmm_scratch); // Zero the register. 3739 __ xorps(xmm_scratch, xmm_scratch); // Zero the register.
3741 __ ucomisd(input_reg, xmm_scratch); 3740 __ ucomisd(input_reg, xmm_scratch);
3742 DeoptimizeIf(parity_even, instr->environment()); 3741 DeoptimizeIf(parity_even, instr);
3743 __ j(below, &negative_sign, Label::kNear); 3742 __ j(below, &negative_sign, Label::kNear);
3744 3743
3745 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 3744 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
3746 // Check for negative zero. 3745 // Check for negative zero.
3747 Label positive_sign; 3746 Label positive_sign;
3748 __ j(above, &positive_sign, Label::kNear); 3747 __ j(above, &positive_sign, Label::kNear);
3749 __ movmskpd(output_reg, input_reg); 3748 __ movmskpd(output_reg, input_reg);
3750 __ testq(output_reg, Immediate(1)); 3749 __ testq(output_reg, Immediate(1));
3751 DeoptimizeIf(not_zero, instr->environment()); 3750 DeoptimizeIf(not_zero, instr);
3752 __ Set(output_reg, 0); 3751 __ Set(output_reg, 0);
3753 __ jmp(&done); 3752 __ jmp(&done);
3754 __ bind(&positive_sign); 3753 __ bind(&positive_sign);
3755 } 3754 }
3756 3755
3757 // Use truncating instruction (OK because input is positive). 3756 // Use truncating instruction (OK because input is positive).
3758 __ cvttsd2si(output_reg, input_reg); 3757 __ cvttsd2si(output_reg, input_reg);
3759 // Overflow is signalled with minint. 3758 // Overflow is signalled with minint.
3760 __ cmpl(output_reg, Immediate(0x1)); 3759 __ cmpl(output_reg, Immediate(0x1));
3761 DeoptimizeIf(overflow, instr->environment()); 3760 DeoptimizeIf(overflow, instr);
3762 __ jmp(&done, Label::kNear); 3761 __ jmp(&done, Label::kNear);
3763 3762
3764 // Non-zero negative reaches here. 3763 // Non-zero negative reaches here.
3765 __ bind(&negative_sign); 3764 __ bind(&negative_sign);
3766 // Truncate, then compare and compensate. 3765 // Truncate, then compare and compensate.
3767 __ cvttsd2si(output_reg, input_reg); 3766 __ cvttsd2si(output_reg, input_reg);
3768 __ Cvtlsi2sd(xmm_scratch, output_reg); 3767 __ Cvtlsi2sd(xmm_scratch, output_reg);
3769 __ ucomisd(input_reg, xmm_scratch); 3768 __ ucomisd(input_reg, xmm_scratch);
3770 __ j(equal, &done, Label::kNear); 3769 __ j(equal, &done, Label::kNear);
3771 __ subl(output_reg, Immediate(1)); 3770 __ subl(output_reg, Immediate(1));
3772 DeoptimizeIf(overflow, instr->environment()); 3771 DeoptimizeIf(overflow, instr);
3773 3772
3774 __ bind(&done); 3773 __ bind(&done);
3775 } 3774 }
3776 } 3775 }
3777 3776
3778 3777
3779 void LCodeGen::DoMathRound(LMathRound* instr) { 3778 void LCodeGen::DoMathRound(LMathRound* instr) {
3780 const XMMRegister xmm_scratch = double_scratch0(); 3779 const XMMRegister xmm_scratch = double_scratch0();
3781 Register output_reg = ToRegister(instr->result()); 3780 Register output_reg = ToRegister(instr->result());
3782 XMMRegister input_reg = ToDoubleRegister(instr->value()); 3781 XMMRegister input_reg = ToDoubleRegister(instr->value());
3783 XMMRegister input_temp = ToDoubleRegister(instr->temp()); 3782 XMMRegister input_temp = ToDoubleRegister(instr->temp());
3784 static int64_t one_half = V8_INT64_C(0x3FE0000000000000); // 0.5 3783 static int64_t one_half = V8_INT64_C(0x3FE0000000000000); // 0.5
3785 static int64_t minus_one_half = V8_INT64_C(0xBFE0000000000000); // -0.5 3784 static int64_t minus_one_half = V8_INT64_C(0xBFE0000000000000); // -0.5
3786 3785
3787 Label done, round_to_zero, below_one_half; 3786 Label done, round_to_zero, below_one_half;
3788 Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear; 3787 Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear;
3789 __ movq(kScratchRegister, one_half); 3788 __ movq(kScratchRegister, one_half);
3790 __ movq(xmm_scratch, kScratchRegister); 3789 __ movq(xmm_scratch, kScratchRegister);
3791 __ ucomisd(xmm_scratch, input_reg); 3790 __ ucomisd(xmm_scratch, input_reg);
3792 __ j(above, &below_one_half, Label::kNear); 3791 __ j(above, &below_one_half, Label::kNear);
3793 3792
3794 // CVTTSD2SI rounds towards zero, since 0.5 <= x, we use floor(0.5 + x). 3793 // CVTTSD2SI rounds towards zero, since 0.5 <= x, we use floor(0.5 + x).
3795 __ addsd(xmm_scratch, input_reg); 3794 __ addsd(xmm_scratch, input_reg);
3796 __ cvttsd2si(output_reg, xmm_scratch); 3795 __ cvttsd2si(output_reg, xmm_scratch);
3797 // Overflow is signalled with minint. 3796 // Overflow is signalled with minint.
3798 __ cmpl(output_reg, Immediate(0x1)); 3797 __ cmpl(output_reg, Immediate(0x1));
3799 __ RecordComment("D2I conversion overflow"); 3798 __ RecordComment("D2I conversion overflow");
3800 DeoptimizeIf(overflow, instr->environment()); 3799 DeoptimizeIf(overflow, instr);
3801 __ jmp(&done, dist); 3800 __ jmp(&done, dist);
3802 3801
3803 __ bind(&below_one_half); 3802 __ bind(&below_one_half);
3804 __ movq(kScratchRegister, minus_one_half); 3803 __ movq(kScratchRegister, minus_one_half);
3805 __ movq(xmm_scratch, kScratchRegister); 3804 __ movq(xmm_scratch, kScratchRegister);
3806 __ ucomisd(xmm_scratch, input_reg); 3805 __ ucomisd(xmm_scratch, input_reg);
3807 __ j(below_equal, &round_to_zero, Label::kNear); 3806 __ j(below_equal, &round_to_zero, Label::kNear);
3808 3807
3809 // CVTTSD2SI rounds towards zero, we use ceil(x - (-0.5)) and then 3808 // CVTTSD2SI rounds towards zero, we use ceil(x - (-0.5)) and then
3810 // compare and compensate. 3809 // compare and compensate.
3811 __ movq(input_temp, input_reg); // Do not alter input_reg. 3810 __ movq(input_temp, input_reg); // Do not alter input_reg.
3812 __ subsd(input_temp, xmm_scratch); 3811 __ subsd(input_temp, xmm_scratch);
3813 __ cvttsd2si(output_reg, input_temp); 3812 __ cvttsd2si(output_reg, input_temp);
3814 // Catch minint due to overflow, and to prevent overflow when compensating. 3813 // Catch minint due to overflow, and to prevent overflow when compensating.
3815 __ cmpl(output_reg, Immediate(0x1)); 3814 __ cmpl(output_reg, Immediate(0x1));
3816 __ RecordComment("D2I conversion overflow"); 3815 __ RecordComment("D2I conversion overflow");
3817 DeoptimizeIf(overflow, instr->environment()); 3816 DeoptimizeIf(overflow, instr);
3818 3817
3819 __ Cvtlsi2sd(xmm_scratch, output_reg); 3818 __ Cvtlsi2sd(xmm_scratch, output_reg);
3820 __ ucomisd(xmm_scratch, input_temp); 3819 __ ucomisd(xmm_scratch, input_temp);
3821 __ j(equal, &done, dist); 3820 __ j(equal, &done, dist);
3822 __ subl(output_reg, Immediate(1)); 3821 __ subl(output_reg, Immediate(1));
3823 // No overflow because we already ruled out minint. 3822 // No overflow because we already ruled out minint.
3824 __ jmp(&done, dist); 3823 __ jmp(&done, dist);
3825 3824
3826 __ bind(&round_to_zero); 3825 __ bind(&round_to_zero);
3827 // We return 0 for the input range [+0, 0.5[, or [-0.5, 0.5[ if 3826 // We return 0 for the input range [+0, 0.5[, or [-0.5, 0.5[ if
3828 // we can ignore the difference between a result of -0 and +0. 3827 // we can ignore the difference between a result of -0 and +0.
3829 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 3828 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
3830 __ movq(output_reg, input_reg); 3829 __ movq(output_reg, input_reg);
3831 __ testq(output_reg, output_reg); 3830 __ testq(output_reg, output_reg);
3832 __ RecordComment("Minus zero"); 3831 __ RecordComment("Minus zero");
3833 DeoptimizeIf(negative, instr->environment()); 3832 DeoptimizeIf(negative, instr);
3834 } 3833 }
3835 __ Set(output_reg, 0); 3834 __ Set(output_reg, 0);
3836 __ bind(&done); 3835 __ bind(&done);
3837 } 3836 }
3838 3837
3839 3838
3840 void LCodeGen::DoMathFround(LMathFround* instr) { 3839 void LCodeGen::DoMathFround(LMathFround* instr) {
3841 XMMRegister input_reg = ToDoubleRegister(instr->value()); 3840 XMMRegister input_reg = ToDoubleRegister(instr->value());
3842 XMMRegister output_reg = ToDoubleRegister(instr->result()); 3841 XMMRegister output_reg = ToDoubleRegister(instr->result());
3843 __ cvtsd2ss(output_reg, input_reg); 3842 __ cvtsd2ss(output_reg, input_reg);
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
3902 DCHECK(ToDoubleRegister(instr->left()).is(xmm2)); 3901 DCHECK(ToDoubleRegister(instr->left()).is(xmm2));
3903 DCHECK(ToDoubleRegister(instr->result()).is(xmm3)); 3902 DCHECK(ToDoubleRegister(instr->result()).is(xmm3));
3904 3903
3905 if (exponent_type.IsSmi()) { 3904 if (exponent_type.IsSmi()) {
3906 MathPowStub stub(isolate(), MathPowStub::TAGGED); 3905 MathPowStub stub(isolate(), MathPowStub::TAGGED);
3907 __ CallStub(&stub); 3906 __ CallStub(&stub);
3908 } else if (exponent_type.IsTagged()) { 3907 } else if (exponent_type.IsTagged()) {
3909 Label no_deopt; 3908 Label no_deopt;
3910 __ JumpIfSmi(tagged_exponent, &no_deopt, Label::kNear); 3909 __ JumpIfSmi(tagged_exponent, &no_deopt, Label::kNear);
3911 __ CmpObjectType(tagged_exponent, HEAP_NUMBER_TYPE, rcx); 3910 __ CmpObjectType(tagged_exponent, HEAP_NUMBER_TYPE, rcx);
3912 DeoptimizeIf(not_equal, instr->environment()); 3911 DeoptimizeIf(not_equal, instr);
3913 __ bind(&no_deopt); 3912 __ bind(&no_deopt);
3914 MathPowStub stub(isolate(), MathPowStub::TAGGED); 3913 MathPowStub stub(isolate(), MathPowStub::TAGGED);
3915 __ CallStub(&stub); 3914 __ CallStub(&stub);
3916 } else if (exponent_type.IsInteger32()) { 3915 } else if (exponent_type.IsInteger32()) {
3917 MathPowStub stub(isolate(), MathPowStub::INTEGER); 3916 MathPowStub stub(isolate(), MathPowStub::INTEGER);
3918 __ CallStub(&stub); 3917 __ CallStub(&stub);
3919 } else { 3918 } else {
3920 DCHECK(exponent_type.IsDouble()); 3919 DCHECK(exponent_type.IsDouble());
3921 MathPowStub stub(isolate(), MathPowStub::DOUBLE); 3920 MathPowStub stub(isolate(), MathPowStub::DOUBLE);
3922 __ CallStub(&stub); 3921 __ CallStub(&stub);
(...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after
4274 __ cmpl(length, index); 4273 __ cmpl(length, index);
4275 } 4274 }
4276 } 4275 }
4277 } 4276 }
4278 if (FLAG_debug_code && instr->hydrogen()->skip_check()) { 4277 if (FLAG_debug_code && instr->hydrogen()->skip_check()) {
4279 Label done; 4278 Label done;
4280 __ j(NegateCondition(cc), &done, Label::kNear); 4279 __ j(NegateCondition(cc), &done, Label::kNear);
4281 __ int3(); 4280 __ int3();
4282 __ bind(&done); 4281 __ bind(&done);
4283 } else { 4282 } else {
4284 DeoptimizeIf(cc, instr->environment()); 4283 DeoptimizeIf(cc, instr);
4285 } 4284 }
4286 } 4285 }
4287 4286
4288 4287
4289 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) { 4288 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
4290 ElementsKind elements_kind = instr->elements_kind(); 4289 ElementsKind elements_kind = instr->elements_kind();
4291 LOperand* key = instr->key(); 4290 LOperand* key = instr->key();
4292 if (kPointerSize == kInt32Size && !key->IsConstantOperand()) { 4291 if (kPointerSize == kInt32Size && !key->IsConstantOperand()) {
4293 Register key_reg = ToRegister(key); 4292 Register key_reg = ToRegister(key);
4294 Representation key_representation = 4293 Representation key_representation =
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after
4522 } 4521 }
4523 __ bind(&not_applicable); 4522 __ bind(&not_applicable);
4524 } 4523 }
4525 4524
4526 4525
4527 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) { 4526 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) {
4528 Register object = ToRegister(instr->object()); 4527 Register object = ToRegister(instr->object());
4529 Register temp = ToRegister(instr->temp()); 4528 Register temp = ToRegister(instr->temp());
4530 Label no_memento_found; 4529 Label no_memento_found;
4531 __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found); 4530 __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found);
4532 DeoptimizeIf(equal, instr->environment()); 4531 DeoptimizeIf(equal, instr);
4533 __ bind(&no_memento_found); 4532 __ bind(&no_memento_found);
4534 } 4533 }
4535 4534
4536 4535
4537 void LCodeGen::DoStringAdd(LStringAdd* instr) { 4536 void LCodeGen::DoStringAdd(LStringAdd* instr) {
4538 DCHECK(ToRegister(instr->context()).is(rsi)); 4537 DCHECK(ToRegister(instr->context()).is(rsi));
4539 DCHECK(ToRegister(instr->left()).is(rdx)); 4538 DCHECK(ToRegister(instr->left()).is(rdx));
4540 DCHECK(ToRegister(instr->right()).is(rax)); 4539 DCHECK(ToRegister(instr->right()).is(rax));
4541 StringAddStub stub(isolate(), 4540 StringAddStub stub(isolate(),
4542 instr->hydrogen()->flags(), 4541 instr->hydrogen()->flags(),
(...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after
4841 } 4840 }
4842 4841
4843 4842
4844 void LCodeGen::DoSmiTag(LSmiTag* instr) { 4843 void LCodeGen::DoSmiTag(LSmiTag* instr) {
4845 HChange* hchange = instr->hydrogen(); 4844 HChange* hchange = instr->hydrogen();
4846 Register input = ToRegister(instr->value()); 4845 Register input = ToRegister(instr->value());
4847 Register output = ToRegister(instr->result()); 4846 Register output = ToRegister(instr->result());
4848 if (hchange->CheckFlag(HValue::kCanOverflow) && 4847 if (hchange->CheckFlag(HValue::kCanOverflow) &&
4849 hchange->value()->CheckFlag(HValue::kUint32)) { 4848 hchange->value()->CheckFlag(HValue::kUint32)) {
4850 Condition is_smi = __ CheckUInteger32ValidSmiValue(input); 4849 Condition is_smi = __ CheckUInteger32ValidSmiValue(input);
4851 DeoptimizeIf(NegateCondition(is_smi), instr->environment()); 4850 DeoptimizeIf(NegateCondition(is_smi), instr);
4852 } 4851 }
4853 __ Integer32ToSmi(output, input); 4852 __ Integer32ToSmi(output, input);
4854 if (hchange->CheckFlag(HValue::kCanOverflow) && 4853 if (hchange->CheckFlag(HValue::kCanOverflow) &&
4855 !hchange->value()->CheckFlag(HValue::kUint32)) { 4854 !hchange->value()->CheckFlag(HValue::kUint32)) {
4856 DeoptimizeIf(overflow, instr->environment()); 4855 DeoptimizeIf(overflow, instr);
4857 } 4856 }
4858 } 4857 }
4859 4858
4860 4859
4861 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { 4860 void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
4862 DCHECK(instr->value()->Equals(instr->result())); 4861 DCHECK(instr->value()->Equals(instr->result()));
4863 Register input = ToRegister(instr->value()); 4862 Register input = ToRegister(instr->value());
4864 if (instr->needs_check()) { 4863 if (instr->needs_check()) {
4865 Condition is_smi = __ CheckSmi(input); 4864 Condition is_smi = __ CheckSmi(input);
4866 DeoptimizeIf(NegateCondition(is_smi), instr->environment()); 4865 DeoptimizeIf(NegateCondition(is_smi), instr);
4867 } else { 4866 } else {
4868 __ AssertSmi(input); 4867 __ AssertSmi(input);
4869 } 4868 }
4870 __ SmiToInteger32(input, input); 4869 __ SmiToInteger32(input, input);
4871 } 4870 }
4872 4871
4873 4872
4874 void LCodeGen::EmitNumberUntagD(Register input_reg, 4873 void LCodeGen::EmitNumberUntagD(LNumberUntagD* instr, Register input_reg,
4875 XMMRegister result_reg, 4874 XMMRegister result_reg, NumberUntagDMode mode) {
4876 bool can_convert_undefined_to_nan, 4875 bool can_convert_undefined_to_nan =
4877 bool deoptimize_on_minus_zero, 4876 instr->hydrogen()->can_convert_undefined_to_nan();
4878 LEnvironment* env, 4877 bool deoptimize_on_minus_zero = instr->hydrogen()->deoptimize_on_minus_zero();
4879 NumberUntagDMode mode) { 4878
4880 Label convert, load_smi, done; 4879 Label convert, load_smi, done;
4881 4880
4882 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) { 4881 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) {
4883 // Smi check. 4882 // Smi check.
4884 __ JumpIfSmi(input_reg, &load_smi, Label::kNear); 4883 __ JumpIfSmi(input_reg, &load_smi, Label::kNear);
4885 4884
4886 // Heap number map check. 4885 // Heap number map check.
4887 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), 4886 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset),
4888 Heap::kHeapNumberMapRootIndex); 4887 Heap::kHeapNumberMapRootIndex);
4889 4888
4890 // On x64 it is safe to load at heap number offset before evaluating the map 4889 // On x64 it is safe to load at heap number offset before evaluating the map
4891 // check, since all heap objects are at least two words long. 4890 // check, since all heap objects are at least two words long.
4892 __ movsd(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset)); 4891 __ movsd(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset));
4893 4892
4894 if (can_convert_undefined_to_nan) { 4893 if (can_convert_undefined_to_nan) {
4895 __ j(not_equal, &convert, Label::kNear); 4894 __ j(not_equal, &convert, Label::kNear);
4896 } else { 4895 } else {
4897 DeoptimizeIf(not_equal, env); 4896 DeoptimizeIf(not_equal, instr);
4898 } 4897 }
4899 4898
4900 if (deoptimize_on_minus_zero) { 4899 if (deoptimize_on_minus_zero) {
4901 XMMRegister xmm_scratch = double_scratch0(); 4900 XMMRegister xmm_scratch = double_scratch0();
4902 __ xorps(xmm_scratch, xmm_scratch); 4901 __ xorps(xmm_scratch, xmm_scratch);
4903 __ ucomisd(xmm_scratch, result_reg); 4902 __ ucomisd(xmm_scratch, result_reg);
4904 __ j(not_equal, &done, Label::kNear); 4903 __ j(not_equal, &done, Label::kNear);
4905 __ movmskpd(kScratchRegister, result_reg); 4904 __ movmskpd(kScratchRegister, result_reg);
4906 __ testq(kScratchRegister, Immediate(1)); 4905 __ testq(kScratchRegister, Immediate(1));
4907 DeoptimizeIf(not_zero, env); 4906 DeoptimizeIf(not_zero, instr);
4908 } 4907 }
4909 __ jmp(&done, Label::kNear); 4908 __ jmp(&done, Label::kNear);
4910 4909
4911 if (can_convert_undefined_to_nan) { 4910 if (can_convert_undefined_to_nan) {
4912 __ bind(&convert); 4911 __ bind(&convert);
4913 4912
4914 // Convert undefined (and hole) to NaN. Compute NaN as 0/0. 4913 // Convert undefined (and hole) to NaN. Compute NaN as 0/0.
4915 __ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex); 4914 __ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex);
4916 DeoptimizeIf(not_equal, env); 4915 DeoptimizeIf(not_equal, instr);
4917 4916
4918 __ xorps(result_reg, result_reg); 4917 __ xorps(result_reg, result_reg);
4919 __ divsd(result_reg, result_reg); 4918 __ divsd(result_reg, result_reg);
4920 __ jmp(&done, Label::kNear); 4919 __ jmp(&done, Label::kNear);
4921 } 4920 }
4922 } else { 4921 } else {
4923 DCHECK(mode == NUMBER_CANDIDATE_IS_SMI); 4922 DCHECK(mode == NUMBER_CANDIDATE_IS_SMI);
4924 } 4923 }
4925 4924
4926 // Smi to XMM conversion 4925 // Smi to XMM conversion
(...skipping 27 matching lines...) Expand all
4954 4953
4955 __ bind(&check_bools); 4954 __ bind(&check_bools);
4956 __ CompareRoot(input_reg, Heap::kTrueValueRootIndex); 4955 __ CompareRoot(input_reg, Heap::kTrueValueRootIndex);
4957 __ j(not_equal, &check_false, Label::kNear); 4956 __ j(not_equal, &check_false, Label::kNear);
4958 __ Set(input_reg, 1); 4957 __ Set(input_reg, 1);
4959 __ jmp(done); 4958 __ jmp(done);
4960 4959
4961 __ bind(&check_false); 4960 __ bind(&check_false);
4962 __ CompareRoot(input_reg, Heap::kFalseValueRootIndex); 4961 __ CompareRoot(input_reg, Heap::kFalseValueRootIndex);
4963 __ RecordComment("Deferred TaggedToI: cannot truncate"); 4962 __ RecordComment("Deferred TaggedToI: cannot truncate");
4964 DeoptimizeIf(not_equal, instr->environment()); 4963 DeoptimizeIf(not_equal, instr);
4965 __ Set(input_reg, 0); 4964 __ Set(input_reg, 0);
4966 } else { 4965 } else {
4967 XMMRegister scratch = ToDoubleRegister(instr->temp()); 4966 XMMRegister scratch = ToDoubleRegister(instr->temp());
4968 DCHECK(!scratch.is(xmm0)); 4967 DCHECK(!scratch.is(xmm0));
4969 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), 4968 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset),
4970 Heap::kHeapNumberMapRootIndex); 4969 Heap::kHeapNumberMapRootIndex);
4971 __ RecordComment("Deferred TaggedToI: not a heap number"); 4970 __ RecordComment("Deferred TaggedToI: not a heap number");
4972 DeoptimizeIf(not_equal, instr->environment()); 4971 DeoptimizeIf(not_equal, instr);
4973 __ movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); 4972 __ movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset));
4974 __ cvttsd2si(input_reg, xmm0); 4973 __ cvttsd2si(input_reg, xmm0);
4975 __ Cvtlsi2sd(scratch, input_reg); 4974 __ Cvtlsi2sd(scratch, input_reg);
4976 __ ucomisd(xmm0, scratch); 4975 __ ucomisd(xmm0, scratch);
4977 __ RecordComment("Deferred TaggedToI: lost precision"); 4976 __ RecordComment("Deferred TaggedToI: lost precision");
4978 DeoptimizeIf(not_equal, instr->environment()); 4977 DeoptimizeIf(not_equal, instr);
4979 __ RecordComment("Deferred TaggedToI: NaN"); 4978 __ RecordComment("Deferred TaggedToI: NaN");
4980 DeoptimizeIf(parity_even, instr->environment()); 4979 DeoptimizeIf(parity_even, instr);
4981 if (instr->hydrogen()->GetMinusZeroMode() == FAIL_ON_MINUS_ZERO) { 4980 if (instr->hydrogen()->GetMinusZeroMode() == FAIL_ON_MINUS_ZERO) {
4982 __ testl(input_reg, input_reg); 4981 __ testl(input_reg, input_reg);
4983 __ j(not_zero, done); 4982 __ j(not_zero, done);
4984 __ movmskpd(input_reg, xmm0); 4983 __ movmskpd(input_reg, xmm0);
4985 __ andl(input_reg, Immediate(1)); 4984 __ andl(input_reg, Immediate(1));
4986 __ RecordComment("Deferred TaggedToI: minus zero"); 4985 __ RecordComment("Deferred TaggedToI: minus zero");
4987 DeoptimizeIf(not_zero, instr->environment()); 4986 DeoptimizeIf(not_zero, instr);
4988 } 4987 }
4989 } 4988 }
4990 } 4989 }
4991 4990
4992 4991
4993 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { 4992 void LCodeGen::DoTaggedToI(LTaggedToI* instr) {
4994 class DeferredTaggedToI FINAL : public LDeferredCode { 4993 class DeferredTaggedToI FINAL : public LDeferredCode {
4995 public: 4994 public:
4996 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) 4995 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr)
4997 : LDeferredCode(codegen), instr_(instr) { } 4996 : LDeferredCode(codegen), instr_(instr) { }
(...skipping 27 matching lines...) Expand all
5025 LOperand* result = instr->result(); 5024 LOperand* result = instr->result();
5026 DCHECK(result->IsDoubleRegister()); 5025 DCHECK(result->IsDoubleRegister());
5027 5026
5028 Register input_reg = ToRegister(input); 5027 Register input_reg = ToRegister(input);
5029 XMMRegister result_reg = ToDoubleRegister(result); 5028 XMMRegister result_reg = ToDoubleRegister(result);
5030 5029
5031 HValue* value = instr->hydrogen()->value(); 5030 HValue* value = instr->hydrogen()->value();
5032 NumberUntagDMode mode = value->representation().IsSmi() 5031 NumberUntagDMode mode = value->representation().IsSmi()
5033 ? NUMBER_CANDIDATE_IS_SMI : NUMBER_CANDIDATE_IS_ANY_TAGGED; 5032 ? NUMBER_CANDIDATE_IS_SMI : NUMBER_CANDIDATE_IS_ANY_TAGGED;
5034 5033
5035 EmitNumberUntagD(input_reg, result_reg, 5034 EmitNumberUntagD(instr, input_reg, result_reg, mode);
5036 instr->hydrogen()->can_convert_undefined_to_nan(),
5037 instr->hydrogen()->deoptimize_on_minus_zero(),
5038 instr->environment(),
5039 mode);
5040 } 5035 }
5041 5036
5042 5037
5043 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { 5038 void LCodeGen::DoDoubleToI(LDoubleToI* instr) {
5044 LOperand* input = instr->value(); 5039 LOperand* input = instr->value();
5045 DCHECK(input->IsDoubleRegister()); 5040 DCHECK(input->IsDoubleRegister());
5046 LOperand* result = instr->result(); 5041 LOperand* result = instr->result();
5047 DCHECK(result->IsRegister()); 5042 DCHECK(result->IsRegister());
5048 5043
5049 XMMRegister input_reg = ToDoubleRegister(input); 5044 XMMRegister input_reg = ToDoubleRegister(input);
5050 Register result_reg = ToRegister(result); 5045 Register result_reg = ToRegister(result);
5051 5046
5052 if (instr->truncating()) { 5047 if (instr->truncating()) {
5053 __ TruncateDoubleToI(result_reg, input_reg); 5048 __ TruncateDoubleToI(result_reg, input_reg);
5054 } else { 5049 } else {
5055 Label bailout, done; 5050 Label bailout, done;
5056 XMMRegister xmm_scratch = double_scratch0(); 5051 XMMRegister xmm_scratch = double_scratch0();
5057 __ DoubleToI(result_reg, input_reg, xmm_scratch, 5052 __ DoubleToI(result_reg, input_reg, xmm_scratch,
5058 instr->hydrogen()->GetMinusZeroMode(), &bailout, Label::kNear); 5053 instr->hydrogen()->GetMinusZeroMode(), &bailout, Label::kNear);
5059 5054
5060 __ jmp(&done, Label::kNear); 5055 __ jmp(&done, Label::kNear);
5061 __ bind(&bailout); 5056 __ bind(&bailout);
5062 DeoptimizeIf(no_condition, instr->environment()); 5057 DeoptimizeIf(no_condition, instr);
5063 __ bind(&done); 5058 __ bind(&done);
5064 } 5059 }
5065 } 5060 }
5066 5061
5067 5062
5068 void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) { 5063 void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) {
5069 LOperand* input = instr->value(); 5064 LOperand* input = instr->value();
5070 DCHECK(input->IsDoubleRegister()); 5065 DCHECK(input->IsDoubleRegister());
5071 LOperand* result = instr->result(); 5066 LOperand* result = instr->result();
5072 DCHECK(result->IsRegister()); 5067 DCHECK(result->IsRegister());
5073 5068
5074 XMMRegister input_reg = ToDoubleRegister(input); 5069 XMMRegister input_reg = ToDoubleRegister(input);
5075 Register result_reg = ToRegister(result); 5070 Register result_reg = ToRegister(result);
5076 5071
5077 Label bailout, done; 5072 Label bailout, done;
5078 XMMRegister xmm_scratch = double_scratch0(); 5073 XMMRegister xmm_scratch = double_scratch0();
5079 __ DoubleToI(result_reg, input_reg, xmm_scratch, 5074 __ DoubleToI(result_reg, input_reg, xmm_scratch,
5080 instr->hydrogen()->GetMinusZeroMode(), &bailout, Label::kNear); 5075 instr->hydrogen()->GetMinusZeroMode(), &bailout, Label::kNear);
5081 5076
5082 __ jmp(&done, Label::kNear); 5077 __ jmp(&done, Label::kNear);
5083 __ bind(&bailout); 5078 __ bind(&bailout);
5084 DeoptimizeIf(no_condition, instr->environment()); 5079 DeoptimizeIf(no_condition, instr);
5085 __ bind(&done); 5080 __ bind(&done);
5086 5081
5087 __ Integer32ToSmi(result_reg, result_reg); 5082 __ Integer32ToSmi(result_reg, result_reg);
5088 DeoptimizeIf(overflow, instr->environment()); 5083 DeoptimizeIf(overflow, instr);
5089 } 5084 }
5090 5085
5091 5086
5092 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { 5087 void LCodeGen::DoCheckSmi(LCheckSmi* instr) {
5093 LOperand* input = instr->value(); 5088 LOperand* input = instr->value();
5094 Condition cc = masm()->CheckSmi(ToRegister(input)); 5089 Condition cc = masm()->CheckSmi(ToRegister(input));
5095 DeoptimizeIf(NegateCondition(cc), instr->environment()); 5090 DeoptimizeIf(NegateCondition(cc), instr);
5096 } 5091 }
5097 5092
5098 5093
5099 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { 5094 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) {
5100 if (!instr->hydrogen()->value()->type().IsHeapObject()) { 5095 if (!instr->hydrogen()->value()->type().IsHeapObject()) {
5101 LOperand* input = instr->value(); 5096 LOperand* input = instr->value();
5102 Condition cc = masm()->CheckSmi(ToRegister(input)); 5097 Condition cc = masm()->CheckSmi(ToRegister(input));
5103 DeoptimizeIf(cc, instr->environment()); 5098 DeoptimizeIf(cc, instr);
5104 } 5099 }
5105 } 5100 }
5106 5101
5107 5102
5108 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { 5103 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
5109 Register input = ToRegister(instr->value()); 5104 Register input = ToRegister(instr->value());
5110 5105
5111 __ movp(kScratchRegister, FieldOperand(input, HeapObject::kMapOffset)); 5106 __ movp(kScratchRegister, FieldOperand(input, HeapObject::kMapOffset));
5112 5107
5113 if (instr->hydrogen()->is_interval_check()) { 5108 if (instr->hydrogen()->is_interval_check()) {
5114 InstanceType first; 5109 InstanceType first;
5115 InstanceType last; 5110 InstanceType last;
5116 instr->hydrogen()->GetCheckInterval(&first, &last); 5111 instr->hydrogen()->GetCheckInterval(&first, &last);
5117 5112
5118 __ cmpb(FieldOperand(kScratchRegister, Map::kInstanceTypeOffset), 5113 __ cmpb(FieldOperand(kScratchRegister, Map::kInstanceTypeOffset),
5119 Immediate(static_cast<int8_t>(first))); 5114 Immediate(static_cast<int8_t>(first)));
5120 5115
5121 // If there is only one type in the interval check for equality. 5116 // If there is only one type in the interval check for equality.
5122 if (first == last) { 5117 if (first == last) {
5123 DeoptimizeIf(not_equal, instr->environment()); 5118 DeoptimizeIf(not_equal, instr);
5124 } else { 5119 } else {
5125 DeoptimizeIf(below, instr->environment()); 5120 DeoptimizeIf(below, instr);
5126 // Omit check for the last type. 5121 // Omit check for the last type.
5127 if (last != LAST_TYPE) { 5122 if (last != LAST_TYPE) {
5128 __ cmpb(FieldOperand(kScratchRegister, Map::kInstanceTypeOffset), 5123 __ cmpb(FieldOperand(kScratchRegister, Map::kInstanceTypeOffset),
5129 Immediate(static_cast<int8_t>(last))); 5124 Immediate(static_cast<int8_t>(last)));
5130 DeoptimizeIf(above, instr->environment()); 5125 DeoptimizeIf(above, instr);
5131 } 5126 }
5132 } 5127 }
5133 } else { 5128 } else {
5134 uint8_t mask; 5129 uint8_t mask;
5135 uint8_t tag; 5130 uint8_t tag;
5136 instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag); 5131 instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag);
5137 5132
5138 if (base::bits::IsPowerOfTwo32(mask)) { 5133 if (base::bits::IsPowerOfTwo32(mask)) {
5139 DCHECK(tag == 0 || base::bits::IsPowerOfTwo32(tag)); 5134 DCHECK(tag == 0 || base::bits::IsPowerOfTwo32(tag));
5140 __ testb(FieldOperand(kScratchRegister, Map::kInstanceTypeOffset), 5135 __ testb(FieldOperand(kScratchRegister, Map::kInstanceTypeOffset),
5141 Immediate(mask)); 5136 Immediate(mask));
5142 DeoptimizeIf(tag == 0 ? not_zero : zero, instr->environment()); 5137 DeoptimizeIf(tag == 0 ? not_zero : zero, instr);
5143 } else { 5138 } else {
5144 __ movzxbl(kScratchRegister, 5139 __ movzxbl(kScratchRegister,
5145 FieldOperand(kScratchRegister, Map::kInstanceTypeOffset)); 5140 FieldOperand(kScratchRegister, Map::kInstanceTypeOffset));
5146 __ andb(kScratchRegister, Immediate(mask)); 5141 __ andb(kScratchRegister, Immediate(mask));
5147 __ cmpb(kScratchRegister, Immediate(tag)); 5142 __ cmpb(kScratchRegister, Immediate(tag));
5148 DeoptimizeIf(not_equal, instr->environment()); 5143 DeoptimizeIf(not_equal, instr);
5149 } 5144 }
5150 } 5145 }
5151 } 5146 }
5152 5147
5153 5148
5154 void LCodeGen::DoCheckValue(LCheckValue* instr) { 5149 void LCodeGen::DoCheckValue(LCheckValue* instr) {
5155 Register reg = ToRegister(instr->value()); 5150 Register reg = ToRegister(instr->value());
5156 __ Cmp(reg, instr->hydrogen()->object().handle()); 5151 __ Cmp(reg, instr->hydrogen()->object().handle());
5157 DeoptimizeIf(not_equal, instr->environment()); 5152 DeoptimizeIf(not_equal, instr);
5158 } 5153 }
5159 5154
5160 5155
5161 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) { 5156 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) {
5162 { 5157 {
5163 PushSafepointRegistersScope scope(this); 5158 PushSafepointRegistersScope scope(this);
5164 __ Push(object); 5159 __ Push(object);
5165 __ Set(rsi, 0); 5160 __ Set(rsi, 0);
5166 __ CallRuntimeSaveDoubles(Runtime::kTryMigrateInstance); 5161 __ CallRuntimeSaveDoubles(Runtime::kTryMigrateInstance);
5167 RecordSafepointWithRegisters( 5162 RecordSafepointWithRegisters(
5168 instr->pointer_map(), 1, Safepoint::kNoLazyDeopt); 5163 instr->pointer_map(), 1, Safepoint::kNoLazyDeopt);
5169 5164
5170 __ testp(rax, Immediate(kSmiTagMask)); 5165 __ testp(rax, Immediate(kSmiTagMask));
5171 } 5166 }
5172 DeoptimizeIf(zero, instr->environment()); 5167 DeoptimizeIf(zero, instr);
5173 } 5168 }
5174 5169
5175 5170
5176 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { 5171 void LCodeGen::DoCheckMaps(LCheckMaps* instr) {
5177 class DeferredCheckMaps FINAL : public LDeferredCode { 5172 class DeferredCheckMaps FINAL : public LDeferredCode {
5178 public: 5173 public:
5179 DeferredCheckMaps(LCodeGen* codegen, LCheckMaps* instr, Register object) 5174 DeferredCheckMaps(LCodeGen* codegen, LCheckMaps* instr, Register object)
5180 : LDeferredCode(codegen), instr_(instr), object_(object) { 5175 : LDeferredCode(codegen), instr_(instr), object_(object) {
5181 SetExit(check_maps()); 5176 SetExit(check_maps());
5182 } 5177 }
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
5215 Handle<Map> map = maps->at(i).handle(); 5210 Handle<Map> map = maps->at(i).handle();
5216 __ CompareMap(reg, map); 5211 __ CompareMap(reg, map);
5217 __ j(equal, &success, Label::kNear); 5212 __ j(equal, &success, Label::kNear);
5218 } 5213 }
5219 5214
5220 Handle<Map> map = maps->at(maps->size() - 1).handle(); 5215 Handle<Map> map = maps->at(maps->size() - 1).handle();
5221 __ CompareMap(reg, map); 5216 __ CompareMap(reg, map);
5222 if (instr->hydrogen()->HasMigrationTarget()) { 5217 if (instr->hydrogen()->HasMigrationTarget()) {
5223 __ j(not_equal, deferred->entry()); 5218 __ j(not_equal, deferred->entry());
5224 } else { 5219 } else {
5225 DeoptimizeIf(not_equal, instr->environment()); 5220 DeoptimizeIf(not_equal, instr);
5226 } 5221 }
5227 5222
5228 __ bind(&success); 5223 __ bind(&success);
5229 } 5224 }
5230 5225
5231 5226
5232 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { 5227 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) {
5233 XMMRegister value_reg = ToDoubleRegister(instr->unclamped()); 5228 XMMRegister value_reg = ToDoubleRegister(instr->unclamped());
5234 XMMRegister xmm_scratch = double_scratch0(); 5229 XMMRegister xmm_scratch = double_scratch0();
5235 Register result_reg = ToRegister(instr->result()); 5230 Register result_reg = ToRegister(instr->result());
(...skipping 18 matching lines...) Expand all
5254 __ JumpIfSmi(input_reg, &is_smi, dist); 5249 __ JumpIfSmi(input_reg, &is_smi, dist);
5255 5250
5256 // Check for heap number 5251 // Check for heap number
5257 __ Cmp(FieldOperand(input_reg, HeapObject::kMapOffset), 5252 __ Cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
5258 factory()->heap_number_map()); 5253 factory()->heap_number_map());
5259 __ j(equal, &heap_number, Label::kNear); 5254 __ j(equal, &heap_number, Label::kNear);
5260 5255
5261 // Check for undefined. Undefined is converted to zero for clamping 5256 // Check for undefined. Undefined is converted to zero for clamping
5262 // conversions. 5257 // conversions.
5263 __ Cmp(input_reg, factory()->undefined_value()); 5258 __ Cmp(input_reg, factory()->undefined_value());
5264 DeoptimizeIf(not_equal, instr->environment()); 5259 DeoptimizeIf(not_equal, instr);
5265 __ xorl(input_reg, input_reg); 5260 __ xorl(input_reg, input_reg);
5266 __ jmp(&done, Label::kNear); 5261 __ jmp(&done, Label::kNear);
5267 5262
5268 // Heap number 5263 // Heap number
5269 __ bind(&heap_number); 5264 __ bind(&heap_number);
5270 __ movsd(xmm_scratch, FieldOperand(input_reg, HeapNumber::kValueOffset)); 5265 __ movsd(xmm_scratch, FieldOperand(input_reg, HeapNumber::kValueOffset));
5271 __ ClampDoubleToUint8(xmm_scratch, temp_xmm_reg, input_reg); 5266 __ ClampDoubleToUint8(xmm_scratch, temp_xmm_reg, input_reg);
5272 __ jmp(&done, Label::kNear); 5267 __ jmp(&done, Label::kNear);
5273 5268
5274 // smi 5269 // smi
(...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after
5647 Deoptimizer::BailoutType type = instr->hydrogen()->type(); 5642 Deoptimizer::BailoutType type = instr->hydrogen()->type();
5648 // TODO(danno): Stubs expect all deopts to be lazy for historical reasons (the 5643 // TODO(danno): Stubs expect all deopts to be lazy for historical reasons (the
5649 // needed return address), even though the implementation of LAZY and EAGER is 5644 // needed return address), even though the implementation of LAZY and EAGER is
5650 // now identical. When LAZY is eventually completely folded into EAGER, remove 5645 // now identical. When LAZY is eventually completely folded into EAGER, remove
5651 // the special case below. 5646 // the special case below.
5652 if (info()->IsStub() && type == Deoptimizer::EAGER) { 5647 if (info()->IsStub() && type == Deoptimizer::EAGER) {
5653 type = Deoptimizer::LAZY; 5648 type = Deoptimizer::LAZY;
5654 } 5649 }
5655 5650
5656 Comment(";;; deoptimize: %s", instr->hydrogen()->reason()); 5651 Comment(";;; deoptimize: %s", instr->hydrogen()->reason());
5657 DeoptimizeIf(no_condition, instr->environment(), type); 5652 DeoptimizeIf(no_condition, instr, type);
5658 } 5653 }
5659 5654
5660 5655
5661 void LCodeGen::DoDummy(LDummy* instr) { 5656 void LCodeGen::DoDummy(LDummy* instr) {
5662 // Nothing to see here, move on! 5657 // Nothing to see here, move on!
5663 } 5658 }
5664 5659
5665 5660
5666 void LCodeGen::DoDummyUse(LDummyUse* instr) { 5661 void LCodeGen::DoDummyUse(LDummyUse* instr) {
5667 // Nothing to see here, move on! 5662 // Nothing to see here, move on!
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
5737 DCHECK(!environment->HasBeenRegistered()); 5732 DCHECK(!environment->HasBeenRegistered());
5738 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); 5733 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
5739 5734
5740 GenerateOsrPrologue(); 5735 GenerateOsrPrologue();
5741 } 5736 }
5742 5737
5743 5738
5744 void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) { 5739 void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) {
5745 DCHECK(ToRegister(instr->context()).is(rsi)); 5740 DCHECK(ToRegister(instr->context()).is(rsi));
5746 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); 5741 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
5747 DeoptimizeIf(equal, instr->environment()); 5742 DeoptimizeIf(equal, instr);
5748 5743
5749 Register null_value = rdi; 5744 Register null_value = rdi;
5750 __ LoadRoot(null_value, Heap::kNullValueRootIndex); 5745 __ LoadRoot(null_value, Heap::kNullValueRootIndex);
5751 __ cmpp(rax, null_value); 5746 __ cmpp(rax, null_value);
5752 DeoptimizeIf(equal, instr->environment()); 5747 DeoptimizeIf(equal, instr);
5753 5748
5754 Condition cc = masm()->CheckSmi(rax); 5749 Condition cc = masm()->CheckSmi(rax);
5755 DeoptimizeIf(cc, instr->environment()); 5750 DeoptimizeIf(cc, instr);
5756 5751
5757 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); 5752 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
5758 __ CmpObjectType(rax, LAST_JS_PROXY_TYPE, rcx); 5753 __ CmpObjectType(rax, LAST_JS_PROXY_TYPE, rcx);
5759 DeoptimizeIf(below_equal, instr->environment()); 5754 DeoptimizeIf(below_equal, instr);
5760 5755
5761 Label use_cache, call_runtime; 5756 Label use_cache, call_runtime;
5762 __ CheckEnumCache(null_value, &call_runtime); 5757 __ CheckEnumCache(null_value, &call_runtime);
5763 5758
5764 __ movp(rax, FieldOperand(rax, HeapObject::kMapOffset)); 5759 __ movp(rax, FieldOperand(rax, HeapObject::kMapOffset));
5765 __ jmp(&use_cache, Label::kNear); 5760 __ jmp(&use_cache, Label::kNear);
5766 5761
5767 // Get the set of properties to enumerate. 5762 // Get the set of properties to enumerate.
5768 __ bind(&call_runtime); 5763 __ bind(&call_runtime);
5769 __ Push(rax); 5764 __ Push(rax);
5770 CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr); 5765 CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr);
5771 5766
5772 __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset), 5767 __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset),
5773 Heap::kMetaMapRootIndex); 5768 Heap::kMetaMapRootIndex);
5774 DeoptimizeIf(not_equal, instr->environment()); 5769 DeoptimizeIf(not_equal, instr);
5775 __ bind(&use_cache); 5770 __ bind(&use_cache);
5776 } 5771 }
5777 5772
5778 5773
5779 void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) { 5774 void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) {
5780 Register map = ToRegister(instr->map()); 5775 Register map = ToRegister(instr->map());
5781 Register result = ToRegister(instr->result()); 5776 Register result = ToRegister(instr->result());
5782 Label load_cache, done; 5777 Label load_cache, done;
5783 __ EnumLength(result, map); 5778 __ EnumLength(result, map);
5784 __ Cmp(result, Smi::FromInt(0)); 5779 __ Cmp(result, Smi::FromInt(0));
5785 __ j(not_equal, &load_cache, Label::kNear); 5780 __ j(not_equal, &load_cache, Label::kNear);
5786 __ LoadRoot(result, Heap::kEmptyFixedArrayRootIndex); 5781 __ LoadRoot(result, Heap::kEmptyFixedArrayRootIndex);
5787 __ jmp(&done, Label::kNear); 5782 __ jmp(&done, Label::kNear);
5788 __ bind(&load_cache); 5783 __ bind(&load_cache);
5789 __ LoadInstanceDescriptors(map, result); 5784 __ LoadInstanceDescriptors(map, result);
5790 __ movp(result, 5785 __ movp(result,
5791 FieldOperand(result, DescriptorArray::kEnumCacheOffset)); 5786 FieldOperand(result, DescriptorArray::kEnumCacheOffset));
5792 __ movp(result, 5787 __ movp(result,
5793 FieldOperand(result, FixedArray::SizeFor(instr->idx()))); 5788 FieldOperand(result, FixedArray::SizeFor(instr->idx())));
5794 __ bind(&done); 5789 __ bind(&done);
5795 Condition cc = masm()->CheckSmi(result); 5790 Condition cc = masm()->CheckSmi(result);
5796 DeoptimizeIf(cc, instr->environment()); 5791 DeoptimizeIf(cc, instr);
5797 } 5792 }
5798 5793
5799 5794
5800 void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) { 5795 void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) {
5801 Register object = ToRegister(instr->value()); 5796 Register object = ToRegister(instr->value());
5802 __ cmpp(ToRegister(instr->map()), 5797 __ cmpp(ToRegister(instr->map()),
5803 FieldOperand(object, HeapObject::kMapOffset)); 5798 FieldOperand(object, HeapObject::kMapOffset));
5804 DeoptimizeIf(not_equal, instr->environment()); 5799 DeoptimizeIf(not_equal, instr);
5805 } 5800 }
5806 5801
5807 5802
5808 void LCodeGen::DoDeferredLoadMutableDouble(LLoadFieldByIndex* instr, 5803 void LCodeGen::DoDeferredLoadMutableDouble(LLoadFieldByIndex* instr,
5809 Register object, 5804 Register object,
5810 Register index) { 5805 Register index) {
5811 PushSafepointRegistersScope scope(this); 5806 PushSafepointRegistersScope scope(this);
5812 __ Push(object); 5807 __ Push(object);
5813 __ Push(index); 5808 __ Push(index);
5814 __ xorp(rsi, rsi); 5809 __ xorp(rsi, rsi);
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
5889 CallRuntime(Runtime::kPushBlockContext, 2, instr); 5884 CallRuntime(Runtime::kPushBlockContext, 2, instr);
5890 RecordSafepoint(Safepoint::kNoLazyDeopt); 5885 RecordSafepoint(Safepoint::kNoLazyDeopt);
5891 } 5886 }
5892 5887
5893 5888
5894 #undef __ 5889 #undef __
5895 5890
5896 } } // namespace v8::internal 5891 } } // namespace v8::internal
5897 5892
5898 #endif // V8_TARGET_ARCH_X64 5893 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/lithium-codegen-x64.h ('k') | src/x87/lithium-codegen-x87.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698