| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #if V8_TARGET_ARCH_X64 | 7 #if V8_TARGET_ARCH_X64 |
| 8 | 8 |
| 9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
| 10 #include "src/code-factory.h" | 10 #include "src/code-factory.h" |
| (...skipping 711 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 Loading... |
| 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 Loading... |
| 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, ÷nd_is_not_negative, Label::kNear); | 1033 __ j(not_sign, ÷nd_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(÷nd_is_not_negative); | 1044 __ bind(÷nd_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, ¬_kmin_int, Label::kNear); | 1168 __ j(no_overflow, ¬_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(¬_kmin_int); | 1171 __ bind(¬_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 Loading... |
| 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, ÷nd_not_zero, Label::kNear); | 1245 __ j(not_zero, ÷nd_not_zero, Label::kNear); |
| 1247 __ testl(divisor, divisor); | 1246 __ testl(divisor, divisor); |
| 1248 DeoptimizeIf(sign, instr->environment()); | 1247 DeoptimizeIf(sign, instr); |
| 1249 __ bind(÷nd_not_zero); | 1248 __ bind(÷nd_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, ÷nd_not_min_int, Label::kNear); | 1255 __ j(not_zero, ÷nd_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(÷nd_not_min_int); | 1258 __ bind(÷nd_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, ÷nd_not_zero, Label::kNear); | 1364 __ j(not_zero, ÷nd_not_zero, Label::kNear); |
| 1366 __ testl(divisor, divisor); | 1365 __ testl(divisor, divisor); |
| 1367 DeoptimizeIf(sign, instr->environment()); | 1366 DeoptimizeIf(sign, instr); |
| 1368 __ bind(÷nd_not_zero); | 1367 __ bind(÷nd_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, ÷nd_not_min_int, Label::kNear); | 1374 __ j(not_zero, ÷nd_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(÷nd_not_min_int); | 1377 __ bind(÷nd_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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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(¬_heap_number); | 2226 __ bind(¬_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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 4522 } | 4521 } |
| 4523 __ bind(¬_applicable); | 4522 __ bind(¬_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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |