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

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

Issue 892843007: Revert of Externalize deoptimization reasons. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/x64/lithium-codegen-x64.h ('k') | src/x87/lithium-codegen-x87.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/v8.h" 5 #include "src/v8.h"
6 6
7 #if V8_TARGET_ARCH_X64 7 #if V8_TARGET_ARCH_X64
8 8
9 #include "src/base/bits.h" 9 #include "src/base/bits.h"
10 #include "src/code-factory.h" 10 #include "src/code-factory.h"
(...skipping 705 matching lines...) Expand 10 before | Expand all | Expand 10 after
716 int pc_offset = masm()->pc_offset(); 716 int pc_offset = masm()->pc_offset();
717 environment->Register(deoptimization_index, 717 environment->Register(deoptimization_index,
718 translation.index(), 718 translation.index(),
719 (mode == Safepoint::kLazyDeopt) ? pc_offset : -1); 719 (mode == Safepoint::kLazyDeopt) ? pc_offset : -1);
720 deoptimizations_.Add(environment, environment->zone()); 720 deoptimizations_.Add(environment, environment->zone());
721 } 721 }
722 } 722 }
723 723
724 724
725 void LCodeGen::DeoptimizeIf(Condition cc, LInstruction* instr, 725 void LCodeGen::DeoptimizeIf(Condition cc, LInstruction* instr,
726 Deoptimizer::DeoptReason deopt_reason, 726 const char* detail,
727 Deoptimizer::BailoutType bailout_type) { 727 Deoptimizer::BailoutType bailout_type) {
728 LEnvironment* environment = instr->environment(); 728 LEnvironment* environment = instr->environment();
729 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); 729 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
730 DCHECK(environment->HasBeenRegistered()); 730 DCHECK(environment->HasBeenRegistered());
731 int id = environment->deoptimization_index(); 731 int id = environment->deoptimization_index();
732 DCHECK(info()->IsOptimizing() || info()->IsStub()); 732 DCHECK(info()->IsOptimizing() || info()->IsStub());
733 Address entry = 733 Address entry =
734 Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type); 734 Deoptimizer::GetDeoptimizationEntry(isolate(), id, bailout_type);
735 if (entry == NULL) { 735 if (entry == NULL) {
736 Abort(kBailoutWasNotPrepared); 736 Abort(kBailoutWasNotPrepared);
(...skipping 25 matching lines...) Expand all
762 if (info()->ShouldTrapOnDeopt()) { 762 if (info()->ShouldTrapOnDeopt()) {
763 Label done; 763 Label done;
764 if (cc != no_condition) { 764 if (cc != no_condition) {
765 __ j(NegateCondition(cc), &done, Label::kNear); 765 __ j(NegateCondition(cc), &done, Label::kNear);
766 } 766 }
767 __ int3(); 767 __ int3();
768 __ bind(&done); 768 __ bind(&done);
769 } 769 }
770 770
771 Deoptimizer::Reason reason(instr->hydrogen_value()->position().raw(), 771 Deoptimizer::Reason reason(instr->hydrogen_value()->position().raw(),
772 instr->Mnemonic(), deopt_reason); 772 instr->Mnemonic(), detail);
773 DCHECK(info()->IsStub() || frame_is_built_); 773 DCHECK(info()->IsStub() || frame_is_built_);
774 // Go through jump table if we need to handle condition, build frame, or 774 // Go through jump table if we need to handle condition, build frame, or
775 // restore caller doubles. 775 // restore caller doubles.
776 if (cc == no_condition && frame_is_built_ && 776 if (cc == no_condition && frame_is_built_ &&
777 !info()->saves_caller_doubles()) { 777 !info()->saves_caller_doubles()) {
778 DeoptComment(reason); 778 DeoptComment(reason);
779 __ call(entry, RelocInfo::RUNTIME_ENTRY); 779 __ call(entry, RelocInfo::RUNTIME_ENTRY);
780 } else { 780 } else {
781 Deoptimizer::JumpTableEntry table_entry(entry, reason, bailout_type, 781 Deoptimizer::JumpTableEntry table_entry(entry, reason, bailout_type,
782 !frame_is_built_); 782 !frame_is_built_);
783 // We often have several deopts to the same entry, reuse the last 783 // We often have several deopts to the same entry, reuse the last
784 // jump entry if this is the case. 784 // jump entry if this is the case.
785 if (jump_table_.is_empty() || 785 if (jump_table_.is_empty() ||
786 !table_entry.IsEquivalentTo(jump_table_.last())) { 786 !table_entry.IsEquivalentTo(jump_table_.last())) {
787 jump_table_.Add(table_entry, zone()); 787 jump_table_.Add(table_entry, zone());
788 } 788 }
789 if (cc == no_condition) { 789 if (cc == no_condition) {
790 __ jmp(&jump_table_.last().label); 790 __ jmp(&jump_table_.last().label);
791 } else { 791 } else {
792 __ j(cc, &jump_table_.last().label); 792 __ j(cc, &jump_table_.last().label);
793 } 793 }
794 } 794 }
795 } 795 }
796 796
797 797
798 void LCodeGen::DeoptimizeIf(Condition cc, LInstruction* instr, 798 void LCodeGen::DeoptimizeIf(Condition cc, LInstruction* instr,
799 Deoptimizer::DeoptReason deopt_reason) { 799 const char* detail) {
800 Deoptimizer::BailoutType bailout_type = info()->IsStub() 800 Deoptimizer::BailoutType bailout_type = info()->IsStub()
801 ? Deoptimizer::LAZY 801 ? Deoptimizer::LAZY
802 : Deoptimizer::EAGER; 802 : Deoptimizer::EAGER;
803 DeoptimizeIf(cc, instr, deopt_reason, bailout_type); 803 DeoptimizeIf(cc, instr, detail, bailout_type);
804 } 804 }
805 805
806 806
807 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) { 807 void LCodeGen::PopulateDeoptimizationData(Handle<Code> code) {
808 int length = deoptimizations_.length(); 808 int length = deoptimizations_.length();
809 if (length == 0) return; 809 if (length == 0) return;
810 Handle<DeoptimizationInputData> data = 810 Handle<DeoptimizationInputData> data =
811 DeoptimizationInputData::New(isolate(), length, TENURED); 811 DeoptimizationInputData::New(isolate(), length, TENURED);
812 812
813 Handle<ByteArray> translations = 813 Handle<ByteArray> translations =
(...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after
1025 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); 1025 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1);
1026 Label dividend_is_not_negative, done; 1026 Label dividend_is_not_negative, done;
1027 if (hmod->CheckFlag(HValue::kLeftCanBeNegative)) { 1027 if (hmod->CheckFlag(HValue::kLeftCanBeNegative)) {
1028 __ testl(dividend, dividend); 1028 __ testl(dividend, dividend);
1029 __ j(not_sign, &dividend_is_not_negative, Label::kNear); 1029 __ j(not_sign, &dividend_is_not_negative, Label::kNear);
1030 // Note that this is correct even for kMinInt operands. 1030 // Note that this is correct even for kMinInt operands.
1031 __ negl(dividend); 1031 __ negl(dividend);
1032 __ andl(dividend, Immediate(mask)); 1032 __ andl(dividend, Immediate(mask));
1033 __ negl(dividend); 1033 __ negl(dividend);
1034 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { 1034 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1035 DeoptimizeIf(zero, instr, Deoptimizer::kMinusZero); 1035 DeoptimizeIf(zero, instr, "minus zero");
1036 } 1036 }
1037 __ jmp(&done, Label::kNear); 1037 __ jmp(&done, Label::kNear);
1038 } 1038 }
1039 1039
1040 __ bind(&dividend_is_not_negative); 1040 __ bind(&dividend_is_not_negative);
1041 __ andl(dividend, Immediate(mask)); 1041 __ andl(dividend, Immediate(mask));
1042 __ bind(&done); 1042 __ bind(&done);
1043 } 1043 }
1044 1044
1045 1045
1046 void LCodeGen::DoModByConstI(LModByConstI* instr) { 1046 void LCodeGen::DoModByConstI(LModByConstI* instr) {
1047 Register dividend = ToRegister(instr->dividend()); 1047 Register dividend = ToRegister(instr->dividend());
1048 int32_t divisor = instr->divisor(); 1048 int32_t divisor = instr->divisor();
1049 DCHECK(ToRegister(instr->result()).is(rax)); 1049 DCHECK(ToRegister(instr->result()).is(rax));
1050 1050
1051 if (divisor == 0) { 1051 if (divisor == 0) {
1052 DeoptimizeIf(no_condition, instr, Deoptimizer::kDivisionByZero); 1052 DeoptimizeIf(no_condition, instr, "division by zero");
1053 return; 1053 return;
1054 } 1054 }
1055 1055
1056 __ TruncatingDiv(dividend, Abs(divisor)); 1056 __ TruncatingDiv(dividend, Abs(divisor));
1057 __ imull(rdx, rdx, Immediate(Abs(divisor))); 1057 __ imull(rdx, rdx, Immediate(Abs(divisor)));
1058 __ movl(rax, dividend); 1058 __ movl(rax, dividend);
1059 __ subl(rax, rdx); 1059 __ subl(rax, rdx);
1060 1060
1061 // Check for negative zero. 1061 // Check for negative zero.
1062 HMod* hmod = instr->hydrogen(); 1062 HMod* hmod = instr->hydrogen();
1063 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { 1063 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1064 Label remainder_not_zero; 1064 Label remainder_not_zero;
1065 __ j(not_zero, &remainder_not_zero, Label::kNear); 1065 __ j(not_zero, &remainder_not_zero, Label::kNear);
1066 __ cmpl(dividend, Immediate(0)); 1066 __ cmpl(dividend, Immediate(0));
1067 DeoptimizeIf(less, instr, Deoptimizer::kMinusZero); 1067 DeoptimizeIf(less, instr, "minus zero");
1068 __ bind(&remainder_not_zero); 1068 __ bind(&remainder_not_zero);
1069 } 1069 }
1070 } 1070 }
1071 1071
1072 1072
1073 void LCodeGen::DoModI(LModI* instr) { 1073 void LCodeGen::DoModI(LModI* instr) {
1074 HMod* hmod = instr->hydrogen(); 1074 HMod* hmod = instr->hydrogen();
1075 1075
1076 Register left_reg = ToRegister(instr->left()); 1076 Register left_reg = ToRegister(instr->left());
1077 DCHECK(left_reg.is(rax)); 1077 DCHECK(left_reg.is(rax));
1078 Register right_reg = ToRegister(instr->right()); 1078 Register right_reg = ToRegister(instr->right());
1079 DCHECK(!right_reg.is(rax)); 1079 DCHECK(!right_reg.is(rax));
1080 DCHECK(!right_reg.is(rdx)); 1080 DCHECK(!right_reg.is(rdx));
1081 Register result_reg = ToRegister(instr->result()); 1081 Register result_reg = ToRegister(instr->result());
1082 DCHECK(result_reg.is(rdx)); 1082 DCHECK(result_reg.is(rdx));
1083 1083
1084 Label done; 1084 Label done;
1085 // Check for x % 0, idiv would signal a divide error. We have to 1085 // Check for x % 0, idiv would signal a divide error. We have to
1086 // deopt in this case because we can't return a NaN. 1086 // deopt in this case because we can't return a NaN.
1087 if (hmod->CheckFlag(HValue::kCanBeDivByZero)) { 1087 if (hmod->CheckFlag(HValue::kCanBeDivByZero)) {
1088 __ testl(right_reg, right_reg); 1088 __ testl(right_reg, right_reg);
1089 DeoptimizeIf(zero, instr, Deoptimizer::kDivisionByZero); 1089 DeoptimizeIf(zero, instr, "division by zero");
1090 } 1090 }
1091 1091
1092 // Check for kMinInt % -1, idiv would signal a divide error. We 1092 // Check for kMinInt % -1, idiv would signal a divide error. We
1093 // have to deopt if we care about -0, because we can't return that. 1093 // have to deopt if we care about -0, because we can't return that.
1094 if (hmod->CheckFlag(HValue::kCanOverflow)) { 1094 if (hmod->CheckFlag(HValue::kCanOverflow)) {
1095 Label no_overflow_possible; 1095 Label no_overflow_possible;
1096 __ cmpl(left_reg, Immediate(kMinInt)); 1096 __ cmpl(left_reg, Immediate(kMinInt));
1097 __ j(not_zero, &no_overflow_possible, Label::kNear); 1097 __ j(not_zero, &no_overflow_possible, Label::kNear);
1098 __ cmpl(right_reg, Immediate(-1)); 1098 __ cmpl(right_reg, Immediate(-1));
1099 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { 1099 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1100 DeoptimizeIf(equal, instr, Deoptimizer::kMinusZero); 1100 DeoptimizeIf(equal, instr, "minus zero");
1101 } else { 1101 } else {
1102 __ j(not_equal, &no_overflow_possible, Label::kNear); 1102 __ j(not_equal, &no_overflow_possible, Label::kNear);
1103 __ Set(result_reg, 0); 1103 __ Set(result_reg, 0);
1104 __ jmp(&done, Label::kNear); 1104 __ jmp(&done, Label::kNear);
1105 } 1105 }
1106 __ bind(&no_overflow_possible); 1106 __ bind(&no_overflow_possible);
1107 } 1107 }
1108 1108
1109 // Sign extend dividend in eax into edx:eax, since we are using only the low 1109 // Sign extend dividend in eax into edx:eax, since we are using only the low
1110 // 32 bits of the values. 1110 // 32 bits of the values.
1111 __ cdq(); 1111 __ cdq();
1112 1112
1113 // If we care about -0, test if the dividend is <0 and the result is 0. 1113 // If we care about -0, test if the dividend is <0 and the result is 0.
1114 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { 1114 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1115 Label positive_left; 1115 Label positive_left;
1116 __ testl(left_reg, left_reg); 1116 __ testl(left_reg, left_reg);
1117 __ j(not_sign, &positive_left, Label::kNear); 1117 __ j(not_sign, &positive_left, Label::kNear);
1118 __ idivl(right_reg); 1118 __ idivl(right_reg);
1119 __ testl(result_reg, result_reg); 1119 __ testl(result_reg, result_reg);
1120 DeoptimizeIf(zero, instr, Deoptimizer::kMinusZero); 1120 DeoptimizeIf(zero, instr, "minus zero");
1121 __ jmp(&done, Label::kNear); 1121 __ jmp(&done, Label::kNear);
1122 __ bind(&positive_left); 1122 __ bind(&positive_left);
1123 } 1123 }
1124 __ idivl(right_reg); 1124 __ idivl(right_reg);
1125 __ bind(&done); 1125 __ bind(&done);
1126 } 1126 }
1127 1127
1128 1128
1129 void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) { 1129 void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) {
1130 Register dividend = ToRegister(instr->dividend()); 1130 Register dividend = ToRegister(instr->dividend());
1131 int32_t divisor = instr->divisor(); 1131 int32_t divisor = instr->divisor();
1132 DCHECK(dividend.is(ToRegister(instr->result()))); 1132 DCHECK(dividend.is(ToRegister(instr->result())));
1133 1133
1134 // If the divisor is positive, things are easy: There can be no deopts and we 1134 // If the divisor is positive, things are easy: There can be no deopts and we
1135 // can simply do an arithmetic right shift. 1135 // can simply do an arithmetic right shift.
1136 if (divisor == 1) return; 1136 if (divisor == 1) return;
1137 int32_t shift = WhichPowerOf2Abs(divisor); 1137 int32_t shift = WhichPowerOf2Abs(divisor);
1138 if (divisor > 1) { 1138 if (divisor > 1) {
1139 __ sarl(dividend, Immediate(shift)); 1139 __ sarl(dividend, Immediate(shift));
1140 return; 1140 return;
1141 } 1141 }
1142 1142
1143 // If the divisor is negative, we have to negate and handle edge cases. 1143 // If the divisor is negative, we have to negate and handle edge cases.
1144 __ negl(dividend); 1144 __ negl(dividend);
1145 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 1145 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
1146 DeoptimizeIf(zero, instr, Deoptimizer::kMinusZero); 1146 DeoptimizeIf(zero, instr, "minus zero");
1147 } 1147 }
1148 1148
1149 // Dividing by -1 is basically negation, unless we overflow. 1149 // Dividing by -1 is basically negation, unless we overflow.
1150 if (divisor == -1) { 1150 if (divisor == -1) {
1151 if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { 1151 if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) {
1152 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow); 1152 DeoptimizeIf(overflow, instr, "overflow");
1153 } 1153 }
1154 return; 1154 return;
1155 } 1155 }
1156 1156
1157 // If the negation could not overflow, simply shifting is OK. 1157 // If the negation could not overflow, simply shifting is OK.
1158 if (!instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) { 1158 if (!instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) {
1159 __ sarl(dividend, Immediate(shift)); 1159 __ sarl(dividend, Immediate(shift));
1160 return; 1160 return;
1161 } 1161 }
1162 1162
1163 Label not_kmin_int, done; 1163 Label not_kmin_int, done;
1164 __ j(no_overflow, &not_kmin_int, Label::kNear); 1164 __ j(no_overflow, &not_kmin_int, Label::kNear);
1165 __ movl(dividend, Immediate(kMinInt / divisor)); 1165 __ movl(dividend, Immediate(kMinInt / divisor));
1166 __ jmp(&done, Label::kNear); 1166 __ jmp(&done, Label::kNear);
1167 __ bind(&not_kmin_int); 1167 __ bind(&not_kmin_int);
1168 __ sarl(dividend, Immediate(shift)); 1168 __ sarl(dividend, Immediate(shift));
1169 __ bind(&done); 1169 __ bind(&done);
1170 } 1170 }
1171 1171
1172 1172
1173 void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) { 1173 void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) {
1174 Register dividend = ToRegister(instr->dividend()); 1174 Register dividend = ToRegister(instr->dividend());
1175 int32_t divisor = instr->divisor(); 1175 int32_t divisor = instr->divisor();
1176 DCHECK(ToRegister(instr->result()).is(rdx)); 1176 DCHECK(ToRegister(instr->result()).is(rdx));
1177 1177
1178 if (divisor == 0) { 1178 if (divisor == 0) {
1179 DeoptimizeIf(no_condition, instr, Deoptimizer::kDivisionByZero); 1179 DeoptimizeIf(no_condition, instr, "division by zero");
1180 return; 1180 return;
1181 } 1181 }
1182 1182
1183 // Check for (0 / -x) that will produce negative zero. 1183 // Check for (0 / -x) that will produce negative zero.
1184 HMathFloorOfDiv* hdiv = instr->hydrogen(); 1184 HMathFloorOfDiv* hdiv = instr->hydrogen();
1185 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { 1185 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
1186 __ testl(dividend, dividend); 1186 __ testl(dividend, dividend);
1187 DeoptimizeIf(zero, instr, Deoptimizer::kMinusZero); 1187 DeoptimizeIf(zero, instr, "minus zero");
1188 } 1188 }
1189 1189
1190 // Easy case: We need no dynamic check for the dividend and the flooring 1190 // Easy case: We need no dynamic check for the dividend and the flooring
1191 // division is the same as the truncating division. 1191 // division is the same as the truncating division.
1192 if ((divisor > 0 && !hdiv->CheckFlag(HValue::kLeftCanBeNegative)) || 1192 if ((divisor > 0 && !hdiv->CheckFlag(HValue::kLeftCanBeNegative)) ||
1193 (divisor < 0 && !hdiv->CheckFlag(HValue::kLeftCanBePositive))) { 1193 (divisor < 0 && !hdiv->CheckFlag(HValue::kLeftCanBePositive))) {
1194 __ TruncatingDiv(dividend, Abs(divisor)); 1194 __ TruncatingDiv(dividend, Abs(divisor));
1195 if (divisor < 0) __ negl(rdx); 1195 if (divisor < 0) __ negl(rdx);
1196 return; 1196 return;
1197 } 1197 }
(...skipping 26 matching lines...) Expand all
1224 Register result = ToRegister(instr->result()); 1224 Register result = ToRegister(instr->result());
1225 DCHECK(dividend.is(rax)); 1225 DCHECK(dividend.is(rax));
1226 DCHECK(remainder.is(rdx)); 1226 DCHECK(remainder.is(rdx));
1227 DCHECK(result.is(rax)); 1227 DCHECK(result.is(rax));
1228 DCHECK(!divisor.is(rax)); 1228 DCHECK(!divisor.is(rax));
1229 DCHECK(!divisor.is(rdx)); 1229 DCHECK(!divisor.is(rdx));
1230 1230
1231 // Check for x / 0. 1231 // Check for x / 0.
1232 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { 1232 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
1233 __ testl(divisor, divisor); 1233 __ testl(divisor, divisor);
1234 DeoptimizeIf(zero, instr, Deoptimizer::kDivisionByZero); 1234 DeoptimizeIf(zero, instr, "division by zero");
1235 } 1235 }
1236 1236
1237 // Check for (0 / -x) that will produce negative zero. 1237 // Check for (0 / -x) that will produce negative zero.
1238 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { 1238 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) {
1239 Label dividend_not_zero; 1239 Label dividend_not_zero;
1240 __ testl(dividend, dividend); 1240 __ testl(dividend, dividend);
1241 __ j(not_zero, &dividend_not_zero, Label::kNear); 1241 __ j(not_zero, &dividend_not_zero, Label::kNear);
1242 __ testl(divisor, divisor); 1242 __ testl(divisor, divisor);
1243 DeoptimizeIf(sign, instr, Deoptimizer::kMinusZero); 1243 DeoptimizeIf(sign, instr, "minus zero");
1244 __ bind(&dividend_not_zero); 1244 __ bind(&dividend_not_zero);
1245 } 1245 }
1246 1246
1247 // Check for (kMinInt / -1). 1247 // Check for (kMinInt / -1).
1248 if (hdiv->CheckFlag(HValue::kCanOverflow)) { 1248 if (hdiv->CheckFlag(HValue::kCanOverflow)) {
1249 Label dividend_not_min_int; 1249 Label dividend_not_min_int;
1250 __ cmpl(dividend, Immediate(kMinInt)); 1250 __ cmpl(dividend, Immediate(kMinInt));
1251 __ j(not_zero, &dividend_not_min_int, Label::kNear); 1251 __ j(not_zero, &dividend_not_min_int, Label::kNear);
1252 __ cmpl(divisor, Immediate(-1)); 1252 __ cmpl(divisor, Immediate(-1));
1253 DeoptimizeIf(zero, instr, Deoptimizer::kOverflow); 1253 DeoptimizeIf(zero, instr, "overflow");
1254 __ bind(&dividend_not_min_int); 1254 __ bind(&dividend_not_min_int);
1255 } 1255 }
1256 1256
1257 // Sign extend to rdx (= remainder). 1257 // Sign extend to rdx (= remainder).
1258 __ cdq(); 1258 __ cdq();
1259 __ idivl(divisor); 1259 __ idivl(divisor);
1260 1260
1261 Label done; 1261 Label done;
1262 __ testl(remainder, remainder); 1262 __ testl(remainder, remainder);
1263 __ j(zero, &done, Label::kNear); 1263 __ j(zero, &done, Label::kNear);
1264 __ xorl(remainder, divisor); 1264 __ xorl(remainder, divisor);
1265 __ sarl(remainder, Immediate(31)); 1265 __ sarl(remainder, Immediate(31));
1266 __ addl(result, remainder); 1266 __ addl(result, remainder);
1267 __ bind(&done); 1267 __ bind(&done);
1268 } 1268 }
1269 1269
1270 1270
1271 void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) { 1271 void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) {
1272 Register dividend = ToRegister(instr->dividend()); 1272 Register dividend = ToRegister(instr->dividend());
1273 int32_t divisor = instr->divisor(); 1273 int32_t divisor = instr->divisor();
1274 Register result = ToRegister(instr->result()); 1274 Register result = ToRegister(instr->result());
1275 DCHECK(divisor == kMinInt || base::bits::IsPowerOfTwo32(Abs(divisor))); 1275 DCHECK(divisor == kMinInt || base::bits::IsPowerOfTwo32(Abs(divisor)));
1276 DCHECK(!result.is(dividend)); 1276 DCHECK(!result.is(dividend));
1277 1277
1278 // Check for (0 / -x) that will produce negative zero. 1278 // Check for (0 / -x) that will produce negative zero.
1279 HDiv* hdiv = instr->hydrogen(); 1279 HDiv* hdiv = instr->hydrogen();
1280 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { 1280 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
1281 __ testl(dividend, dividend); 1281 __ testl(dividend, dividend);
1282 DeoptimizeIf(zero, instr, Deoptimizer::kMinusZero); 1282 DeoptimizeIf(zero, instr, "minus zero");
1283 } 1283 }
1284 // Check for (kMinInt / -1). 1284 // Check for (kMinInt / -1).
1285 if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) { 1285 if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) {
1286 __ cmpl(dividend, Immediate(kMinInt)); 1286 __ cmpl(dividend, Immediate(kMinInt));
1287 DeoptimizeIf(zero, instr, Deoptimizer::kOverflow); 1287 DeoptimizeIf(zero, instr, "overflow");
1288 } 1288 }
1289 // Deoptimize if remainder will not be 0. 1289 // Deoptimize if remainder will not be 0.
1290 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) && 1290 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) &&
1291 divisor != 1 && divisor != -1) { 1291 divisor != 1 && divisor != -1) {
1292 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1); 1292 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1);
1293 __ testl(dividend, Immediate(mask)); 1293 __ testl(dividend, Immediate(mask));
1294 DeoptimizeIf(not_zero, instr, Deoptimizer::kLostPrecision); 1294 DeoptimizeIf(not_zero, instr, "lost precision");
1295 } 1295 }
1296 __ Move(result, dividend); 1296 __ Move(result, dividend);
1297 int32_t shift = WhichPowerOf2Abs(divisor); 1297 int32_t shift = WhichPowerOf2Abs(divisor);
1298 if (shift > 0) { 1298 if (shift > 0) {
1299 // The arithmetic shift is always OK, the 'if' is an optimization only. 1299 // The arithmetic shift is always OK, the 'if' is an optimization only.
1300 if (shift > 1) __ sarl(result, Immediate(31)); 1300 if (shift > 1) __ sarl(result, Immediate(31));
1301 __ shrl(result, Immediate(32 - shift)); 1301 __ shrl(result, Immediate(32 - shift));
1302 __ addl(result, dividend); 1302 __ addl(result, dividend);
1303 __ sarl(result, Immediate(shift)); 1303 __ sarl(result, Immediate(shift));
1304 } 1304 }
1305 if (divisor < 0) __ negl(result); 1305 if (divisor < 0) __ negl(result);
1306 } 1306 }
1307 1307
1308 1308
1309 void LCodeGen::DoDivByConstI(LDivByConstI* instr) { 1309 void LCodeGen::DoDivByConstI(LDivByConstI* instr) {
1310 Register dividend = ToRegister(instr->dividend()); 1310 Register dividend = ToRegister(instr->dividend());
1311 int32_t divisor = instr->divisor(); 1311 int32_t divisor = instr->divisor();
1312 DCHECK(ToRegister(instr->result()).is(rdx)); 1312 DCHECK(ToRegister(instr->result()).is(rdx));
1313 1313
1314 if (divisor == 0) { 1314 if (divisor == 0) {
1315 DeoptimizeIf(no_condition, instr, Deoptimizer::kDivisionByZero); 1315 DeoptimizeIf(no_condition, instr, "division by zero");
1316 return; 1316 return;
1317 } 1317 }
1318 1318
1319 // Check for (0 / -x) that will produce negative zero. 1319 // Check for (0 / -x) that will produce negative zero.
1320 HDiv* hdiv = instr->hydrogen(); 1320 HDiv* hdiv = instr->hydrogen();
1321 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) { 1321 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
1322 __ testl(dividend, dividend); 1322 __ testl(dividend, dividend);
1323 DeoptimizeIf(zero, instr, Deoptimizer::kMinusZero); 1323 DeoptimizeIf(zero, instr, "minus zero");
1324 } 1324 }
1325 1325
1326 __ TruncatingDiv(dividend, Abs(divisor)); 1326 __ TruncatingDiv(dividend, Abs(divisor));
1327 if (divisor < 0) __ negl(rdx); 1327 if (divisor < 0) __ negl(rdx);
1328 1328
1329 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) { 1329 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) {
1330 __ movl(rax, rdx); 1330 __ movl(rax, rdx);
1331 __ imull(rax, rax, Immediate(divisor)); 1331 __ imull(rax, rax, Immediate(divisor));
1332 __ subl(rax, dividend); 1332 __ subl(rax, dividend);
1333 DeoptimizeIf(not_equal, instr, Deoptimizer::kLostPrecision); 1333 DeoptimizeIf(not_equal, instr, "lost precision");
1334 } 1334 }
1335 } 1335 }
1336 1336
1337 1337
1338 // TODO(svenpanne) Refactor this to avoid code duplication with DoFlooringDivI. 1338 // TODO(svenpanne) Refactor this to avoid code duplication with DoFlooringDivI.
1339 void LCodeGen::DoDivI(LDivI* instr) { 1339 void LCodeGen::DoDivI(LDivI* instr) {
1340 HBinaryOperation* hdiv = instr->hydrogen(); 1340 HBinaryOperation* hdiv = instr->hydrogen();
1341 Register dividend = ToRegister(instr->dividend()); 1341 Register dividend = ToRegister(instr->dividend());
1342 Register divisor = ToRegister(instr->divisor()); 1342 Register divisor = ToRegister(instr->divisor());
1343 Register remainder = ToRegister(instr->temp()); 1343 Register remainder = ToRegister(instr->temp());
1344 DCHECK(dividend.is(rax)); 1344 DCHECK(dividend.is(rax));
1345 DCHECK(remainder.is(rdx)); 1345 DCHECK(remainder.is(rdx));
1346 DCHECK(ToRegister(instr->result()).is(rax)); 1346 DCHECK(ToRegister(instr->result()).is(rax));
1347 DCHECK(!divisor.is(rax)); 1347 DCHECK(!divisor.is(rax));
1348 DCHECK(!divisor.is(rdx)); 1348 DCHECK(!divisor.is(rdx));
1349 1349
1350 // Check for x / 0. 1350 // Check for x / 0.
1351 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) { 1351 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
1352 __ testl(divisor, divisor); 1352 __ testl(divisor, divisor);
1353 DeoptimizeIf(zero, instr, Deoptimizer::kDivisionByZero); 1353 DeoptimizeIf(zero, instr, "division by zero");
1354 } 1354 }
1355 1355
1356 // Check for (0 / -x) that will produce negative zero. 1356 // Check for (0 / -x) that will produce negative zero.
1357 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { 1357 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) {
1358 Label dividend_not_zero; 1358 Label dividend_not_zero;
1359 __ testl(dividend, dividend); 1359 __ testl(dividend, dividend);
1360 __ j(not_zero, &dividend_not_zero, Label::kNear); 1360 __ j(not_zero, &dividend_not_zero, Label::kNear);
1361 __ testl(divisor, divisor); 1361 __ testl(divisor, divisor);
1362 DeoptimizeIf(sign, instr, Deoptimizer::kMinusZero); 1362 DeoptimizeIf(sign, instr, "minus zero");
1363 __ bind(&dividend_not_zero); 1363 __ bind(&dividend_not_zero);
1364 } 1364 }
1365 1365
1366 // Check for (kMinInt / -1). 1366 // Check for (kMinInt / -1).
1367 if (hdiv->CheckFlag(HValue::kCanOverflow)) { 1367 if (hdiv->CheckFlag(HValue::kCanOverflow)) {
1368 Label dividend_not_min_int; 1368 Label dividend_not_min_int;
1369 __ cmpl(dividend, Immediate(kMinInt)); 1369 __ cmpl(dividend, Immediate(kMinInt));
1370 __ j(not_zero, &dividend_not_min_int, Label::kNear); 1370 __ j(not_zero, &dividend_not_min_int, Label::kNear);
1371 __ cmpl(divisor, Immediate(-1)); 1371 __ cmpl(divisor, Immediate(-1));
1372 DeoptimizeIf(zero, instr, Deoptimizer::kOverflow); 1372 DeoptimizeIf(zero, instr, "overflow");
1373 __ bind(&dividend_not_min_int); 1373 __ bind(&dividend_not_min_int);
1374 } 1374 }
1375 1375
1376 // Sign extend to rdx (= remainder). 1376 // Sign extend to rdx (= remainder).
1377 __ cdq(); 1377 __ cdq();
1378 __ idivl(divisor); 1378 __ idivl(divisor);
1379 1379
1380 if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) { 1380 if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
1381 // Deoptimize if remainder is not 0. 1381 // Deoptimize if remainder is not 0.
1382 __ testl(remainder, remainder); 1382 __ testl(remainder, remainder);
1383 DeoptimizeIf(not_zero, instr, Deoptimizer::kLostPrecision); 1383 DeoptimizeIf(not_zero, instr, "lost precision");
1384 } 1384 }
1385 } 1385 }
1386 1386
1387 1387
1388 void LCodeGen::DoMulI(LMulI* instr) { 1388 void LCodeGen::DoMulI(LMulI* instr) {
1389 Register left = ToRegister(instr->left()); 1389 Register left = ToRegister(instr->left());
1390 LOperand* right = instr->right(); 1390 LOperand* right = instr->right();
1391 1391
1392 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 1392 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
1393 if (instr->hydrogen_value()->representation().IsSmi()) { 1393 if (instr->hydrogen_value()->representation().IsSmi()) {
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
1450 } else { 1450 } else {
1451 if (instr->hydrogen_value()->representation().IsSmi()) { 1451 if (instr->hydrogen_value()->representation().IsSmi()) {
1452 __ SmiToInteger64(left, left); 1452 __ SmiToInteger64(left, left);
1453 __ imulp(left, ToRegister(right)); 1453 __ imulp(left, ToRegister(right));
1454 } else { 1454 } else {
1455 __ imull(left, ToRegister(right)); 1455 __ imull(left, ToRegister(right));
1456 } 1456 }
1457 } 1457 }
1458 1458
1459 if (can_overflow) { 1459 if (can_overflow) {
1460 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow); 1460 DeoptimizeIf(overflow, instr, "overflow");
1461 } 1461 }
1462 1462
1463 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 1463 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
1464 // Bail out if the result is supposed to be negative zero. 1464 // Bail out if the result is supposed to be negative zero.
1465 Label done; 1465 Label done;
1466 if (instr->hydrogen_value()->representation().IsSmi()) { 1466 if (instr->hydrogen_value()->representation().IsSmi()) {
1467 __ testp(left, left); 1467 __ testp(left, left);
1468 } else { 1468 } else {
1469 __ testl(left, left); 1469 __ testl(left, left);
1470 } 1470 }
1471 __ j(not_zero, &done, Label::kNear); 1471 __ j(not_zero, &done, Label::kNear);
1472 if (right->IsConstantOperand()) { 1472 if (right->IsConstantOperand()) {
1473 // Constant can't be represented as 32-bit Smi due to immediate size 1473 // Constant can't be represented as 32-bit Smi due to immediate size
1474 // limit. 1474 // limit.
1475 DCHECK(SmiValuesAre32Bits() 1475 DCHECK(SmiValuesAre32Bits()
1476 ? !instr->hydrogen_value()->representation().IsSmi() 1476 ? !instr->hydrogen_value()->representation().IsSmi()
1477 : SmiValuesAre31Bits()); 1477 : SmiValuesAre31Bits());
1478 if (ToInteger32(LConstantOperand::cast(right)) < 0) { 1478 if (ToInteger32(LConstantOperand::cast(right)) < 0) {
1479 DeoptimizeIf(no_condition, instr, Deoptimizer::kMinusZero); 1479 DeoptimizeIf(no_condition, instr, "minus zero");
1480 } else if (ToInteger32(LConstantOperand::cast(right)) == 0) { 1480 } else if (ToInteger32(LConstantOperand::cast(right)) == 0) {
1481 __ cmpl(kScratchRegister, Immediate(0)); 1481 __ cmpl(kScratchRegister, Immediate(0));
1482 DeoptimizeIf(less, instr, Deoptimizer::kMinusZero); 1482 DeoptimizeIf(less, instr, "minus zero");
1483 } 1483 }
1484 } else if (right->IsStackSlot()) { 1484 } else if (right->IsStackSlot()) {
1485 if (instr->hydrogen_value()->representation().IsSmi()) { 1485 if (instr->hydrogen_value()->representation().IsSmi()) {
1486 __ orp(kScratchRegister, ToOperand(right)); 1486 __ orp(kScratchRegister, ToOperand(right));
1487 } else { 1487 } else {
1488 __ orl(kScratchRegister, ToOperand(right)); 1488 __ orl(kScratchRegister, ToOperand(right));
1489 } 1489 }
1490 DeoptimizeIf(sign, instr, Deoptimizer::kMinusZero); 1490 DeoptimizeIf(sign, instr, "minus zero");
1491 } else { 1491 } else {
1492 // Test the non-zero operand for negative sign. 1492 // Test the non-zero operand for negative sign.
1493 if (instr->hydrogen_value()->representation().IsSmi()) { 1493 if (instr->hydrogen_value()->representation().IsSmi()) {
1494 __ orp(kScratchRegister, ToRegister(right)); 1494 __ orp(kScratchRegister, ToRegister(right));
1495 } else { 1495 } else {
1496 __ orl(kScratchRegister, ToRegister(right)); 1496 __ orl(kScratchRegister, ToRegister(right));
1497 } 1497 }
1498 DeoptimizeIf(sign, instr, Deoptimizer::kMinusZero); 1498 DeoptimizeIf(sign, instr, "minus zero");
1499 } 1499 }
1500 __ bind(&done); 1500 __ bind(&done);
1501 } 1501 }
1502 } 1502 }
1503 1503
1504 1504
1505 void LCodeGen::DoBitI(LBitI* instr) { 1505 void LCodeGen::DoBitI(LBitI* instr) {
1506 LOperand* left = instr->left(); 1506 LOperand* left = instr->left();
1507 LOperand* right = instr->right(); 1507 LOperand* right = instr->right();
1508 DCHECK(left->Equals(instr->result())); 1508 DCHECK(left->Equals(instr->result()));
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
1601 case Token::ROR: 1601 case Token::ROR:
1602 __ rorl_cl(ToRegister(left)); 1602 __ rorl_cl(ToRegister(left));
1603 break; 1603 break;
1604 case Token::SAR: 1604 case Token::SAR:
1605 __ sarl_cl(ToRegister(left)); 1605 __ sarl_cl(ToRegister(left));
1606 break; 1606 break;
1607 case Token::SHR: 1607 case Token::SHR:
1608 __ shrl_cl(ToRegister(left)); 1608 __ shrl_cl(ToRegister(left));
1609 if (instr->can_deopt()) { 1609 if (instr->can_deopt()) {
1610 __ testl(ToRegister(left), ToRegister(left)); 1610 __ testl(ToRegister(left), ToRegister(left));
1611 DeoptimizeIf(negative, instr, Deoptimizer::kNegativeValue); 1611 DeoptimizeIf(negative, instr, "negative value");
1612 } 1612 }
1613 break; 1613 break;
1614 case Token::SHL: 1614 case Token::SHL:
1615 __ shll_cl(ToRegister(left)); 1615 __ shll_cl(ToRegister(left));
1616 break; 1616 break;
1617 default: 1617 default:
1618 UNREACHABLE(); 1618 UNREACHABLE();
1619 break; 1619 break;
1620 } 1620 }
1621 } else { 1621 } else {
1622 int32_t value = ToInteger32(LConstantOperand::cast(right)); 1622 int32_t value = ToInteger32(LConstantOperand::cast(right));
1623 uint8_t shift_count = static_cast<uint8_t>(value & 0x1F); 1623 uint8_t shift_count = static_cast<uint8_t>(value & 0x1F);
1624 switch (instr->op()) { 1624 switch (instr->op()) {
1625 case Token::ROR: 1625 case Token::ROR:
1626 if (shift_count != 0) { 1626 if (shift_count != 0) {
1627 __ rorl(ToRegister(left), Immediate(shift_count)); 1627 __ rorl(ToRegister(left), Immediate(shift_count));
1628 } 1628 }
1629 break; 1629 break;
1630 case Token::SAR: 1630 case Token::SAR:
1631 if (shift_count != 0) { 1631 if (shift_count != 0) {
1632 __ sarl(ToRegister(left), Immediate(shift_count)); 1632 __ sarl(ToRegister(left), Immediate(shift_count));
1633 } 1633 }
1634 break; 1634 break;
1635 case Token::SHR: 1635 case Token::SHR:
1636 if (shift_count != 0) { 1636 if (shift_count != 0) {
1637 __ shrl(ToRegister(left), Immediate(shift_count)); 1637 __ shrl(ToRegister(left), Immediate(shift_count));
1638 } else if (instr->can_deopt()) { 1638 } else if (instr->can_deopt()) {
1639 __ testl(ToRegister(left), ToRegister(left)); 1639 __ testl(ToRegister(left), ToRegister(left));
1640 DeoptimizeIf(negative, instr, Deoptimizer::kNegativeValue); 1640 DeoptimizeIf(negative, instr, "negative value");
1641 } 1641 }
1642 break; 1642 break;
1643 case Token::SHL: 1643 case Token::SHL:
1644 if (shift_count != 0) { 1644 if (shift_count != 0) {
1645 if (instr->hydrogen_value()->representation().IsSmi()) { 1645 if (instr->hydrogen_value()->representation().IsSmi()) {
1646 if (SmiValuesAre32Bits()) { 1646 if (SmiValuesAre32Bits()) {
1647 __ shlp(ToRegister(left), Immediate(shift_count)); 1647 __ shlp(ToRegister(left), Immediate(shift_count));
1648 } else { 1648 } else {
1649 DCHECK(SmiValuesAre31Bits()); 1649 DCHECK(SmiValuesAre31Bits());
1650 if (instr->can_deopt()) { 1650 if (instr->can_deopt()) {
1651 if (shift_count != 1) { 1651 if (shift_count != 1) {
1652 __ shll(ToRegister(left), Immediate(shift_count - 1)); 1652 __ shll(ToRegister(left), Immediate(shift_count - 1));
1653 } 1653 }
1654 __ Integer32ToSmi(ToRegister(left), ToRegister(left)); 1654 __ Integer32ToSmi(ToRegister(left), ToRegister(left));
1655 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow); 1655 DeoptimizeIf(overflow, instr, "overflow");
1656 } else { 1656 } else {
1657 __ shll(ToRegister(left), Immediate(shift_count)); 1657 __ shll(ToRegister(left), Immediate(shift_count));
1658 } 1658 }
1659 } 1659 }
1660 } else { 1660 } else {
1661 __ shll(ToRegister(left), Immediate(shift_count)); 1661 __ shll(ToRegister(left), Immediate(shift_count));
1662 } 1662 }
1663 } 1663 }
1664 break; 1664 break;
1665 default: 1665 default:
(...skipping 22 matching lines...) Expand all
1688 } 1688 }
1689 } else { 1689 } else {
1690 if (instr->hydrogen_value()->representation().IsSmi()) { 1690 if (instr->hydrogen_value()->representation().IsSmi()) {
1691 __ subp(ToRegister(left), ToOperand(right)); 1691 __ subp(ToRegister(left), ToOperand(right));
1692 } else { 1692 } else {
1693 __ subl(ToRegister(left), ToOperand(right)); 1693 __ subl(ToRegister(left), ToOperand(right));
1694 } 1694 }
1695 } 1695 }
1696 1696
1697 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { 1697 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
1698 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow); 1698 DeoptimizeIf(overflow, instr, "overflow");
1699 } 1699 }
1700 } 1700 }
1701 1701
1702 1702
1703 void LCodeGen::DoConstantI(LConstantI* instr) { 1703 void LCodeGen::DoConstantI(LConstantI* instr) {
1704 Register dst = ToRegister(instr->result()); 1704 Register dst = ToRegister(instr->result());
1705 if (instr->value() == 0) { 1705 if (instr->value() == 0) {
1706 __ xorl(dst, dst); 1706 __ xorl(dst, dst);
1707 } else { 1707 } else {
1708 __ movl(dst, Immediate(instr->value())); 1708 __ movl(dst, Immediate(instr->value()));
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1741 1741
1742 void LCodeGen::DoDateField(LDateField* instr) { 1742 void LCodeGen::DoDateField(LDateField* instr) {
1743 Register object = ToRegister(instr->date()); 1743 Register object = ToRegister(instr->date());
1744 Register result = ToRegister(instr->result()); 1744 Register result = ToRegister(instr->result());
1745 Smi* index = instr->index(); 1745 Smi* index = instr->index();
1746 Label runtime, done, not_date_object; 1746 Label runtime, done, not_date_object;
1747 DCHECK(object.is(result)); 1747 DCHECK(object.is(result));
1748 DCHECK(object.is(rax)); 1748 DCHECK(object.is(rax));
1749 1749
1750 Condition cc = masm()->CheckSmi(object); 1750 Condition cc = masm()->CheckSmi(object);
1751 DeoptimizeIf(cc, instr, Deoptimizer::kSmi); 1751 DeoptimizeIf(cc, instr, "Smi");
1752 __ CmpObjectType(object, JS_DATE_TYPE, kScratchRegister); 1752 __ CmpObjectType(object, JS_DATE_TYPE, kScratchRegister);
1753 DeoptimizeIf(not_equal, instr, Deoptimizer::kNotADateObject); 1753 DeoptimizeIf(not_equal, instr, "not a date object");
1754 1754
1755 if (index->value() == 0) { 1755 if (index->value() == 0) {
1756 __ movp(result, FieldOperand(object, JSDate::kValueOffset)); 1756 __ movp(result, FieldOperand(object, JSDate::kValueOffset));
1757 } else { 1757 } else {
1758 if (index->value() < JSDate::kFirstUncachedField) { 1758 if (index->value() < JSDate::kFirstUncachedField) {
1759 ExternalReference stamp = ExternalReference::date_cache_stamp(isolate()); 1759 ExternalReference stamp = ExternalReference::date_cache_stamp(isolate());
1760 Operand stamp_operand = __ ExternalOperand(stamp); 1760 Operand stamp_operand = __ ExternalOperand(stamp);
1761 __ movp(kScratchRegister, stamp_operand); 1761 __ movp(kScratchRegister, stamp_operand);
1762 __ cmpp(kScratchRegister, FieldOperand(object, 1762 __ cmpp(kScratchRegister, FieldOperand(object,
1763 JSDate::kCacheStampOffset)); 1763 JSDate::kCacheStampOffset));
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
1907 __ addl(ToRegister(left), ToRegister(right)); 1907 __ addl(ToRegister(left), ToRegister(right));
1908 } 1908 }
1909 } else { 1909 } else {
1910 if (is_p) { 1910 if (is_p) {
1911 __ addp(ToRegister(left), ToOperand(right)); 1911 __ addp(ToRegister(left), ToOperand(right));
1912 } else { 1912 } else {
1913 __ addl(ToRegister(left), ToOperand(right)); 1913 __ addl(ToRegister(left), ToOperand(right));
1914 } 1914 }
1915 } 1915 }
1916 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { 1916 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) {
1917 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow); 1917 DeoptimizeIf(overflow, instr, "overflow");
1918 } 1918 }
1919 } 1919 }
1920 } 1920 }
1921 1921
1922 1922
1923 void LCodeGen::DoMathMinMax(LMathMinMax* instr) { 1923 void LCodeGen::DoMathMinMax(LMathMinMax* instr) {
1924 LOperand* left = instr->left(); 1924 LOperand* left = instr->left();
1925 LOperand* right = instr->right(); 1925 LOperand* right = instr->right();
1926 DCHECK(left->Equals(instr->result())); 1926 DCHECK(left->Equals(instr->result()));
1927 HMathMinMax::Operation operation = instr->hydrogen()->operation(); 1927 HMathMinMax::Operation operation = instr->hydrogen()->operation();
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after
2174 } 2174 }
2175 2175
2176 if (expected.Contains(ToBooleanStub::SMI)) { 2176 if (expected.Contains(ToBooleanStub::SMI)) {
2177 // Smis: 0 -> false, all other -> true. 2177 // Smis: 0 -> false, all other -> true.
2178 __ Cmp(reg, Smi::FromInt(0)); 2178 __ Cmp(reg, Smi::FromInt(0));
2179 __ j(equal, instr->FalseLabel(chunk_)); 2179 __ j(equal, instr->FalseLabel(chunk_));
2180 __ JumpIfSmi(reg, instr->TrueLabel(chunk_)); 2180 __ JumpIfSmi(reg, instr->TrueLabel(chunk_));
2181 } else if (expected.NeedsMap()) { 2181 } else if (expected.NeedsMap()) {
2182 // If we need a map later and have a Smi -> deopt. 2182 // If we need a map later and have a Smi -> deopt.
2183 __ testb(reg, Immediate(kSmiTagMask)); 2183 __ testb(reg, Immediate(kSmiTagMask));
2184 DeoptimizeIf(zero, instr, Deoptimizer::kSmi); 2184 DeoptimizeIf(zero, instr, "Smi");
2185 } 2185 }
2186 2186
2187 const Register map = kScratchRegister; 2187 const Register map = kScratchRegister;
2188 if (expected.NeedsMap()) { 2188 if (expected.NeedsMap()) {
2189 __ movp(map, FieldOperand(reg, HeapObject::kMapOffset)); 2189 __ movp(map, FieldOperand(reg, HeapObject::kMapOffset));
2190 2190
2191 if (expected.CanBeUndetectable()) { 2191 if (expected.CanBeUndetectable()) {
2192 // Undetectable -> false. 2192 // Undetectable -> false.
2193 __ testb(FieldOperand(map, Map::kBitFieldOffset), 2193 __ testb(FieldOperand(map, Map::kBitFieldOffset),
2194 Immediate(1 << Map::kIsUndetectable)); 2194 Immediate(1 << Map::kIsUndetectable));
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
2228 __ xorps(xmm_scratch, xmm_scratch); 2228 __ xorps(xmm_scratch, xmm_scratch);
2229 __ ucomisd(xmm_scratch, FieldOperand(reg, HeapNumber::kValueOffset)); 2229 __ ucomisd(xmm_scratch, FieldOperand(reg, HeapNumber::kValueOffset));
2230 __ j(zero, instr->FalseLabel(chunk_)); 2230 __ j(zero, instr->FalseLabel(chunk_));
2231 __ jmp(instr->TrueLabel(chunk_)); 2231 __ jmp(instr->TrueLabel(chunk_));
2232 __ bind(&not_heap_number); 2232 __ bind(&not_heap_number);
2233 } 2233 }
2234 2234
2235 if (!expected.IsGeneric()) { 2235 if (!expected.IsGeneric()) {
2236 // We've seen something for the first time -> deopt. 2236 // We've seen something for the first time -> deopt.
2237 // This can only happen if we are not generic already. 2237 // This can only happen if we are not generic already.
2238 DeoptimizeIf(no_condition, instr, Deoptimizer::kUnexpectedObject); 2238 DeoptimizeIf(no_condition, instr, "unexpected object");
2239 } 2239 }
2240 } 2240 }
2241 } 2241 }
2242 } 2242 }
2243 2243
2244 2244
2245 void LCodeGen::EmitGoto(int block) { 2245 void LCodeGen::EmitGoto(int block) {
2246 if (!IsNextEmittedBlock(block)) { 2246 if (!IsNextEmittedBlock(block)) {
2247 __ jmp(chunk_->GetAssemblyLabel(chunk_->LookupDestination(block))); 2247 __ jmp(chunk_->GetAssemblyLabel(chunk_->LookupDestination(block)));
2248 } 2248 }
(...skipping 596 matching lines...) Expand 10 before | Expand all | Expand 10 after
2845 info_->AddNoFrameRange(no_frame_start, masm_->pc_offset()); 2845 info_->AddNoFrameRange(no_frame_start, masm_->pc_offset());
2846 } 2846 }
2847 } 2847 }
2848 2848
2849 2849
2850 void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) { 2850 void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) {
2851 Register result = ToRegister(instr->result()); 2851 Register result = ToRegister(instr->result());
2852 __ LoadGlobalCell(result, instr->hydrogen()->cell().handle()); 2852 __ LoadGlobalCell(result, instr->hydrogen()->cell().handle());
2853 if (instr->hydrogen()->RequiresHoleCheck()) { 2853 if (instr->hydrogen()->RequiresHoleCheck()) {
2854 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); 2854 __ CompareRoot(result, Heap::kTheHoleValueRootIndex);
2855 DeoptimizeIf(equal, instr, Deoptimizer::kHole); 2855 DeoptimizeIf(equal, instr, "hole");
2856 } 2856 }
2857 } 2857 }
2858 2858
2859 2859
2860 template <class T> 2860 template <class T>
2861 void LCodeGen::EmitVectorLoadICRegisters(T* instr) { 2861 void LCodeGen::EmitVectorLoadICRegisters(T* instr) {
2862 DCHECK(FLAG_vector_ics); 2862 DCHECK(FLAG_vector_ics);
2863 Register vector_register = ToRegister(instr->temp_vector()); 2863 Register vector_register = ToRegister(instr->temp_vector());
2864 Register slot_register = VectorLoadICDescriptor::SlotRegister(); 2864 Register slot_register = VectorLoadICDescriptor::SlotRegister();
2865 DCHECK(vector_register.is(VectorLoadICDescriptor::VectorRegister())); 2865 DCHECK(vector_register.is(VectorLoadICDescriptor::VectorRegister()));
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
2898 // If the cell we are storing to contains the hole it could have 2898 // If the cell we are storing to contains the hole it could have
2899 // been deleted from the property dictionary. In that case, we need 2899 // been deleted from the property dictionary. In that case, we need
2900 // to update the property details in the property dictionary to mark 2900 // to update the property details in the property dictionary to mark
2901 // it as no longer deleted. We deoptimize in that case. 2901 // it as no longer deleted. We deoptimize in that case.
2902 if (instr->hydrogen()->RequiresHoleCheck()) { 2902 if (instr->hydrogen()->RequiresHoleCheck()) {
2903 // We have a temp because CompareRoot might clobber kScratchRegister. 2903 // We have a temp because CompareRoot might clobber kScratchRegister.
2904 Register cell = ToRegister(instr->temp()); 2904 Register cell = ToRegister(instr->temp());
2905 DCHECK(!value.is(cell)); 2905 DCHECK(!value.is(cell));
2906 __ Move(cell, cell_handle, RelocInfo::CELL); 2906 __ Move(cell, cell_handle, RelocInfo::CELL);
2907 __ CompareRoot(Operand(cell, 0), Heap::kTheHoleValueRootIndex); 2907 __ CompareRoot(Operand(cell, 0), Heap::kTheHoleValueRootIndex);
2908 DeoptimizeIf(equal, instr, Deoptimizer::kHole); 2908 DeoptimizeIf(equal, instr, "hole");
2909 // Store the value. 2909 // Store the value.
2910 __ movp(Operand(cell, 0), value); 2910 __ movp(Operand(cell, 0), value);
2911 } else { 2911 } else {
2912 // Store the value. 2912 // Store the value.
2913 __ Move(kScratchRegister, cell_handle, RelocInfo::CELL); 2913 __ Move(kScratchRegister, cell_handle, RelocInfo::CELL);
2914 __ movp(Operand(kScratchRegister, 0), value); 2914 __ movp(Operand(kScratchRegister, 0), value);
2915 } 2915 }
2916 // Cells are always rescanned, so no write barrier here. 2916 // Cells are always rescanned, so no write barrier here.
2917 } 2917 }
2918 2918
2919 2919
2920 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { 2920 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) {
2921 Register context = ToRegister(instr->context()); 2921 Register context = ToRegister(instr->context());
2922 Register result = ToRegister(instr->result()); 2922 Register result = ToRegister(instr->result());
2923 __ movp(result, ContextOperand(context, instr->slot_index())); 2923 __ movp(result, ContextOperand(context, instr->slot_index()));
2924 if (instr->hydrogen()->RequiresHoleCheck()) { 2924 if (instr->hydrogen()->RequiresHoleCheck()) {
2925 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); 2925 __ CompareRoot(result, Heap::kTheHoleValueRootIndex);
2926 if (instr->hydrogen()->DeoptimizesOnHole()) { 2926 if (instr->hydrogen()->DeoptimizesOnHole()) {
2927 DeoptimizeIf(equal, instr, Deoptimizer::kHole); 2927 DeoptimizeIf(equal, instr, "hole");
2928 } else { 2928 } else {
2929 Label is_not_hole; 2929 Label is_not_hole;
2930 __ j(not_equal, &is_not_hole, Label::kNear); 2930 __ j(not_equal, &is_not_hole, Label::kNear);
2931 __ LoadRoot(result, Heap::kUndefinedValueRootIndex); 2931 __ LoadRoot(result, Heap::kUndefinedValueRootIndex);
2932 __ bind(&is_not_hole); 2932 __ bind(&is_not_hole);
2933 } 2933 }
2934 } 2934 }
2935 } 2935 }
2936 2936
2937 2937
2938 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) { 2938 void LCodeGen::DoStoreContextSlot(LStoreContextSlot* instr) {
2939 Register context = ToRegister(instr->context()); 2939 Register context = ToRegister(instr->context());
2940 Register value = ToRegister(instr->value()); 2940 Register value = ToRegister(instr->value());
2941 2941
2942 Operand target = ContextOperand(context, instr->slot_index()); 2942 Operand target = ContextOperand(context, instr->slot_index());
2943 2943
2944 Label skip_assignment; 2944 Label skip_assignment;
2945 if (instr->hydrogen()->RequiresHoleCheck()) { 2945 if (instr->hydrogen()->RequiresHoleCheck()) {
2946 __ CompareRoot(target, Heap::kTheHoleValueRootIndex); 2946 __ CompareRoot(target, Heap::kTheHoleValueRootIndex);
2947 if (instr->hydrogen()->DeoptimizesOnHole()) { 2947 if (instr->hydrogen()->DeoptimizesOnHole()) {
2948 DeoptimizeIf(equal, instr, Deoptimizer::kHole); 2948 DeoptimizeIf(equal, instr, "hole");
2949 } else { 2949 } else {
2950 __ j(not_equal, &skip_assignment); 2950 __ j(not_equal, &skip_assignment);
2951 } 2951 }
2952 } 2952 }
2953 __ movp(target, value); 2953 __ movp(target, value);
2954 2954
2955 if (instr->hydrogen()->NeedsWriteBarrier()) { 2955 if (instr->hydrogen()->NeedsWriteBarrier()) {
2956 SmiCheck check_needed = 2956 SmiCheck check_needed =
2957 instr->hydrogen()->value()->type().IsHeapObject() 2957 instr->hydrogen()->value()->type().IsHeapObject()
2958 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; 2958 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
3038 void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { 3038 void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) {
3039 Register function = ToRegister(instr->function()); 3039 Register function = ToRegister(instr->function());
3040 Register result = ToRegister(instr->result()); 3040 Register result = ToRegister(instr->result());
3041 3041
3042 // Get the prototype or initial map from the function. 3042 // Get the prototype or initial map from the function.
3043 __ movp(result, 3043 __ movp(result,
3044 FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset)); 3044 FieldOperand(function, JSFunction::kPrototypeOrInitialMapOffset));
3045 3045
3046 // Check that the function has a prototype or an initial map. 3046 // Check that the function has a prototype or an initial map.
3047 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); 3047 __ CompareRoot(result, Heap::kTheHoleValueRootIndex);
3048 DeoptimizeIf(equal, instr, Deoptimizer::kHole); 3048 DeoptimizeIf(equal, instr, "hole");
3049 3049
3050 // If the function does not have an initial map, we're done. 3050 // If the function does not have an initial map, we're done.
3051 Label done; 3051 Label done;
3052 __ CmpObjectType(result, MAP_TYPE, kScratchRegister); 3052 __ CmpObjectType(result, MAP_TYPE, kScratchRegister);
3053 __ j(not_equal, &done, Label::kNear); 3053 __ j(not_equal, &done, Label::kNear);
3054 3054
3055 // Get the prototype from the initial map. 3055 // Get the prototype from the initial map.
3056 __ movp(result, FieldOperand(result, Map::kPrototypeOffset)); 3056 __ movp(result, FieldOperand(result, Map::kPrototypeOffset));
3057 3057
3058 // All done. 3058 // All done.
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
3150 break; 3150 break;
3151 case EXTERNAL_INT32_ELEMENTS: 3151 case EXTERNAL_INT32_ELEMENTS:
3152 case INT32_ELEMENTS: 3152 case INT32_ELEMENTS:
3153 __ movl(result, operand); 3153 __ movl(result, operand);
3154 break; 3154 break;
3155 case EXTERNAL_UINT32_ELEMENTS: 3155 case EXTERNAL_UINT32_ELEMENTS:
3156 case UINT32_ELEMENTS: 3156 case UINT32_ELEMENTS:
3157 __ movl(result, operand); 3157 __ movl(result, operand);
3158 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) { 3158 if (!instr->hydrogen()->CheckFlag(HInstruction::kUint32)) {
3159 __ testl(result, result); 3159 __ testl(result, result);
3160 DeoptimizeIf(negative, instr, Deoptimizer::kNegativeValue); 3160 DeoptimizeIf(negative, instr, "negative value");
3161 } 3161 }
3162 break; 3162 break;
3163 case EXTERNAL_FLOAT32_ELEMENTS: 3163 case EXTERNAL_FLOAT32_ELEMENTS:
3164 case EXTERNAL_FLOAT64_ELEMENTS: 3164 case EXTERNAL_FLOAT64_ELEMENTS:
3165 case FLOAT32_ELEMENTS: 3165 case FLOAT32_ELEMENTS:
3166 case FLOAT64_ELEMENTS: 3166 case FLOAT64_ELEMENTS:
3167 case FAST_ELEMENTS: 3167 case FAST_ELEMENTS:
3168 case FAST_SMI_ELEMENTS: 3168 case FAST_SMI_ELEMENTS:
3169 case FAST_DOUBLE_ELEMENTS: 3169 case FAST_DOUBLE_ELEMENTS:
3170 case FAST_HOLEY_ELEMENTS: 3170 case FAST_HOLEY_ELEMENTS:
(...skipping 18 matching lines...) Expand all
3189 __ movsxlq(ToRegister(key), ToRegister(key)); 3189 __ movsxlq(ToRegister(key), ToRegister(key));
3190 } 3190 }
3191 if (instr->hydrogen()->RequiresHoleCheck()) { 3191 if (instr->hydrogen()->RequiresHoleCheck()) {
3192 Operand hole_check_operand = BuildFastArrayOperand( 3192 Operand hole_check_operand = BuildFastArrayOperand(
3193 instr->elements(), 3193 instr->elements(),
3194 key, 3194 key,
3195 instr->hydrogen()->key()->representation(), 3195 instr->hydrogen()->key()->representation(),
3196 FAST_DOUBLE_ELEMENTS, 3196 FAST_DOUBLE_ELEMENTS,
3197 instr->base_offset() + sizeof(kHoleNanLower32)); 3197 instr->base_offset() + sizeof(kHoleNanLower32));
3198 __ cmpl(hole_check_operand, Immediate(kHoleNanUpper32)); 3198 __ cmpl(hole_check_operand, Immediate(kHoleNanUpper32));
3199 DeoptimizeIf(equal, instr, Deoptimizer::kHole); 3199 DeoptimizeIf(equal, instr, "hole");
3200 } 3200 }
3201 3201
3202 Operand double_load_operand = BuildFastArrayOperand( 3202 Operand double_load_operand = BuildFastArrayOperand(
3203 instr->elements(), 3203 instr->elements(),
3204 key, 3204 key,
3205 instr->hydrogen()->key()->representation(), 3205 instr->hydrogen()->key()->representation(),
3206 FAST_DOUBLE_ELEMENTS, 3206 FAST_DOUBLE_ELEMENTS,
3207 instr->base_offset()); 3207 instr->base_offset());
3208 __ movsd(result, double_load_operand); 3208 __ movsd(result, double_load_operand);
3209 } 3209 }
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
3246 __ Load(result, 3246 __ Load(result,
3247 BuildFastArrayOperand(instr->elements(), key, 3247 BuildFastArrayOperand(instr->elements(), key,
3248 instr->hydrogen()->key()->representation(), 3248 instr->hydrogen()->key()->representation(),
3249 FAST_ELEMENTS, offset), 3249 FAST_ELEMENTS, offset),
3250 representation); 3250 representation);
3251 3251
3252 // Check for the hole value. 3252 // Check for the hole value.
3253 if (requires_hole_check) { 3253 if (requires_hole_check) {
3254 if (IsFastSmiElementsKind(hinstr->elements_kind())) { 3254 if (IsFastSmiElementsKind(hinstr->elements_kind())) {
3255 Condition smi = __ CheckSmi(result); 3255 Condition smi = __ CheckSmi(result);
3256 DeoptimizeIf(NegateCondition(smi), instr, Deoptimizer::kNotASmi); 3256 DeoptimizeIf(NegateCondition(smi), instr, "not a Smi");
3257 } else { 3257 } else {
3258 __ CompareRoot(result, Heap::kTheHoleValueRootIndex); 3258 __ CompareRoot(result, Heap::kTheHoleValueRootIndex);
3259 DeoptimizeIf(equal, instr, Deoptimizer::kHole); 3259 DeoptimizeIf(equal, instr, "hole");
3260 } 3260 }
3261 } 3261 }
3262 } 3262 }
3263 3263
3264 3264
3265 void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) { 3265 void LCodeGen::DoLoadKeyed(LLoadKeyed* instr) {
3266 if (instr->is_typed_elements()) { 3266 if (instr->is_typed_elements()) {
3267 DoLoadKeyedExternalArray(instr); 3267 DoLoadKeyedExternalArray(instr);
3268 } else if (instr->hydrogen()->representation().IsDouble()) { 3268 } else if (instr->hydrogen()->representation().IsDouble()) {
3269 DoLoadKeyedFixedDoubleArray(instr); 3269 DoLoadKeyedFixedDoubleArray(instr);
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
3396 } 3396 }
3397 3397
3398 // Normal function. Replace undefined or null with global receiver. 3398 // Normal function. Replace undefined or null with global receiver.
3399 __ CompareRoot(receiver, Heap::kNullValueRootIndex); 3399 __ CompareRoot(receiver, Heap::kNullValueRootIndex);
3400 __ j(equal, &global_object, Label::kNear); 3400 __ j(equal, &global_object, Label::kNear);
3401 __ CompareRoot(receiver, Heap::kUndefinedValueRootIndex); 3401 __ CompareRoot(receiver, Heap::kUndefinedValueRootIndex);
3402 __ j(equal, &global_object, Label::kNear); 3402 __ j(equal, &global_object, Label::kNear);
3403 3403
3404 // The receiver should be a JS object. 3404 // The receiver should be a JS object.
3405 Condition is_smi = __ CheckSmi(receiver); 3405 Condition is_smi = __ CheckSmi(receiver);
3406 DeoptimizeIf(is_smi, instr, Deoptimizer::kSmi); 3406 DeoptimizeIf(is_smi, instr, "Smi");
3407 __ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, kScratchRegister); 3407 __ CmpObjectType(receiver, FIRST_SPEC_OBJECT_TYPE, kScratchRegister);
3408 DeoptimizeIf(below, instr, Deoptimizer::kNotAJavaScriptObject); 3408 DeoptimizeIf(below, instr, "not a JavaScript object");
3409 3409
3410 __ jmp(&receiver_ok, Label::kNear); 3410 __ jmp(&receiver_ok, Label::kNear);
3411 __ bind(&global_object); 3411 __ bind(&global_object);
3412 __ movp(receiver, FieldOperand(function, JSFunction::kContextOffset)); 3412 __ movp(receiver, FieldOperand(function, JSFunction::kContextOffset));
3413 __ movp(receiver, 3413 __ movp(receiver,
3414 Operand(receiver, 3414 Operand(receiver,
3415 Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); 3415 Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX)));
3416 __ movp(receiver, FieldOperand(receiver, GlobalObject::kGlobalProxyOffset)); 3416 __ movp(receiver, FieldOperand(receiver, GlobalObject::kGlobalProxyOffset));
3417 3417
3418 __ bind(&receiver_ok); 3418 __ bind(&receiver_ok);
3419 } 3419 }
3420 3420
3421 3421
3422 void LCodeGen::DoApplyArguments(LApplyArguments* instr) { 3422 void LCodeGen::DoApplyArguments(LApplyArguments* instr) {
3423 Register receiver = ToRegister(instr->receiver()); 3423 Register receiver = ToRegister(instr->receiver());
3424 Register function = ToRegister(instr->function()); 3424 Register function = ToRegister(instr->function());
3425 Register length = ToRegister(instr->length()); 3425 Register length = ToRegister(instr->length());
3426 Register elements = ToRegister(instr->elements()); 3426 Register elements = ToRegister(instr->elements());
3427 DCHECK(receiver.is(rax)); // Used for parameter count. 3427 DCHECK(receiver.is(rax)); // Used for parameter count.
3428 DCHECK(function.is(rdi)); // Required by InvokeFunction. 3428 DCHECK(function.is(rdi)); // Required by InvokeFunction.
3429 DCHECK(ToRegister(instr->result()).is(rax)); 3429 DCHECK(ToRegister(instr->result()).is(rax));
3430 3430
3431 // Copy the arguments to this function possibly from the 3431 // Copy the arguments to this function possibly from the
3432 // adaptor frame below it. 3432 // adaptor frame below it.
3433 const uint32_t kArgumentsLimit = 1 * KB; 3433 const uint32_t kArgumentsLimit = 1 * KB;
3434 __ cmpp(length, Immediate(kArgumentsLimit)); 3434 __ cmpp(length, Immediate(kArgumentsLimit));
3435 DeoptimizeIf(above, instr, Deoptimizer::kTooManyArguments); 3435 DeoptimizeIf(above, instr, "too many arguments");
3436 3436
3437 __ Push(receiver); 3437 __ Push(receiver);
3438 __ movp(receiver, length); 3438 __ movp(receiver, length);
3439 3439
3440 // Loop through the arguments pushing them onto the execution 3440 // Loop through the arguments pushing them onto the execution
3441 // stack. 3441 // stack.
3442 Label invoke, loop; 3442 Label invoke, loop;
3443 // length is a small non-negative integer, due to the test above. 3443 // length is a small non-negative integer, due to the test above.
3444 __ testl(length, length); 3444 __ testl(length, length);
3445 __ j(zero, &invoke, Label::kNear); 3445 __ j(zero, &invoke, Label::kNear);
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after
3639 __ Call(target); 3639 __ Call(target);
3640 } 3640 }
3641 generator.AfterCall(); 3641 generator.AfterCall();
3642 } 3642 }
3643 3643
3644 3644
3645 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) { 3645 void LCodeGen::DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr) {
3646 Register input_reg = ToRegister(instr->value()); 3646 Register input_reg = ToRegister(instr->value());
3647 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), 3647 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset),
3648 Heap::kHeapNumberMapRootIndex); 3648 Heap::kHeapNumberMapRootIndex);
3649 DeoptimizeIf(not_equal, instr, Deoptimizer::kNotAHeapNumber); 3649 DeoptimizeIf(not_equal, instr, "not a heap number");
3650 3650
3651 Label slow, allocated, done; 3651 Label slow, allocated, done;
3652 Register tmp = input_reg.is(rax) ? rcx : rax; 3652 Register tmp = input_reg.is(rax) ? rcx : rax;
3653 Register tmp2 = tmp.is(rcx) ? rdx : input_reg.is(rcx) ? rdx : rcx; 3653 Register tmp2 = tmp.is(rcx) ? rdx : input_reg.is(rcx) ? rdx : rcx;
3654 3654
3655 // Preserve the value of all registers. 3655 // Preserve the value of all registers.
3656 PushSafepointRegistersScope scope(this); 3656 PushSafepointRegistersScope scope(this);
3657 3657
3658 __ movl(tmp, FieldOperand(input_reg, HeapNumber::kExponentOffset)); 3658 __ movl(tmp, FieldOperand(input_reg, HeapNumber::kExponentOffset));
3659 // Check the sign of the argument. If the argument is positive, just 3659 // Check the sign of the argument. If the argument is positive, just
(...skipping 25 matching lines...) Expand all
3685 __ bind(&done); 3685 __ bind(&done);
3686 } 3686 }
3687 3687
3688 3688
3689 void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) { 3689 void LCodeGen::EmitIntegerMathAbs(LMathAbs* instr) {
3690 Register input_reg = ToRegister(instr->value()); 3690 Register input_reg = ToRegister(instr->value());
3691 __ testl(input_reg, input_reg); 3691 __ testl(input_reg, input_reg);
3692 Label is_positive; 3692 Label is_positive;
3693 __ j(not_sign, &is_positive, Label::kNear); 3693 __ j(not_sign, &is_positive, Label::kNear);
3694 __ negl(input_reg); // Sets flags. 3694 __ negl(input_reg); // Sets flags.
3695 DeoptimizeIf(negative, instr, Deoptimizer::kOverflow); 3695 DeoptimizeIf(negative, instr, "overflow");
3696 __ bind(&is_positive); 3696 __ bind(&is_positive);
3697 } 3697 }
3698 3698
3699 3699
3700 void LCodeGen::EmitSmiMathAbs(LMathAbs* instr) { 3700 void LCodeGen::EmitSmiMathAbs(LMathAbs* instr) {
3701 Register input_reg = ToRegister(instr->value()); 3701 Register input_reg = ToRegister(instr->value());
3702 __ testp(input_reg, input_reg); 3702 __ testp(input_reg, input_reg);
3703 Label is_positive; 3703 Label is_positive;
3704 __ j(not_sign, &is_positive, Label::kNear); 3704 __ j(not_sign, &is_positive, Label::kNear);
3705 __ negp(input_reg); // Sets flags. 3705 __ negp(input_reg); // Sets flags.
3706 DeoptimizeIf(negative, instr, Deoptimizer::kOverflow); 3706 DeoptimizeIf(negative, instr, "overflow");
3707 __ bind(&is_positive); 3707 __ bind(&is_positive);
3708 } 3708 }
3709 3709
3710 3710
3711 void LCodeGen::DoMathAbs(LMathAbs* instr) { 3711 void LCodeGen::DoMathAbs(LMathAbs* instr) {
3712 // Class for deferred case. 3712 // Class for deferred case.
3713 class DeferredMathAbsTaggedHeapNumber FINAL : public LDeferredCode { 3713 class DeferredMathAbsTaggedHeapNumber FINAL : public LDeferredCode {
3714 public: 3714 public:
3715 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, LMathAbs* instr) 3715 DeferredMathAbsTaggedHeapNumber(LCodeGen* codegen, LMathAbs* instr)
3716 : LDeferredCode(codegen), instr_(instr) { } 3716 : LDeferredCode(codegen), instr_(instr) { }
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
3752 XMMRegister xmm_scratch = double_scratch0(); 3752 XMMRegister xmm_scratch = double_scratch0();
3753 Register output_reg = ToRegister(instr->result()); 3753 Register output_reg = ToRegister(instr->result());
3754 XMMRegister input_reg = ToDoubleRegister(instr->value()); 3754 XMMRegister input_reg = ToDoubleRegister(instr->value());
3755 3755
3756 if (CpuFeatures::IsSupported(SSE4_1)) { 3756 if (CpuFeatures::IsSupported(SSE4_1)) {
3757 CpuFeatureScope scope(masm(), SSE4_1); 3757 CpuFeatureScope scope(masm(), SSE4_1);
3758 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 3758 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
3759 // Deoptimize if minus zero. 3759 // Deoptimize if minus zero.
3760 __ movq(output_reg, input_reg); 3760 __ movq(output_reg, input_reg);
3761 __ subq(output_reg, Immediate(1)); 3761 __ subq(output_reg, Immediate(1));
3762 DeoptimizeIf(overflow, instr, Deoptimizer::kMinusZero); 3762 DeoptimizeIf(overflow, instr, "minus zero");
3763 } 3763 }
3764 __ roundsd(xmm_scratch, input_reg, Assembler::kRoundDown); 3764 __ roundsd(xmm_scratch, input_reg, Assembler::kRoundDown);
3765 __ cvttsd2si(output_reg, xmm_scratch); 3765 __ cvttsd2si(output_reg, xmm_scratch);
3766 __ cmpl(output_reg, Immediate(0x1)); 3766 __ cmpl(output_reg, Immediate(0x1));
3767 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow); 3767 DeoptimizeIf(overflow, instr, "overflow");
3768 } else { 3768 } else {
3769 Label negative_sign, done; 3769 Label negative_sign, done;
3770 // Deoptimize on unordered. 3770 // Deoptimize on unordered.
3771 __ xorps(xmm_scratch, xmm_scratch); // Zero the register. 3771 __ xorps(xmm_scratch, xmm_scratch); // Zero the register.
3772 __ ucomisd(input_reg, xmm_scratch); 3772 __ ucomisd(input_reg, xmm_scratch);
3773 DeoptimizeIf(parity_even, instr, Deoptimizer::kNaN); 3773 DeoptimizeIf(parity_even, instr, "NaN");
3774 __ j(below, &negative_sign, Label::kNear); 3774 __ j(below, &negative_sign, Label::kNear);
3775 3775
3776 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 3776 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
3777 // Check for negative zero. 3777 // Check for negative zero.
3778 Label positive_sign; 3778 Label positive_sign;
3779 __ j(above, &positive_sign, Label::kNear); 3779 __ j(above, &positive_sign, Label::kNear);
3780 __ movmskpd(output_reg, input_reg); 3780 __ movmskpd(output_reg, input_reg);
3781 __ testq(output_reg, Immediate(1)); 3781 __ testq(output_reg, Immediate(1));
3782 DeoptimizeIf(not_zero, instr, Deoptimizer::kMinusZero); 3782 DeoptimizeIf(not_zero, instr, "minus zero");
3783 __ Set(output_reg, 0); 3783 __ Set(output_reg, 0);
3784 __ jmp(&done); 3784 __ jmp(&done);
3785 __ bind(&positive_sign); 3785 __ bind(&positive_sign);
3786 } 3786 }
3787 3787
3788 // Use truncating instruction (OK because input is positive). 3788 // Use truncating instruction (OK because input is positive).
3789 __ cvttsd2si(output_reg, input_reg); 3789 __ cvttsd2si(output_reg, input_reg);
3790 // Overflow is signalled with minint. 3790 // Overflow is signalled with minint.
3791 __ cmpl(output_reg, Immediate(0x1)); 3791 __ cmpl(output_reg, Immediate(0x1));
3792 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow); 3792 DeoptimizeIf(overflow, instr, "overflow");
3793 __ jmp(&done, Label::kNear); 3793 __ jmp(&done, Label::kNear);
3794 3794
3795 // Non-zero negative reaches here. 3795 // Non-zero negative reaches here.
3796 __ bind(&negative_sign); 3796 __ bind(&negative_sign);
3797 // Truncate, then compare and compensate. 3797 // Truncate, then compare and compensate.
3798 __ cvttsd2si(output_reg, input_reg); 3798 __ cvttsd2si(output_reg, input_reg);
3799 __ Cvtlsi2sd(xmm_scratch, output_reg); 3799 __ Cvtlsi2sd(xmm_scratch, output_reg);
3800 __ ucomisd(input_reg, xmm_scratch); 3800 __ ucomisd(input_reg, xmm_scratch);
3801 __ j(equal, &done, Label::kNear); 3801 __ j(equal, &done, Label::kNear);
3802 __ subl(output_reg, Immediate(1)); 3802 __ subl(output_reg, Immediate(1));
3803 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow); 3803 DeoptimizeIf(overflow, instr, "overflow");
3804 3804
3805 __ bind(&done); 3805 __ bind(&done);
3806 } 3806 }
3807 } 3807 }
3808 3808
3809 3809
3810 void LCodeGen::DoMathRound(LMathRound* instr) { 3810 void LCodeGen::DoMathRound(LMathRound* instr) {
3811 const XMMRegister xmm_scratch = double_scratch0(); 3811 const XMMRegister xmm_scratch = double_scratch0();
3812 Register output_reg = ToRegister(instr->result()); 3812 Register output_reg = ToRegister(instr->result());
3813 XMMRegister input_reg = ToDoubleRegister(instr->value()); 3813 XMMRegister input_reg = ToDoubleRegister(instr->value());
3814 XMMRegister input_temp = ToDoubleRegister(instr->temp()); 3814 XMMRegister input_temp = ToDoubleRegister(instr->temp());
3815 static int64_t one_half = V8_INT64_C(0x3FE0000000000000); // 0.5 3815 static int64_t one_half = V8_INT64_C(0x3FE0000000000000); // 0.5
3816 static int64_t minus_one_half = V8_INT64_C(0xBFE0000000000000); // -0.5 3816 static int64_t minus_one_half = V8_INT64_C(0xBFE0000000000000); // -0.5
3817 3817
3818 Label done, round_to_zero, below_one_half; 3818 Label done, round_to_zero, below_one_half;
3819 Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear; 3819 Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear;
3820 __ movq(kScratchRegister, one_half); 3820 __ movq(kScratchRegister, one_half);
3821 __ movq(xmm_scratch, kScratchRegister); 3821 __ movq(xmm_scratch, kScratchRegister);
3822 __ ucomisd(xmm_scratch, input_reg); 3822 __ ucomisd(xmm_scratch, input_reg);
3823 __ j(above, &below_one_half, Label::kNear); 3823 __ j(above, &below_one_half, Label::kNear);
3824 3824
3825 // CVTTSD2SI rounds towards zero, since 0.5 <= x, we use floor(0.5 + x). 3825 // CVTTSD2SI rounds towards zero, since 0.5 <= x, we use floor(0.5 + x).
3826 __ addsd(xmm_scratch, input_reg); 3826 __ addsd(xmm_scratch, input_reg);
3827 __ cvttsd2si(output_reg, xmm_scratch); 3827 __ cvttsd2si(output_reg, xmm_scratch);
3828 // Overflow is signalled with minint. 3828 // Overflow is signalled with minint.
3829 __ cmpl(output_reg, Immediate(0x1)); 3829 __ cmpl(output_reg, Immediate(0x1));
3830 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow); 3830 DeoptimizeIf(overflow, instr, "overflow");
3831 __ jmp(&done, dist); 3831 __ jmp(&done, dist);
3832 3832
3833 __ bind(&below_one_half); 3833 __ bind(&below_one_half);
3834 __ movq(kScratchRegister, minus_one_half); 3834 __ movq(kScratchRegister, minus_one_half);
3835 __ movq(xmm_scratch, kScratchRegister); 3835 __ movq(xmm_scratch, kScratchRegister);
3836 __ ucomisd(xmm_scratch, input_reg); 3836 __ ucomisd(xmm_scratch, input_reg);
3837 __ j(below_equal, &round_to_zero, Label::kNear); 3837 __ j(below_equal, &round_to_zero, Label::kNear);
3838 3838
3839 // CVTTSD2SI rounds towards zero, we use ceil(x - (-0.5)) and then 3839 // CVTTSD2SI rounds towards zero, we use ceil(x - (-0.5)) and then
3840 // compare and compensate. 3840 // compare and compensate.
3841 __ movq(input_temp, input_reg); // Do not alter input_reg. 3841 __ movq(input_temp, input_reg); // Do not alter input_reg.
3842 __ subsd(input_temp, xmm_scratch); 3842 __ subsd(input_temp, xmm_scratch);
3843 __ cvttsd2si(output_reg, input_temp); 3843 __ cvttsd2si(output_reg, input_temp);
3844 // Catch minint due to overflow, and to prevent overflow when compensating. 3844 // Catch minint due to overflow, and to prevent overflow when compensating.
3845 __ cmpl(output_reg, Immediate(0x1)); 3845 __ cmpl(output_reg, Immediate(0x1));
3846 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow); 3846 DeoptimizeIf(overflow, instr, "overflow");
3847 3847
3848 __ Cvtlsi2sd(xmm_scratch, output_reg); 3848 __ Cvtlsi2sd(xmm_scratch, output_reg);
3849 __ ucomisd(xmm_scratch, input_temp); 3849 __ ucomisd(xmm_scratch, input_temp);
3850 __ j(equal, &done, dist); 3850 __ j(equal, &done, dist);
3851 __ subl(output_reg, Immediate(1)); 3851 __ subl(output_reg, Immediate(1));
3852 // No overflow because we already ruled out minint. 3852 // No overflow because we already ruled out minint.
3853 __ jmp(&done, dist); 3853 __ jmp(&done, dist);
3854 3854
3855 __ bind(&round_to_zero); 3855 __ bind(&round_to_zero);
3856 // We return 0 for the input range [+0, 0.5[, or [-0.5, 0.5[ if 3856 // We return 0 for the input range [+0, 0.5[, or [-0.5, 0.5[ if
3857 // we can ignore the difference between a result of -0 and +0. 3857 // we can ignore the difference between a result of -0 and +0.
3858 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 3858 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
3859 __ movq(output_reg, input_reg); 3859 __ movq(output_reg, input_reg);
3860 __ testq(output_reg, output_reg); 3860 __ testq(output_reg, output_reg);
3861 DeoptimizeIf(negative, instr, Deoptimizer::kMinusZero); 3861 DeoptimizeIf(negative, instr, "minus zero");
3862 } 3862 }
3863 __ Set(output_reg, 0); 3863 __ Set(output_reg, 0);
3864 __ bind(&done); 3864 __ bind(&done);
3865 } 3865 }
3866 3866
3867 3867
3868 void LCodeGen::DoMathFround(LMathFround* instr) { 3868 void LCodeGen::DoMathFround(LMathFround* instr) {
3869 XMMRegister input_reg = ToDoubleRegister(instr->value()); 3869 XMMRegister input_reg = ToDoubleRegister(instr->value());
3870 XMMRegister output_reg = ToDoubleRegister(instr->result()); 3870 XMMRegister output_reg = ToDoubleRegister(instr->result());
3871 __ cvtsd2ss(output_reg, input_reg); 3871 __ cvtsd2ss(output_reg, input_reg);
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
3930 DCHECK(ToDoubleRegister(instr->left()).is(xmm2)); 3930 DCHECK(ToDoubleRegister(instr->left()).is(xmm2));
3931 DCHECK(ToDoubleRegister(instr->result()).is(xmm3)); 3931 DCHECK(ToDoubleRegister(instr->result()).is(xmm3));
3932 3932
3933 if (exponent_type.IsSmi()) { 3933 if (exponent_type.IsSmi()) {
3934 MathPowStub stub(isolate(), MathPowStub::TAGGED); 3934 MathPowStub stub(isolate(), MathPowStub::TAGGED);
3935 __ CallStub(&stub); 3935 __ CallStub(&stub);
3936 } else if (exponent_type.IsTagged()) { 3936 } else if (exponent_type.IsTagged()) {
3937 Label no_deopt; 3937 Label no_deopt;
3938 __ JumpIfSmi(tagged_exponent, &no_deopt, Label::kNear); 3938 __ JumpIfSmi(tagged_exponent, &no_deopt, Label::kNear);
3939 __ CmpObjectType(tagged_exponent, HEAP_NUMBER_TYPE, rcx); 3939 __ CmpObjectType(tagged_exponent, HEAP_NUMBER_TYPE, rcx);
3940 DeoptimizeIf(not_equal, instr, Deoptimizer::kNotAHeapNumber); 3940 DeoptimizeIf(not_equal, instr, "not a heap number");
3941 __ bind(&no_deopt); 3941 __ bind(&no_deopt);
3942 MathPowStub stub(isolate(), MathPowStub::TAGGED); 3942 MathPowStub stub(isolate(), MathPowStub::TAGGED);
3943 __ CallStub(&stub); 3943 __ CallStub(&stub);
3944 } else if (exponent_type.IsInteger32()) { 3944 } else if (exponent_type.IsInteger32()) {
3945 MathPowStub stub(isolate(), MathPowStub::INTEGER); 3945 MathPowStub stub(isolate(), MathPowStub::INTEGER);
3946 __ CallStub(&stub); 3946 __ CallStub(&stub);
3947 } else { 3947 } else {
3948 DCHECK(exponent_type.IsDouble()); 3948 DCHECK(exponent_type.IsDouble());
3949 MathPowStub stub(isolate(), MathPowStub::DOUBLE); 3949 MathPowStub stub(isolate(), MathPowStub::DOUBLE);
3950 __ CallStub(&stub); 3950 __ CallStub(&stub);
(...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after
4324 __ cmpl(length, index); 4324 __ cmpl(length, index);
4325 } 4325 }
4326 } 4326 }
4327 } 4327 }
4328 if (FLAG_debug_code && instr->hydrogen()->skip_check()) { 4328 if (FLAG_debug_code && instr->hydrogen()->skip_check()) {
4329 Label done; 4329 Label done;
4330 __ j(NegateCondition(cc), &done, Label::kNear); 4330 __ j(NegateCondition(cc), &done, Label::kNear);
4331 __ int3(); 4331 __ int3();
4332 __ bind(&done); 4332 __ bind(&done);
4333 } else { 4333 } else {
4334 DeoptimizeIf(cc, instr, Deoptimizer::kOutOfBounds); 4334 DeoptimizeIf(cc, instr, "out of bounds");
4335 } 4335 }
4336 } 4336 }
4337 4337
4338 4338
4339 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) { 4339 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
4340 ElementsKind elements_kind = instr->elements_kind(); 4340 ElementsKind elements_kind = instr->elements_kind();
4341 LOperand* key = instr->key(); 4341 LOperand* key = instr->key();
4342 if (kPointerSize == kInt32Size && !key->IsConstantOperand()) { 4342 if (kPointerSize == kInt32Size && !key->IsConstantOperand()) {
4343 Register key_reg = ToRegister(key); 4343 Register key_reg = ToRegister(key);
4344 Representation key_representation = 4344 Representation key_representation =
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after
4565 } 4565 }
4566 __ bind(&not_applicable); 4566 __ bind(&not_applicable);
4567 } 4567 }
4568 4568
4569 4569
4570 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) { 4570 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) {
4571 Register object = ToRegister(instr->object()); 4571 Register object = ToRegister(instr->object());
4572 Register temp = ToRegister(instr->temp()); 4572 Register temp = ToRegister(instr->temp());
4573 Label no_memento_found; 4573 Label no_memento_found;
4574 __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found); 4574 __ TestJSArrayForAllocationMemento(object, temp, &no_memento_found);
4575 DeoptimizeIf(equal, instr, Deoptimizer::kMementoFound); 4575 DeoptimizeIf(equal, instr, "memento found");
4576 __ bind(&no_memento_found); 4576 __ bind(&no_memento_found);
4577 } 4577 }
4578 4578
4579 4579
4580 void LCodeGen::DoStringAdd(LStringAdd* instr) { 4580 void LCodeGen::DoStringAdd(LStringAdd* instr) {
4581 DCHECK(ToRegister(instr->context()).is(rsi)); 4581 DCHECK(ToRegister(instr->context()).is(rsi));
4582 DCHECK(ToRegister(instr->left()).is(rdx)); 4582 DCHECK(ToRegister(instr->left()).is(rdx));
4583 DCHECK(ToRegister(instr->right()).is(rax)); 4583 DCHECK(ToRegister(instr->right()).is(rax));
4584 StringAddStub stub(isolate(), 4584 StringAddStub stub(isolate(),
4585 instr->hydrogen()->flags(), 4585 instr->hydrogen()->flags(),
(...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after
4885 } 4885 }
4886 4886
4887 4887
4888 void LCodeGen::DoSmiTag(LSmiTag* instr) { 4888 void LCodeGen::DoSmiTag(LSmiTag* instr) {
4889 HChange* hchange = instr->hydrogen(); 4889 HChange* hchange = instr->hydrogen();
4890 Register input = ToRegister(instr->value()); 4890 Register input = ToRegister(instr->value());
4891 Register output = ToRegister(instr->result()); 4891 Register output = ToRegister(instr->result());
4892 if (hchange->CheckFlag(HValue::kCanOverflow) && 4892 if (hchange->CheckFlag(HValue::kCanOverflow) &&
4893 hchange->value()->CheckFlag(HValue::kUint32)) { 4893 hchange->value()->CheckFlag(HValue::kUint32)) {
4894 Condition is_smi = __ CheckUInteger32ValidSmiValue(input); 4894 Condition is_smi = __ CheckUInteger32ValidSmiValue(input);
4895 DeoptimizeIf(NegateCondition(is_smi), instr, Deoptimizer::kOverflow); 4895 DeoptimizeIf(NegateCondition(is_smi), instr, "overflow");
4896 } 4896 }
4897 __ Integer32ToSmi(output, input); 4897 __ Integer32ToSmi(output, input);
4898 if (hchange->CheckFlag(HValue::kCanOverflow) && 4898 if (hchange->CheckFlag(HValue::kCanOverflow) &&
4899 !hchange->value()->CheckFlag(HValue::kUint32)) { 4899 !hchange->value()->CheckFlag(HValue::kUint32)) {
4900 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow); 4900 DeoptimizeIf(overflow, instr, "overflow");
4901 } 4901 }
4902 } 4902 }
4903 4903
4904 4904
4905 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { 4905 void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
4906 DCHECK(instr->value()->Equals(instr->result())); 4906 DCHECK(instr->value()->Equals(instr->result()));
4907 Register input = ToRegister(instr->value()); 4907 Register input = ToRegister(instr->value());
4908 if (instr->needs_check()) { 4908 if (instr->needs_check()) {
4909 Condition is_smi = __ CheckSmi(input); 4909 Condition is_smi = __ CheckSmi(input);
4910 DeoptimizeIf(NegateCondition(is_smi), instr, Deoptimizer::kNotASmi); 4910 DeoptimizeIf(NegateCondition(is_smi), instr, "not a Smi");
4911 } else { 4911 } else {
4912 __ AssertSmi(input); 4912 __ AssertSmi(input);
4913 } 4913 }
4914 __ SmiToInteger32(input, input); 4914 __ SmiToInteger32(input, input);
4915 } 4915 }
4916 4916
4917 4917
4918 void LCodeGen::EmitNumberUntagD(LNumberUntagD* instr, Register input_reg, 4918 void LCodeGen::EmitNumberUntagD(LNumberUntagD* instr, Register input_reg,
4919 XMMRegister result_reg, NumberUntagDMode mode) { 4919 XMMRegister result_reg, NumberUntagDMode mode) {
4920 bool can_convert_undefined_to_nan = 4920 bool can_convert_undefined_to_nan =
(...skipping 10 matching lines...) Expand all
4931 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), 4931 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset),
4932 Heap::kHeapNumberMapRootIndex); 4932 Heap::kHeapNumberMapRootIndex);
4933 4933
4934 // On x64 it is safe to load at heap number offset before evaluating the map 4934 // On x64 it is safe to load at heap number offset before evaluating the map
4935 // check, since all heap objects are at least two words long. 4935 // check, since all heap objects are at least two words long.
4936 __ movsd(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset)); 4936 __ movsd(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset));
4937 4937
4938 if (can_convert_undefined_to_nan) { 4938 if (can_convert_undefined_to_nan) {
4939 __ j(not_equal, &convert, Label::kNear); 4939 __ j(not_equal, &convert, Label::kNear);
4940 } else { 4940 } else {
4941 DeoptimizeIf(not_equal, instr, Deoptimizer::kNotAHeapNumber); 4941 DeoptimizeIf(not_equal, instr, "not a heap number");
4942 } 4942 }
4943 4943
4944 if (deoptimize_on_minus_zero) { 4944 if (deoptimize_on_minus_zero) {
4945 XMMRegister xmm_scratch = double_scratch0(); 4945 XMMRegister xmm_scratch = double_scratch0();
4946 __ xorps(xmm_scratch, xmm_scratch); 4946 __ xorps(xmm_scratch, xmm_scratch);
4947 __ ucomisd(xmm_scratch, result_reg); 4947 __ ucomisd(xmm_scratch, result_reg);
4948 __ j(not_equal, &done, Label::kNear); 4948 __ j(not_equal, &done, Label::kNear);
4949 __ movmskpd(kScratchRegister, result_reg); 4949 __ movmskpd(kScratchRegister, result_reg);
4950 __ testq(kScratchRegister, Immediate(1)); 4950 __ testq(kScratchRegister, Immediate(1));
4951 DeoptimizeIf(not_zero, instr, Deoptimizer::kMinusZero); 4951 DeoptimizeIf(not_zero, instr, "minus zero");
4952 } 4952 }
4953 __ jmp(&done, Label::kNear); 4953 __ jmp(&done, Label::kNear);
4954 4954
4955 if (can_convert_undefined_to_nan) { 4955 if (can_convert_undefined_to_nan) {
4956 __ bind(&convert); 4956 __ bind(&convert);
4957 4957
4958 // Convert undefined (and hole) to NaN. Compute NaN as 0/0. 4958 // Convert undefined (and hole) to NaN. Compute NaN as 0/0.
4959 __ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex); 4959 __ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex);
4960 DeoptimizeIf(not_equal, instr, Deoptimizer::kNotAHeapNumberUndefined); 4960 DeoptimizeIf(not_equal, instr, "not a heap number/undefined");
4961 4961
4962 __ pcmpeqd(result_reg, result_reg); 4962 __ pcmpeqd(result_reg, result_reg);
4963 __ jmp(&done, Label::kNear); 4963 __ jmp(&done, Label::kNear);
4964 } 4964 }
4965 } else { 4965 } else {
4966 DCHECK(mode == NUMBER_CANDIDATE_IS_SMI); 4966 DCHECK(mode == NUMBER_CANDIDATE_IS_SMI);
4967 } 4967 }
4968 4968
4969 // Smi to XMM conversion 4969 // Smi to XMM conversion
4970 __ bind(&load_smi); 4970 __ bind(&load_smi);
(...skipping 25 matching lines...) Expand all
4996 __ jmp(done); 4996 __ jmp(done);
4997 4997
4998 __ bind(&check_bools); 4998 __ bind(&check_bools);
4999 __ CompareRoot(input_reg, Heap::kTrueValueRootIndex); 4999 __ CompareRoot(input_reg, Heap::kTrueValueRootIndex);
5000 __ j(not_equal, &check_false, Label::kNear); 5000 __ j(not_equal, &check_false, Label::kNear);
5001 __ Set(input_reg, 1); 5001 __ Set(input_reg, 1);
5002 __ jmp(done); 5002 __ jmp(done);
5003 5003
5004 __ bind(&check_false); 5004 __ bind(&check_false);
5005 __ CompareRoot(input_reg, Heap::kFalseValueRootIndex); 5005 __ CompareRoot(input_reg, Heap::kFalseValueRootIndex);
5006 DeoptimizeIf(not_equal, instr, 5006 DeoptimizeIf(not_equal, instr, "not a heap number/undefined/true/false");
5007 Deoptimizer::kNotAHeapNumberUndefinedBoolean);
5008 __ Set(input_reg, 0); 5007 __ Set(input_reg, 0);
5009 } else { 5008 } else {
5010 XMMRegister scratch = ToDoubleRegister(instr->temp()); 5009 XMMRegister scratch = ToDoubleRegister(instr->temp());
5011 DCHECK(!scratch.is(xmm0)); 5010 DCHECK(!scratch.is(xmm0));
5012 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset), 5011 __ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset),
5013 Heap::kHeapNumberMapRootIndex); 5012 Heap::kHeapNumberMapRootIndex);
5014 DeoptimizeIf(not_equal, instr, Deoptimizer::kNotAHeapNumber); 5013 DeoptimizeIf(not_equal, instr, "not a heap number");
5015 __ movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); 5014 __ movsd(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset));
5016 __ cvttsd2si(input_reg, xmm0); 5015 __ cvttsd2si(input_reg, xmm0);
5017 __ Cvtlsi2sd(scratch, input_reg); 5016 __ Cvtlsi2sd(scratch, input_reg);
5018 __ ucomisd(xmm0, scratch); 5017 __ ucomisd(xmm0, scratch);
5019 DeoptimizeIf(not_equal, instr, Deoptimizer::kLostPrecision); 5018 DeoptimizeIf(not_equal, instr, "lost precision");
5020 DeoptimizeIf(parity_even, instr, Deoptimizer::kNaN); 5019 DeoptimizeIf(parity_even, instr, "NaN");
5021 if (instr->hydrogen()->GetMinusZeroMode() == FAIL_ON_MINUS_ZERO) { 5020 if (instr->hydrogen()->GetMinusZeroMode() == FAIL_ON_MINUS_ZERO) {
5022 __ testl(input_reg, input_reg); 5021 __ testl(input_reg, input_reg);
5023 __ j(not_zero, done); 5022 __ j(not_zero, done);
5024 __ movmskpd(input_reg, xmm0); 5023 __ movmskpd(input_reg, xmm0);
5025 __ andl(input_reg, Immediate(1)); 5024 __ andl(input_reg, Immediate(1));
5026 DeoptimizeIf(not_zero, instr, Deoptimizer::kMinusZero); 5025 DeoptimizeIf(not_zero, instr, "minus zero");
5027 } 5026 }
5028 } 5027 }
5029 } 5028 }
5030 5029
5031 5030
5032 void LCodeGen::DoTaggedToI(LTaggedToI* instr) { 5031 void LCodeGen::DoTaggedToI(LTaggedToI* instr) {
5033 class DeferredTaggedToI FINAL : public LDeferredCode { 5032 class DeferredTaggedToI FINAL : public LDeferredCode {
5034 public: 5033 public:
5035 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr) 5034 DeferredTaggedToI(LCodeGen* codegen, LTaggedToI* instr)
5036 : LDeferredCode(codegen), instr_(instr) { } 5035 : LDeferredCode(codegen), instr_(instr) { }
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
5087 __ TruncateDoubleToI(result_reg, input_reg); 5086 __ TruncateDoubleToI(result_reg, input_reg);
5088 } else { 5087 } else {
5089 Label lost_precision, is_nan, minus_zero, done; 5088 Label lost_precision, is_nan, minus_zero, done;
5090 XMMRegister xmm_scratch = double_scratch0(); 5089 XMMRegister xmm_scratch = double_scratch0();
5091 Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear; 5090 Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear;
5092 __ DoubleToI(result_reg, input_reg, xmm_scratch, 5091 __ DoubleToI(result_reg, input_reg, xmm_scratch,
5093 instr->hydrogen()->GetMinusZeroMode(), &lost_precision, 5092 instr->hydrogen()->GetMinusZeroMode(), &lost_precision,
5094 &is_nan, &minus_zero, dist); 5093 &is_nan, &minus_zero, dist);
5095 __ jmp(&done, dist); 5094 __ jmp(&done, dist);
5096 __ bind(&lost_precision); 5095 __ bind(&lost_precision);
5097 DeoptimizeIf(no_condition, instr, Deoptimizer::kLostPrecision); 5096 DeoptimizeIf(no_condition, instr, "lost precision");
5098 __ bind(&is_nan); 5097 __ bind(&is_nan);
5099 DeoptimizeIf(no_condition, instr, Deoptimizer::kNaN); 5098 DeoptimizeIf(no_condition, instr, "NaN");
5100 __ bind(&minus_zero); 5099 __ bind(&minus_zero);
5101 DeoptimizeIf(no_condition, instr, Deoptimizer::kMinusZero); 5100 DeoptimizeIf(no_condition, instr, "minus zero");
5102 __ bind(&done); 5101 __ bind(&done);
5103 } 5102 }
5104 } 5103 }
5105 5104
5106 5105
5107 void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) { 5106 void LCodeGen::DoDoubleToSmi(LDoubleToSmi* instr) {
5108 LOperand* input = instr->value(); 5107 LOperand* input = instr->value();
5109 DCHECK(input->IsDoubleRegister()); 5108 DCHECK(input->IsDoubleRegister());
5110 LOperand* result = instr->result(); 5109 LOperand* result = instr->result();
5111 DCHECK(result->IsRegister()); 5110 DCHECK(result->IsRegister());
5112 5111
5113 XMMRegister input_reg = ToDoubleRegister(input); 5112 XMMRegister input_reg = ToDoubleRegister(input);
5114 Register result_reg = ToRegister(result); 5113 Register result_reg = ToRegister(result);
5115 5114
5116 Label lost_precision, is_nan, minus_zero, done; 5115 Label lost_precision, is_nan, minus_zero, done;
5117 XMMRegister xmm_scratch = double_scratch0(); 5116 XMMRegister xmm_scratch = double_scratch0();
5118 Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear; 5117 Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear;
5119 __ DoubleToI(result_reg, input_reg, xmm_scratch, 5118 __ DoubleToI(result_reg, input_reg, xmm_scratch,
5120 instr->hydrogen()->GetMinusZeroMode(), &lost_precision, &is_nan, 5119 instr->hydrogen()->GetMinusZeroMode(), &lost_precision, &is_nan,
5121 &minus_zero, dist); 5120 &minus_zero, dist);
5122 __ jmp(&done, dist); 5121 __ jmp(&done, dist);
5123 __ bind(&lost_precision); 5122 __ bind(&lost_precision);
5124 DeoptimizeIf(no_condition, instr, Deoptimizer::kLostPrecision); 5123 DeoptimizeIf(no_condition, instr, "lost precision");
5125 __ bind(&is_nan); 5124 __ bind(&is_nan);
5126 DeoptimizeIf(no_condition, instr, Deoptimizer::kNaN); 5125 DeoptimizeIf(no_condition, instr, "NaN");
5127 __ bind(&minus_zero); 5126 __ bind(&minus_zero);
5128 DeoptimizeIf(no_condition, instr, Deoptimizer::kMinusZero); 5127 DeoptimizeIf(no_condition, instr, "minus zero");
5129 __ bind(&done); 5128 __ bind(&done);
5130 __ Integer32ToSmi(result_reg, result_reg); 5129 __ Integer32ToSmi(result_reg, result_reg);
5131 DeoptimizeIf(overflow, instr, Deoptimizer::kOverflow); 5130 DeoptimizeIf(overflow, instr, "overflow");
5132 } 5131 }
5133 5132
5134 5133
5135 void LCodeGen::DoCheckSmi(LCheckSmi* instr) { 5134 void LCodeGen::DoCheckSmi(LCheckSmi* instr) {
5136 LOperand* input = instr->value(); 5135 LOperand* input = instr->value();
5137 Condition cc = masm()->CheckSmi(ToRegister(input)); 5136 Condition cc = masm()->CheckSmi(ToRegister(input));
5138 DeoptimizeIf(NegateCondition(cc), instr, Deoptimizer::kNotASmi); 5137 DeoptimizeIf(NegateCondition(cc), instr, "not a Smi");
5139 } 5138 }
5140 5139
5141 5140
5142 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) { 5141 void LCodeGen::DoCheckNonSmi(LCheckNonSmi* instr) {
5143 if (!instr->hydrogen()->value()->type().IsHeapObject()) { 5142 if (!instr->hydrogen()->value()->type().IsHeapObject()) {
5144 LOperand* input = instr->value(); 5143 LOperand* input = instr->value();
5145 Condition cc = masm()->CheckSmi(ToRegister(input)); 5144 Condition cc = masm()->CheckSmi(ToRegister(input));
5146 DeoptimizeIf(cc, instr, Deoptimizer::kSmi); 5145 DeoptimizeIf(cc, instr, "Smi");
5147 } 5146 }
5148 } 5147 }
5149 5148
5150 5149
5151 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) { 5150 void LCodeGen::DoCheckInstanceType(LCheckInstanceType* instr) {
5152 Register input = ToRegister(instr->value()); 5151 Register input = ToRegister(instr->value());
5153 5152
5154 __ movp(kScratchRegister, FieldOperand(input, HeapObject::kMapOffset)); 5153 __ movp(kScratchRegister, FieldOperand(input, HeapObject::kMapOffset));
5155 5154
5156 if (instr->hydrogen()->is_interval_check()) { 5155 if (instr->hydrogen()->is_interval_check()) {
5157 InstanceType first; 5156 InstanceType first;
5158 InstanceType last; 5157 InstanceType last;
5159 instr->hydrogen()->GetCheckInterval(&first, &last); 5158 instr->hydrogen()->GetCheckInterval(&first, &last);
5160 5159
5161 __ cmpb(FieldOperand(kScratchRegister, Map::kInstanceTypeOffset), 5160 __ cmpb(FieldOperand(kScratchRegister, Map::kInstanceTypeOffset),
5162 Immediate(static_cast<int8_t>(first))); 5161 Immediate(static_cast<int8_t>(first)));
5163 5162
5164 // If there is only one type in the interval check for equality. 5163 // If there is only one type in the interval check for equality.
5165 if (first == last) { 5164 if (first == last) {
5166 DeoptimizeIf(not_equal, instr, Deoptimizer::kWrongInstanceType); 5165 DeoptimizeIf(not_equal, instr, "wrong instance type");
5167 } else { 5166 } else {
5168 DeoptimizeIf(below, instr, Deoptimizer::kWrongInstanceType); 5167 DeoptimizeIf(below, instr, "wrong instance type");
5169 // Omit check for the last type. 5168 // Omit check for the last type.
5170 if (last != LAST_TYPE) { 5169 if (last != LAST_TYPE) {
5171 __ cmpb(FieldOperand(kScratchRegister, Map::kInstanceTypeOffset), 5170 __ cmpb(FieldOperand(kScratchRegister, Map::kInstanceTypeOffset),
5172 Immediate(static_cast<int8_t>(last))); 5171 Immediate(static_cast<int8_t>(last)));
5173 DeoptimizeIf(above, instr, Deoptimizer::kWrongInstanceType); 5172 DeoptimizeIf(above, instr, "wrong instance type");
5174 } 5173 }
5175 } 5174 }
5176 } else { 5175 } else {
5177 uint8_t mask; 5176 uint8_t mask;
5178 uint8_t tag; 5177 uint8_t tag;
5179 instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag); 5178 instr->hydrogen()->GetCheckMaskAndTag(&mask, &tag);
5180 5179
5181 if (base::bits::IsPowerOfTwo32(mask)) { 5180 if (base::bits::IsPowerOfTwo32(mask)) {
5182 DCHECK(tag == 0 || base::bits::IsPowerOfTwo32(tag)); 5181 DCHECK(tag == 0 || base::bits::IsPowerOfTwo32(tag));
5183 __ testb(FieldOperand(kScratchRegister, Map::kInstanceTypeOffset), 5182 __ testb(FieldOperand(kScratchRegister, Map::kInstanceTypeOffset),
5184 Immediate(mask)); 5183 Immediate(mask));
5185 DeoptimizeIf(tag == 0 ? not_zero : zero, instr, 5184 DeoptimizeIf(tag == 0 ? not_zero : zero, instr, "wrong instance type");
5186 Deoptimizer::kWrongInstanceType);
5187 } else { 5185 } else {
5188 __ movzxbl(kScratchRegister, 5186 __ movzxbl(kScratchRegister,
5189 FieldOperand(kScratchRegister, Map::kInstanceTypeOffset)); 5187 FieldOperand(kScratchRegister, Map::kInstanceTypeOffset));
5190 __ andb(kScratchRegister, Immediate(mask)); 5188 __ andb(kScratchRegister, Immediate(mask));
5191 __ cmpb(kScratchRegister, Immediate(tag)); 5189 __ cmpb(kScratchRegister, Immediate(tag));
5192 DeoptimizeIf(not_equal, instr, Deoptimizer::kWrongInstanceType); 5190 DeoptimizeIf(not_equal, instr, "wrong instance type");
5193 } 5191 }
5194 } 5192 }
5195 } 5193 }
5196 5194
5197 5195
5198 void LCodeGen::DoCheckValue(LCheckValue* instr) { 5196 void LCodeGen::DoCheckValue(LCheckValue* instr) {
5199 Register reg = ToRegister(instr->value()); 5197 Register reg = ToRegister(instr->value());
5200 __ Cmp(reg, instr->hydrogen()->object().handle()); 5198 __ Cmp(reg, instr->hydrogen()->object().handle());
5201 DeoptimizeIf(not_equal, instr, Deoptimizer::kValueMismatch); 5199 DeoptimizeIf(not_equal, instr, "value mismatch");
5202 } 5200 }
5203 5201
5204 5202
5205 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) { 5203 void LCodeGen::DoDeferredInstanceMigration(LCheckMaps* instr, Register object) {
5206 { 5204 {
5207 PushSafepointRegistersScope scope(this); 5205 PushSafepointRegistersScope scope(this);
5208 __ Push(object); 5206 __ Push(object);
5209 __ Set(rsi, 0); 5207 __ Set(rsi, 0);
5210 __ CallRuntimeSaveDoubles(Runtime::kTryMigrateInstance); 5208 __ CallRuntimeSaveDoubles(Runtime::kTryMigrateInstance);
5211 RecordSafepointWithRegisters( 5209 RecordSafepointWithRegisters(
5212 instr->pointer_map(), 1, Safepoint::kNoLazyDeopt); 5210 instr->pointer_map(), 1, Safepoint::kNoLazyDeopt);
5213 5211
5214 __ testp(rax, Immediate(kSmiTagMask)); 5212 __ testp(rax, Immediate(kSmiTagMask));
5215 } 5213 }
5216 DeoptimizeIf(zero, instr, Deoptimizer::kInstanceMigrationFailed); 5214 DeoptimizeIf(zero, instr, "instance migration failed");
5217 } 5215 }
5218 5216
5219 5217
5220 void LCodeGen::DoCheckMaps(LCheckMaps* instr) { 5218 void LCodeGen::DoCheckMaps(LCheckMaps* instr) {
5221 class DeferredCheckMaps FINAL : public LDeferredCode { 5219 class DeferredCheckMaps FINAL : public LDeferredCode {
5222 public: 5220 public:
5223 DeferredCheckMaps(LCodeGen* codegen, LCheckMaps* instr, Register object) 5221 DeferredCheckMaps(LCodeGen* codegen, LCheckMaps* instr, Register object)
5224 : LDeferredCode(codegen), instr_(instr), object_(object) { 5222 : LDeferredCode(codegen), instr_(instr), object_(object) {
5225 SetExit(check_maps()); 5223 SetExit(check_maps());
5226 } 5224 }
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
5260 Handle<Map> map = maps->at(i).handle(); 5258 Handle<Map> map = maps->at(i).handle();
5261 __ CompareMap(reg, map); 5259 __ CompareMap(reg, map);
5262 __ j(equal, &success, Label::kNear); 5260 __ j(equal, &success, Label::kNear);
5263 } 5261 }
5264 5262
5265 Handle<Map> map = maps->at(maps->size() - 1).handle(); 5263 Handle<Map> map = maps->at(maps->size() - 1).handle();
5266 __ CompareMap(reg, map); 5264 __ CompareMap(reg, map);
5267 if (instr->hydrogen()->HasMigrationTarget()) { 5265 if (instr->hydrogen()->HasMigrationTarget()) {
5268 __ j(not_equal, deferred->entry()); 5266 __ j(not_equal, deferred->entry());
5269 } else { 5267 } else {
5270 DeoptimizeIf(not_equal, instr, Deoptimizer::kWrongMap); 5268 DeoptimizeIf(not_equal, instr, "wrong map");
5271 } 5269 }
5272 5270
5273 __ bind(&success); 5271 __ bind(&success);
5274 } 5272 }
5275 5273
5276 5274
5277 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { 5275 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) {
5278 XMMRegister value_reg = ToDoubleRegister(instr->unclamped()); 5276 XMMRegister value_reg = ToDoubleRegister(instr->unclamped());
5279 XMMRegister xmm_scratch = double_scratch0(); 5277 XMMRegister xmm_scratch = double_scratch0();
5280 Register result_reg = ToRegister(instr->result()); 5278 Register result_reg = ToRegister(instr->result());
(...skipping 18 matching lines...) Expand all
5299 __ JumpIfSmi(input_reg, &is_smi, dist); 5297 __ JumpIfSmi(input_reg, &is_smi, dist);
5300 5298
5301 // Check for heap number 5299 // Check for heap number
5302 __ Cmp(FieldOperand(input_reg, HeapObject::kMapOffset), 5300 __ Cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
5303 factory()->heap_number_map()); 5301 factory()->heap_number_map());
5304 __ j(equal, &heap_number, Label::kNear); 5302 __ j(equal, &heap_number, Label::kNear);
5305 5303
5306 // Check for undefined. Undefined is converted to zero for clamping 5304 // Check for undefined. Undefined is converted to zero for clamping
5307 // conversions. 5305 // conversions.
5308 __ Cmp(input_reg, factory()->undefined_value()); 5306 __ Cmp(input_reg, factory()->undefined_value());
5309 DeoptimizeIf(not_equal, instr, Deoptimizer::kNotAHeapNumberUndefined); 5307 DeoptimizeIf(not_equal, instr, "not a heap number/undefined");
5310 __ xorl(input_reg, input_reg); 5308 __ xorl(input_reg, input_reg);
5311 __ jmp(&done, Label::kNear); 5309 __ jmp(&done, Label::kNear);
5312 5310
5313 // Heap number 5311 // Heap number
5314 __ bind(&heap_number); 5312 __ bind(&heap_number);
5315 __ movsd(xmm_scratch, FieldOperand(input_reg, HeapNumber::kValueOffset)); 5313 __ movsd(xmm_scratch, FieldOperand(input_reg, HeapNumber::kValueOffset));
5316 __ ClampDoubleToUint8(xmm_scratch, temp_xmm_reg, input_reg); 5314 __ ClampDoubleToUint8(xmm_scratch, temp_xmm_reg, input_reg);
5317 __ jmp(&done, Label::kNear); 5315 __ jmp(&done, Label::kNear);
5318 5316
5319 // smi 5317 // smi
(...skipping 458 matching lines...) Expand 10 before | Expand all | Expand 10 after
5778 DCHECK(!environment->HasBeenRegistered()); 5776 DCHECK(!environment->HasBeenRegistered());
5779 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); 5777 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt);
5780 5778
5781 GenerateOsrPrologue(); 5779 GenerateOsrPrologue();
5782 } 5780 }
5783 5781
5784 5782
5785 void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) { 5783 void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) {
5786 DCHECK(ToRegister(instr->context()).is(rsi)); 5784 DCHECK(ToRegister(instr->context()).is(rsi));
5787 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); 5785 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
5788 DeoptimizeIf(equal, instr, Deoptimizer::kUndefined); 5786 DeoptimizeIf(equal, instr, "undefined");
5789 5787
5790 Register null_value = rdi; 5788 Register null_value = rdi;
5791 __ LoadRoot(null_value, Heap::kNullValueRootIndex); 5789 __ LoadRoot(null_value, Heap::kNullValueRootIndex);
5792 __ cmpp(rax, null_value); 5790 __ cmpp(rax, null_value);
5793 DeoptimizeIf(equal, instr, Deoptimizer::kNull); 5791 DeoptimizeIf(equal, instr, "null");
5794 5792
5795 Condition cc = masm()->CheckSmi(rax); 5793 Condition cc = masm()->CheckSmi(rax);
5796 DeoptimizeIf(cc, instr, Deoptimizer::kSmi); 5794 DeoptimizeIf(cc, instr, "Smi");
5797 5795
5798 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE); 5796 STATIC_ASSERT(FIRST_JS_PROXY_TYPE == FIRST_SPEC_OBJECT_TYPE);
5799 __ CmpObjectType(rax, LAST_JS_PROXY_TYPE, rcx); 5797 __ CmpObjectType(rax, LAST_JS_PROXY_TYPE, rcx);
5800 DeoptimizeIf(below_equal, instr, Deoptimizer::kWrongInstanceType); 5798 DeoptimizeIf(below_equal, instr, "wrong instance type");
5801 5799
5802 Label use_cache, call_runtime; 5800 Label use_cache, call_runtime;
5803 __ CheckEnumCache(null_value, &call_runtime); 5801 __ CheckEnumCache(null_value, &call_runtime);
5804 5802
5805 __ movp(rax, FieldOperand(rax, HeapObject::kMapOffset)); 5803 __ movp(rax, FieldOperand(rax, HeapObject::kMapOffset));
5806 __ jmp(&use_cache, Label::kNear); 5804 __ jmp(&use_cache, Label::kNear);
5807 5805
5808 // Get the set of properties to enumerate. 5806 // Get the set of properties to enumerate.
5809 __ bind(&call_runtime); 5807 __ bind(&call_runtime);
5810 __ Push(rax); 5808 __ Push(rax);
5811 CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr); 5809 CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr);
5812 5810
5813 __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset), 5811 __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset),
5814 Heap::kMetaMapRootIndex); 5812 Heap::kMetaMapRootIndex);
5815 DeoptimizeIf(not_equal, instr, Deoptimizer::kWrongMap); 5813 DeoptimizeIf(not_equal, instr, "wrong map");
5816 __ bind(&use_cache); 5814 __ bind(&use_cache);
5817 } 5815 }
5818 5816
5819 5817
5820 void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) { 5818 void LCodeGen::DoForInCacheArray(LForInCacheArray* instr) {
5821 Register map = ToRegister(instr->map()); 5819 Register map = ToRegister(instr->map());
5822 Register result = ToRegister(instr->result()); 5820 Register result = ToRegister(instr->result());
5823 Label load_cache, done; 5821 Label load_cache, done;
5824 __ EnumLength(result, map); 5822 __ EnumLength(result, map);
5825 __ Cmp(result, Smi::FromInt(0)); 5823 __ Cmp(result, Smi::FromInt(0));
5826 __ j(not_equal, &load_cache, Label::kNear); 5824 __ j(not_equal, &load_cache, Label::kNear);
5827 __ LoadRoot(result, Heap::kEmptyFixedArrayRootIndex); 5825 __ LoadRoot(result, Heap::kEmptyFixedArrayRootIndex);
5828 __ jmp(&done, Label::kNear); 5826 __ jmp(&done, Label::kNear);
5829 __ bind(&load_cache); 5827 __ bind(&load_cache);
5830 __ LoadInstanceDescriptors(map, result); 5828 __ LoadInstanceDescriptors(map, result);
5831 __ movp(result, 5829 __ movp(result,
5832 FieldOperand(result, DescriptorArray::kEnumCacheOffset)); 5830 FieldOperand(result, DescriptorArray::kEnumCacheOffset));
5833 __ movp(result, 5831 __ movp(result,
5834 FieldOperand(result, FixedArray::SizeFor(instr->idx()))); 5832 FieldOperand(result, FixedArray::SizeFor(instr->idx())));
5835 __ bind(&done); 5833 __ bind(&done);
5836 Condition cc = masm()->CheckSmi(result); 5834 Condition cc = masm()->CheckSmi(result);
5837 DeoptimizeIf(cc, instr, Deoptimizer::kNoCache); 5835 DeoptimizeIf(cc, instr, "no cache");
5838 } 5836 }
5839 5837
5840 5838
5841 void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) { 5839 void LCodeGen::DoCheckMapValue(LCheckMapValue* instr) {
5842 Register object = ToRegister(instr->value()); 5840 Register object = ToRegister(instr->value());
5843 __ cmpp(ToRegister(instr->map()), 5841 __ cmpp(ToRegister(instr->map()),
5844 FieldOperand(object, HeapObject::kMapOffset)); 5842 FieldOperand(object, HeapObject::kMapOffset));
5845 DeoptimizeIf(not_equal, instr, Deoptimizer::kWrongMap); 5843 DeoptimizeIf(not_equal, instr, "wrong map");
5846 } 5844 }
5847 5845
5848 5846
5849 void LCodeGen::DoDeferredLoadMutableDouble(LLoadFieldByIndex* instr, 5847 void LCodeGen::DoDeferredLoadMutableDouble(LLoadFieldByIndex* instr,
5850 Register object, 5848 Register object,
5851 Register index) { 5849 Register index) {
5852 PushSafepointRegistersScope scope(this); 5850 PushSafepointRegistersScope scope(this);
5853 __ Push(object); 5851 __ Push(object);
5854 __ Push(index); 5852 __ Push(index);
5855 __ xorp(rsi, rsi); 5853 __ xorp(rsi, rsi);
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
5931 CallRuntime(Runtime::kPushBlockContext, 2, instr); 5929 CallRuntime(Runtime::kPushBlockContext, 2, instr);
5932 RecordSafepoint(Safepoint::kNoLazyDeopt); 5930 RecordSafepoint(Safepoint::kNoLazyDeopt);
5933 } 5931 }
5934 5932
5935 5933
5936 #undef __ 5934 #undef __
5937 5935
5938 } } // namespace v8::internal 5936 } } // namespace v8::internal
5939 5937
5940 #endif // V8_TARGET_ARCH_X64 5938 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/lithium-codegen-x64.h ('k') | src/x87/lithium-codegen-x87.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698