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

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

Issue 196133017: Experimental parser: merge r19949 (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/parser
Patch Set: Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/x64/lithium-codegen-x64.h ('k') | src/x64/lithium-x64.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
147 if (info()->IsOptimizing()) { 147 if (info()->IsOptimizing()) {
148 ProfileEntryHookStub::MaybeCallEntryHook(masm_); 148 ProfileEntryHookStub::MaybeCallEntryHook(masm_);
149 149
150 #ifdef DEBUG 150 #ifdef DEBUG
151 if (strlen(FLAG_stop_at) > 0 && 151 if (strlen(FLAG_stop_at) > 0 &&
152 info_->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { 152 info_->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) {
153 __ int3(); 153 __ int3();
154 } 154 }
155 #endif 155 #endif
156 156
157 // Classic mode functions need to replace the receiver with the global proxy 157 // Sloppy mode functions need to replace the receiver with the global proxy
158 // when called as functions (without an explicit receiver object). 158 // when called as functions (without an explicit receiver object).
159 if (info_->this_has_uses() && 159 if (info_->this_has_uses() &&
160 info_->is_classic_mode() && 160 info_->strict_mode() == SLOPPY &&
161 !info_->is_native()) { 161 !info_->is_native()) {
162 Label ok; 162 Label ok;
163 StackArgumentsAccessor args(rsp, scope()->num_parameters()); 163 StackArgumentsAccessor args(rsp, scope()->num_parameters());
164 __ movp(rcx, args.GetReceiverOperand()); 164 __ movp(rcx, args.GetReceiverOperand());
165 165
166 __ CompareRoot(rcx, Heap::kUndefinedValueRootIndex); 166 __ CompareRoot(rcx, Heap::kUndefinedValueRootIndex);
167 __ j(not_equal, &ok, Label::kNear); 167 __ j(not_equal, &ok, Label::kNear);
168 168
169 __ movp(rcx, GlobalObjectOperand()); 169 __ movp(rcx, GlobalObjectOperand());
170 __ movp(rcx, FieldOperand(rcx, GlobalObject::kGlobalReceiverOffset)); 170 __ movp(rcx, FieldOperand(rcx, GlobalObject::kGlobalReceiverOffset));
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
266 osr_pc_offset_ = masm()->pc_offset(); 266 osr_pc_offset_ = masm()->pc_offset();
267 267
268 // Adjust the frame size, subsuming the unoptimized frame into the 268 // Adjust the frame size, subsuming the unoptimized frame into the
269 // optimized frame. 269 // optimized frame.
270 int slots = GetStackSlotCount() - graph()->osr()->UnoptimizedFrameSlots(); 270 int slots = GetStackSlotCount() - graph()->osr()->UnoptimizedFrameSlots();
271 ASSERT(slots >= 0); 271 ASSERT(slots >= 0);
272 __ subq(rsp, Immediate(slots * kPointerSize)); 272 __ subq(rsp, Immediate(slots * kPointerSize));
273 } 273 }
274 274
275 275
276 void LCodeGen::GenerateBodyInstructionPre(LInstruction* instr) {
277 if (!instr->IsLazyBailout() && !instr->IsGap()) {
278 safepoints_.BumpLastLazySafepointIndex();
279 }
280 }
281
282
276 bool LCodeGen::GenerateJumpTable() { 283 bool LCodeGen::GenerateJumpTable() {
277 Label needs_frame; 284 Label needs_frame;
278 if (jump_table_.length() > 0) { 285 if (jump_table_.length() > 0) {
279 Comment(";;; -------------------- Jump table --------------------"); 286 Comment(";;; -------------------- Jump table --------------------");
280 } 287 }
281 for (int i = 0; i < jump_table_.length(); i++) { 288 for (int i = 0; i < jump_table_.length(); i++) {
282 __ bind(&jump_table_[i].label); 289 __ bind(&jump_table_[i].label);
283 Address entry = jump_table_[i].address; 290 Address entry = jump_table_[i].address;
284 Deoptimizer::BailoutType type = jump_table_[i].bailout_type; 291 Deoptimizer::BailoutType type = jump_table_[i].bailout_type;
285 int id = Deoptimizer::GetDeoptimizationId(isolate(), entry, type); 292 int id = Deoptimizer::GetDeoptimizationId(isolate(), entry, type);
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after
564 if (op->IsStackSlot()) { 571 if (op->IsStackSlot()) {
565 if (is_tagged) { 572 if (is_tagged) {
566 translation->StoreStackSlot(op->index()); 573 translation->StoreStackSlot(op->index());
567 } else if (is_uint32) { 574 } else if (is_uint32) {
568 translation->StoreUint32StackSlot(op->index()); 575 translation->StoreUint32StackSlot(op->index());
569 } else { 576 } else {
570 translation->StoreInt32StackSlot(op->index()); 577 translation->StoreInt32StackSlot(op->index());
571 } 578 }
572 } else if (op->IsDoubleStackSlot()) { 579 } else if (op->IsDoubleStackSlot()) {
573 translation->StoreDoubleStackSlot(op->index()); 580 translation->StoreDoubleStackSlot(op->index());
574 } else if (op->IsArgument()) {
575 ASSERT(is_tagged);
576 int src_index = GetStackSlotCount() + op->index();
577 translation->StoreStackSlot(src_index);
578 } else if (op->IsRegister()) { 581 } else if (op->IsRegister()) {
579 Register reg = ToRegister(op); 582 Register reg = ToRegister(op);
580 if (is_tagged) { 583 if (is_tagged) {
581 translation->StoreRegister(reg); 584 translation->StoreRegister(reg);
582 } else if (is_uint32) { 585 } else if (is_uint32) {
583 translation->StoreUint32Register(reg); 586 translation->StoreUint32Register(reg);
584 } else { 587 } else {
585 translation->StoreInt32Register(reg); 588 translation->StoreInt32Register(reg);
586 } 589 }
587 } else if (op->IsDoubleRegister()) { 590 } else if (op->IsDoubleRegister()) {
(...skipping 392 matching lines...) Expand 10 before | Expand all | Expand 10 after
980 UNREACHABLE(); 983 UNREACHABLE();
981 } 984 }
982 } 985 }
983 986
984 987
985 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { 988 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) {
986 GenerateOsrPrologue(); 989 GenerateOsrPrologue();
987 } 990 }
988 991
989 992
993 void LCodeGen::DoModByPowerOf2I(LModByPowerOf2I* instr) {
994 Register dividend = ToRegister(instr->dividend());
995 int32_t divisor = instr->divisor();
996 ASSERT(dividend.is(ToRegister(instr->result())));
997
998 // Theoretically, a variation of the branch-free code for integer division by
999 // a power of 2 (calculating the remainder via an additional multiplication
1000 // (which gets simplified to an 'and') and subtraction) should be faster, and
1001 // this is exactly what GCC and clang emit. Nevertheless, benchmarks seem to
1002 // indicate that positive dividends are heavily favored, so the branching
1003 // version performs better.
1004 HMod* hmod = instr->hydrogen();
1005 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1);
1006 Label dividend_is_not_negative, done;
1007 if (hmod->CheckFlag(HValue::kLeftCanBeNegative)) {
1008 __ testl(dividend, dividend);
1009 __ j(not_sign, &dividend_is_not_negative, Label::kNear);
1010 // Note that this is correct even for kMinInt operands.
1011 __ negl(dividend);
1012 __ andl(dividend, Immediate(mask));
1013 __ negl(dividend);
1014 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1015 DeoptimizeIf(zero, instr->environment());
1016 }
1017 __ jmp(&done, Label::kNear);
1018 }
1019
1020 __ bind(&dividend_is_not_negative);
1021 __ andl(dividend, Immediate(mask));
1022 __ bind(&done);
1023 }
1024
1025
1026 void LCodeGen::DoModByConstI(LModByConstI* instr) {
1027 Register dividend = ToRegister(instr->dividend());
1028 int32_t divisor = instr->divisor();
1029 ASSERT(ToRegister(instr->result()).is(rax));
1030
1031 if (divisor == 0) {
1032 DeoptimizeIf(no_condition, instr->environment());
1033 return;
1034 }
1035
1036 __ FlooringDiv(dividend, Abs(divisor));
1037 __ movl(rax, dividend);
1038 __ shrl(rax, Immediate(31));
1039 __ addl(rdx, rax);
1040 __ imull(rdx, rdx, Immediate(Abs(divisor)));
1041 __ movl(rax, dividend);
1042 __ subl(rax, rdx);
1043
1044 // Check for negative zero.
1045 HMod* hmod = instr->hydrogen();
1046 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1047 Label remainder_not_zero;
1048 __ j(not_zero, &remainder_not_zero, Label::kNear);
1049 __ cmpl(dividend, Immediate(0));
1050 DeoptimizeIf(less, instr->environment());
1051 __ bind(&remainder_not_zero);
1052 }
1053 }
1054
1055
990 void LCodeGen::DoModI(LModI* instr) { 1056 void LCodeGen::DoModI(LModI* instr) {
991 HMod* hmod = instr->hydrogen(); 1057 HMod* hmod = instr->hydrogen();
992 HValue* left = hmod->left(); 1058
993 HValue* right = hmod->right(); 1059 Register left_reg = ToRegister(instr->left());
994 if (hmod->RightIsPowerOf2()) { 1060 ASSERT(left_reg.is(rax));
995 // TODO(svenpanne) We should really do the strength reduction on the 1061 Register right_reg = ToRegister(instr->right());
996 // Hydrogen level. 1062 ASSERT(!right_reg.is(rax));
997 Register left_reg = ToRegister(instr->left()); 1063 ASSERT(!right_reg.is(rdx));
998 ASSERT(left_reg.is(ToRegister(instr->result()))); 1064 Register result_reg = ToRegister(instr->result());
999 1065 ASSERT(result_reg.is(rdx));
1000 // Note: The code below even works when right contains kMinInt. 1066
1001 int32_t divisor = Abs(right->GetInteger32Constant()); 1067 Label done;
1002 1068 // Check for x % 0, idiv would signal a divide error. We have to
1003 Label left_is_not_negative, done; 1069 // deopt in this case because we can't return a NaN.
1004 if (left->CanBeNegative()) { 1070 if (hmod->CheckFlag(HValue::kCanBeDivByZero)) {
1005 __ testl(left_reg, left_reg); 1071 __ testl(right_reg, right_reg);
1006 __ j(not_sign, &left_is_not_negative, Label::kNear); 1072 DeoptimizeIf(zero, instr->environment());
1007 __ negl(left_reg); 1073 }
1008 __ andl(left_reg, Immediate(divisor - 1)); 1074
1009 __ negl(left_reg); 1075 // Check for kMinInt % -1, idiv would signal a divide error. We
1010 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { 1076 // have to deopt if we care about -0, because we can't return that.
1011 DeoptimizeIf(zero, instr->environment()); 1077 if (hmod->CheckFlag(HValue::kCanOverflow)) {
1012 } 1078 Label no_overflow_possible;
1079 __ cmpl(left_reg, Immediate(kMinInt));
1080 __ j(not_zero, &no_overflow_possible, Label::kNear);
1081 __ cmpl(right_reg, Immediate(-1));
1082 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1083 DeoptimizeIf(equal, instr->environment());
1084 } else {
1085 __ j(not_equal, &no_overflow_possible, Label::kNear);
1086 __ Set(result_reg, 0);
1013 __ jmp(&done, Label::kNear); 1087 __ jmp(&done, Label::kNear);
1014 } 1088 }
1015 1089 __ bind(&no_overflow_possible);
1016 __ bind(&left_is_not_negative); 1090 }
1017 __ andl(left_reg, Immediate(divisor - 1)); 1091
1018 __ bind(&done); 1092 // Sign extend dividend in eax into edx:eax, since we are using only the low
1019 } else { 1093 // 32 bits of the values.
1020 Register left_reg = ToRegister(instr->left()); 1094 __ cdq();
1021 ASSERT(left_reg.is(rax)); 1095
1022 Register right_reg = ToRegister(instr->right()); 1096 // If we care about -0, test if the dividend is <0 and the result is 0.
1023 ASSERT(!right_reg.is(rax)); 1097 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1024 ASSERT(!right_reg.is(rdx)); 1098 Label positive_left;
1025 Register result_reg = ToRegister(instr->result()); 1099 __ testl(left_reg, left_reg);
1026 ASSERT(result_reg.is(rdx)); 1100 __ j(not_sign, &positive_left, Label::kNear);
1027 1101 __ idivl(right_reg);
1028 Label done; 1102 __ testl(result_reg, result_reg);
1029 // Check for x % 0, idiv would signal a divide error. We have to 1103 DeoptimizeIf(zero, instr->environment());
1030 // deopt in this case because we can't return a NaN. 1104 __ jmp(&done, Label::kNear);
1031 if (right->CanBeZero()) { 1105 __ bind(&positive_left);
1032 __ testl(right_reg, right_reg); 1106 }
1033 DeoptimizeIf(zero, instr->environment()); 1107 __ idivl(right_reg);
1108 __ bind(&done);
1109 }
1110
1111
1112 void LCodeGen::DoFlooringDivByPowerOf2I(LFlooringDivByPowerOf2I* instr) {
1113 Register dividend = ToRegister(instr->dividend());
1114 int32_t divisor = instr->divisor();
1115 ASSERT(dividend.is(ToRegister(instr->result())));
1116
1117 // If the divisor is positive, things are easy: There can be no deopts and we
1118 // can simply do an arithmetic right shift.
1119 if (divisor == 1) return;
1120 int32_t shift = WhichPowerOf2Abs(divisor);
1121 if (divisor > 1) {
1122 __ sarl(dividend, Immediate(shift));
1123 return;
1124 }
1125
1126 // If the divisor is negative, we have to negate and handle edge cases.
1127 Label not_kmin_int, done;
1128 __ negl(dividend);
1129 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
1130 DeoptimizeIf(zero, instr->environment());
1131 }
1132 if (instr->hydrogen()->CheckFlag(HValue::kLeftCanBeMinInt)) {
1133 // Note that we could emit branch-free code, but that would need one more
1134 // register.
1135 __ j(no_overflow, &not_kmin_int, Label::kNear);
1136 if (divisor == -1) {
1137 DeoptimizeIf(no_condition, instr->environment());
1138 } else {
1139 __ movl(dividend, Immediate(kMinInt / divisor));
1140 __ jmp(&done, Label::kNear);
1034 } 1141 }
1035 1142 }
1036 // Check for kMinInt % -1, idiv would signal a divide error. We 1143 __ bind(&not_kmin_int);
1037 // have to deopt if we care about -0, because we can't return that. 1144 __ sarl(dividend, Immediate(shift));
1038 if (left->RangeCanInclude(kMinInt) && right->RangeCanInclude(-1)) { 1145 __ bind(&done);
1039 Label no_overflow_possible; 1146 }
1040 __ cmpl(left_reg, Immediate(kMinInt)); 1147
1041 __ j(not_zero, &no_overflow_possible, Label::kNear); 1148
1042 __ cmpl(right_reg, Immediate(-1)); 1149 void LCodeGen::DoFlooringDivByConstI(LFlooringDivByConstI* instr) {
1043 if (hmod->CheckFlag(HValue::kBailoutOnMinusZero)) { 1150 Register dividend = ToRegister(instr->dividend());
1044 DeoptimizeIf(equal, instr->environment()); 1151 int32_t divisor = instr->divisor();
1045 } else { 1152 ASSERT(ToRegister(instr->result()).is(rdx));
1046 __ j(not_equal, &no_overflow_possible, Label::kNear); 1153
1047 __ Set(result_reg, 0); 1154 if (divisor == 0) {
1048 __ jmp(&done, Label::kNear);
1049 }
1050 __ bind(&no_overflow_possible);
1051 }
1052
1053 // Sign extend dividend in eax into edx:eax, since we are using only the low
1054 // 32 bits of the values.
1055 __ cdq();
1056
1057 // If we care about -0, test if the dividend is <0 and the result is 0.
1058 if (left->CanBeNegative() &&
1059 hmod->CanBeZero() &&
1060 hmod->CheckFlag(HValue::kBailoutOnMinusZero)) {
1061 Label positive_left;
1062 __ testl(left_reg, left_reg);
1063 __ j(not_sign, &positive_left, Label::kNear);
1064 __ idivl(right_reg);
1065 __ testl(result_reg, result_reg);
1066 DeoptimizeIf(zero, instr->environment());
1067 __ jmp(&done, Label::kNear);
1068 __ bind(&positive_left);
1069 }
1070 __ idivl(right_reg);
1071 __ bind(&done);
1072 }
1073 }
1074
1075
1076 void LCodeGen::DoMathFloorOfDiv(LMathFloorOfDiv* instr) {
1077 ASSERT(instr->right()->IsConstantOperand());
1078
1079 const Register dividend = ToRegister(instr->left());
1080 int32_t divisor = ToInteger32(LConstantOperand::cast(instr->right()));
1081 const Register result = ToRegister(instr->result());
1082
1083 switch (divisor) {
1084 case 0:
1085 DeoptimizeIf(no_condition, instr->environment()); 1155 DeoptimizeIf(no_condition, instr->environment());
1086 return; 1156 return;
1087 1157 }
1088 case 1: 1158
1089 if (!result.is(dividend)) { 1159 // Check for (0 / -x) that will produce negative zero.
1090 __ movl(result, dividend); 1160 HMathFloorOfDiv* hdiv = instr->hydrogen();
1091 } 1161 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
1162 __ testl(dividend, dividend);
1163 DeoptimizeIf(zero, instr->environment());
1164 }
1165
1166 __ FlooringDiv(dividend, divisor);
1167 }
1168
1169
1170 void LCodeGen::DoDivByPowerOf2I(LDivByPowerOf2I* instr) {
1171 Register dividend = ToRegister(instr->dividend());
1172 int32_t divisor = instr->divisor();
1173 Register result = ToRegister(instr->result());
1174 ASSERT(divisor == kMinInt || (divisor != 0 && IsPowerOf2(Abs(divisor))));
1175 ASSERT(!result.is(dividend));
1176
1177 // Check for (0 / -x) that will produce negative zero.
1178 HDiv* hdiv = instr->hydrogen();
1179 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
1180 __ testl(dividend, dividend);
1181 DeoptimizeIf(zero, instr->environment());
1182 }
1183 // Check for (kMinInt / -1).
1184 if (hdiv->CheckFlag(HValue::kCanOverflow) && divisor == -1) {
1185 __ cmpl(dividend, Immediate(kMinInt));
1186 DeoptimizeIf(zero, instr->environment());
1187 }
1188 // Deoptimize if remainder will not be 0.
1189 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32) &&
1190 divisor != 1 && divisor != -1) {
1191 int32_t mask = divisor < 0 ? -(divisor + 1) : (divisor - 1);
1192 __ testl(dividend, Immediate(mask));
1193 DeoptimizeIf(not_zero, instr->environment());
1194 }
1195 __ Move(result, dividend);
1196 int32_t shift = WhichPowerOf2Abs(divisor);
1197 if (shift > 0) {
1198 // The arithmetic shift is always OK, the 'if' is an optimization only.
1199 if (shift > 1) __ sarl(result, Immediate(31));
1200 __ shrl(result, Immediate(32 - shift));
1201 __ addl(result, dividend);
1202 __ sarl(result, Immediate(shift));
1203 }
1204 if (divisor < 0) __ negl(result);
1205 }
1206
1207
1208 void LCodeGen::DoDivByConstI(LDivByConstI* instr) {
1209 Register dividend = ToRegister(instr->dividend());
1210 int32_t divisor = instr->divisor();
1211 ASSERT(ToRegister(instr->result()).is(rdx));
1212
1213 if (divisor == 0) {
1214 DeoptimizeIf(no_condition, instr->environment());
1092 return; 1215 return;
1093 1216 }
1094 case -1: 1217
1095 if (!result.is(dividend)) { 1218 // Check for (0 / -x) that will produce negative zero.
1096 __ movl(result, dividend); 1219 HDiv* hdiv = instr->hydrogen();
1097 } 1220 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero) && divisor < 0) {
1098 __ negl(result); 1221 __ testl(dividend, dividend);
1099 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 1222 DeoptimizeIf(zero, instr->environment());
1100 DeoptimizeIf(zero, instr->environment()); 1223 }
1101 } 1224
1102 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { 1225 __ FlooringDiv(dividend, Abs(divisor));
1103 DeoptimizeIf(overflow, instr->environment()); 1226 __ movl(rax, dividend);
1104 } 1227 __ shrl(rax, Immediate(31));
1105 return; 1228 __ addl(rdx, rax);
1106 } 1229 if (divisor < 0) __ neg(rdx);
1107 1230
1108 uint32_t divisor_abs = abs(divisor); 1231 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) {
1109 if (IsPowerOf2(divisor_abs)) { 1232 __ movl(rax, rdx);
1110 int32_t power = WhichPowerOf2(divisor_abs); 1233 __ imull(rax, rax, Immediate(divisor));
1111 if (divisor < 0) { 1234 __ subl(rax, dividend);
1112 __ movsxlq(result, dividend); 1235 DeoptimizeIf(not_equal, instr->environment());
1113 __ neg(result);
1114 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
1115 DeoptimizeIf(zero, instr->environment());
1116 }
1117 __ sar(result, Immediate(power));
1118 } else {
1119 if (!result.is(dividend)) {
1120 __ movl(result, dividend);
1121 }
1122 __ sarl(result, Immediate(power));
1123 }
1124 } else {
1125 Register reg1 = ToRegister(instr->temp());
1126 Register reg2 = ToRegister(instr->result());
1127
1128 // Find b which: 2^b < divisor_abs < 2^(b+1).
1129 unsigned b = 31 - CompilerIntrinsics::CountLeadingZeros(divisor_abs);
1130 unsigned shift = 32 + b; // Precision +1bit (effectively).
1131 double multiplier_f =
1132 static_cast<double>(static_cast<uint64_t>(1) << shift) / divisor_abs;
1133 int64_t multiplier;
1134 if (multiplier_f - std::floor(multiplier_f) < 0.5) {
1135 multiplier = static_cast<int64_t>(std::floor(multiplier_f));
1136 } else {
1137 multiplier = static_cast<int64_t>(std::floor(multiplier_f)) + 1;
1138 }
1139 // The multiplier is a uint32.
1140 ASSERT(multiplier > 0 &&
1141 multiplier < (static_cast<int64_t>(1) << 32));
1142 // The multiply is int64, so sign-extend to r64.
1143 __ movsxlq(reg1, dividend);
1144 if (divisor < 0 &&
1145 instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
1146 __ neg(reg1);
1147 DeoptimizeIf(zero, instr->environment());
1148 }
1149 __ Set(reg2, multiplier);
1150 // Result just fit in r64, because it's int32 * uint32.
1151 __ imul(reg2, reg1);
1152
1153 __ addq(reg2, Immediate(1 << 30));
1154 __ sar(reg2, Immediate(shift));
1155 } 1236 }
1156 } 1237 }
1157 1238
1158 1239
1159 void LCodeGen::DoDivI(LDivI* instr) { 1240 void LCodeGen::DoDivI(LDivI* instr) {
1160 if (!instr->is_flooring() && instr->hydrogen()->RightIsPowerOf2()) { 1241 HBinaryOperation* hdiv = instr->hydrogen();
1161 Register dividend = ToRegister(instr->left()); 1242 Register dividend = ToRegister(instr->left());
1162 HDiv* hdiv = instr->hydrogen(); 1243 Register divisor = ToRegister(instr->right());
1163 int32_t divisor = hdiv->right()->GetInteger32Constant(); 1244 Register remainder = ToRegister(instr->temp());
1164 Register result = ToRegister(instr->result()); 1245 Register result = ToRegister(instr->result());
1165 ASSERT(!result.is(dividend)); 1246 ASSERT(dividend.is(rax));
1166 1247 ASSERT(remainder.is(rdx));
1167 // Check for (0 / -x) that will produce negative zero. 1248 ASSERT(result.is(rax));
1168 if (hdiv->left()->RangeCanInclude(0) && divisor < 0 && 1249 ASSERT(!divisor.is(rax));
1169 hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) { 1250 ASSERT(!divisor.is(rdx));
1170 __ testl(dividend, dividend);
1171 DeoptimizeIf(zero, instr->environment());
1172 }
1173 // Check for (kMinInt / -1).
1174 if (hdiv->left()->RangeCanInclude(kMinInt) && divisor == -1 &&
1175 hdiv->CheckFlag(HValue::kCanOverflow)) {
1176 __ cmpl(dividend, Immediate(kMinInt));
1177 DeoptimizeIf(zero, instr->environment());
1178 }
1179 // Deoptimize if remainder will not be 0.
1180 if (!hdiv->CheckFlag(HInstruction::kAllUsesTruncatingToInt32)) {
1181 __ testl(dividend, Immediate(Abs(divisor) - 1));
1182 DeoptimizeIf(not_zero, instr->environment());
1183 }
1184 __ Move(result, dividend);
1185 int32_t shift = WhichPowerOf2(Abs(divisor));
1186 if (shift > 0) {
1187 // The arithmetic shift is always OK, the 'if' is an optimization only.
1188 if (shift > 1) __ sarl(result, Immediate(31));
1189 __ shrl(result, Immediate(32 - shift));
1190 __ addl(result, dividend);
1191 __ sarl(result, Immediate(shift));
1192 }
1193 if (divisor < 0) __ negl(result);
1194 return;
1195 }
1196
1197 LOperand* right = instr->right();
1198 ASSERT(ToRegister(instr->result()).is(rax));
1199 ASSERT(ToRegister(instr->left()).is(rax));
1200 ASSERT(!ToRegister(instr->right()).is(rax));
1201 ASSERT(!ToRegister(instr->right()).is(rdx));
1202
1203 Register left_reg = rax;
1204 1251
1205 // Check for x / 0. 1252 // Check for x / 0.
1206 Register right_reg = ToRegister(right); 1253 if (hdiv->CheckFlag(HValue::kCanBeDivByZero)) {
1207 if (instr->hydrogen_value()->CheckFlag(HValue::kCanBeDivByZero)) { 1254 __ testl(divisor, divisor);
1208 __ testl(right_reg, right_reg);
1209 DeoptimizeIf(zero, instr->environment()); 1255 DeoptimizeIf(zero, instr->environment());
1210 } 1256 }
1211 1257
1212 // Check for (0 / -x) that will produce negative zero. 1258 // Check for (0 / -x) that will produce negative zero.
1213 if (instr->hydrogen_value()->CheckFlag(HValue::kBailoutOnMinusZero)) { 1259 if (hdiv->CheckFlag(HValue::kBailoutOnMinusZero)) {
1214 Label left_not_zero; 1260 Label dividend_not_zero;
1215 __ testl(left_reg, left_reg); 1261 __ testl(dividend, dividend);
1216 __ j(not_zero, &left_not_zero, Label::kNear); 1262 __ j(not_zero, &dividend_not_zero, Label::kNear);
1217 __ testl(right_reg, right_reg); 1263 __ testl(divisor, divisor);
1218 DeoptimizeIf(sign, instr->environment()); 1264 DeoptimizeIf(sign, instr->environment());
1219 __ bind(&left_not_zero); 1265 __ bind(&dividend_not_zero);
1220 } 1266 }
1221 1267
1222 // Check for (kMinInt / -1). 1268 // Check for (kMinInt / -1).
1223 if (instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow)) { 1269 if (hdiv->CheckFlag(HValue::kCanOverflow)) {
1224 Label left_not_min_int; 1270 Label dividend_not_min_int;
1225 __ cmpl(left_reg, Immediate(kMinInt)); 1271 __ cmpl(dividend, Immediate(kMinInt));
1226 __ j(not_zero, &left_not_min_int, Label::kNear); 1272 __ j(not_zero, &dividend_not_min_int, Label::kNear);
1227 __ cmpl(right_reg, Immediate(-1)); 1273 __ cmpl(divisor, Immediate(-1));
1228 DeoptimizeIf(zero, instr->environment()); 1274 DeoptimizeIf(zero, instr->environment());
1229 __ bind(&left_not_min_int); 1275 __ bind(&dividend_not_min_int);
1230 } 1276 }
1231 1277
1232 // Sign extend to rdx. 1278 // Sign extend to rdx (= remainder).
1233 __ cdq(); 1279 __ cdq();
1234 __ idivl(right_reg); 1280 __ idivl(divisor);
1235 1281
1236 if (instr->is_flooring()) { 1282 if (hdiv->IsMathFloorOfDiv()) {
1237 Label done; 1283 Label done;
1238 __ testl(rdx, rdx); 1284 __ testl(remainder, remainder);
1239 __ j(zero, &done, Label::kNear); 1285 __ j(zero, &done, Label::kNear);
1240 __ xorl(rdx, right_reg); 1286 __ xorl(remainder, divisor);
1241 __ sarl(rdx, Immediate(31)); 1287 __ sarl(remainder, Immediate(31));
1242 __ addl(rax, rdx); 1288 __ addl(result, remainder);
1243 __ bind(&done); 1289 __ bind(&done);
1244 } else if (!instr->hydrogen()->CheckFlag( 1290 } else if (!hdiv->CheckFlag(HValue::kAllUsesTruncatingToInt32)) {
1245 HInstruction::kAllUsesTruncatingToInt32)) {
1246 // Deoptimize if remainder is not 0. 1291 // Deoptimize if remainder is not 0.
1247 __ testl(rdx, rdx); 1292 __ testl(remainder, remainder);
1248 DeoptimizeIf(not_zero, instr->environment()); 1293 DeoptimizeIf(not_zero, instr->environment());
1249 } 1294 }
1250 } 1295 }
1251 1296
1252 1297
1253 void LCodeGen::DoMulI(LMulI* instr) { 1298 void LCodeGen::DoMulI(LMulI* instr) {
1254 Register left = ToRegister(instr->left()); 1299 Register left = ToRegister(instr->left());
1255 LOperand* right = instr->right(); 1300 LOperand* right = instr->right();
1256 1301
1257 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 1302 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
(...skipping 597 matching lines...) Expand 10 before | Expand all | Expand 10 after
1855 1900
1856 1901
1857 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { 1902 void LCodeGen::DoArithmeticT(LArithmeticT* instr) {
1858 ASSERT(ToRegister(instr->context()).is(rsi)); 1903 ASSERT(ToRegister(instr->context()).is(rsi));
1859 ASSERT(ToRegister(instr->left()).is(rdx)); 1904 ASSERT(ToRegister(instr->left()).is(rdx));
1860 ASSERT(ToRegister(instr->right()).is(rax)); 1905 ASSERT(ToRegister(instr->right()).is(rax));
1861 ASSERT(ToRegister(instr->result()).is(rax)); 1906 ASSERT(ToRegister(instr->result()).is(rax));
1862 1907
1863 BinaryOpICStub stub(instr->op(), NO_OVERWRITE); 1908 BinaryOpICStub stub(instr->op(), NO_OVERWRITE);
1864 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); 1909 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
1865 __ nop(); // Signals no inlined code.
1866 } 1910 }
1867 1911
1868 1912
1869 template<class InstrType> 1913 template<class InstrType>
1870 void LCodeGen::EmitBranch(InstrType instr, Condition cc) { 1914 void LCodeGen::EmitBranch(InstrType instr, Condition cc) {
1871 int left_block = instr->TrueDestination(chunk_); 1915 int left_block = instr->TrueDestination(chunk_);
1872 int right_block = instr->FalseDestination(chunk_); 1916 int right_block = instr->FalseDestination(chunk_);
1873 1917
1874 int next_block = GetNextEmittedBlock(); 1918 int next_block = GetNextEmittedBlock();
1875 1919
(...skipping 1067 matching lines...) Expand 10 before | Expand all | Expand 10 after
2943 case EXTERNAL_FLOAT64_ELEMENTS: 2987 case EXTERNAL_FLOAT64_ELEMENTS:
2944 case FLOAT32_ELEMENTS: 2988 case FLOAT32_ELEMENTS:
2945 case FLOAT64_ELEMENTS: 2989 case FLOAT64_ELEMENTS:
2946 case FAST_ELEMENTS: 2990 case FAST_ELEMENTS:
2947 case FAST_SMI_ELEMENTS: 2991 case FAST_SMI_ELEMENTS:
2948 case FAST_DOUBLE_ELEMENTS: 2992 case FAST_DOUBLE_ELEMENTS:
2949 case FAST_HOLEY_ELEMENTS: 2993 case FAST_HOLEY_ELEMENTS:
2950 case FAST_HOLEY_SMI_ELEMENTS: 2994 case FAST_HOLEY_SMI_ELEMENTS:
2951 case FAST_HOLEY_DOUBLE_ELEMENTS: 2995 case FAST_HOLEY_DOUBLE_ELEMENTS:
2952 case DICTIONARY_ELEMENTS: 2996 case DICTIONARY_ELEMENTS:
2953 case NON_STRICT_ARGUMENTS_ELEMENTS: 2997 case SLOPPY_ARGUMENTS_ELEMENTS:
2954 UNREACHABLE(); 2998 UNREACHABLE();
2955 break; 2999 break;
2956 } 3000 }
2957 } 3001 }
2958 } 3002 }
2959 3003
2960 3004
2961 void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) { 3005 void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) {
2962 XMMRegister result(ToDoubleRegister(instr->result())); 3006 XMMRegister result(ToDoubleRegister(instr->result()));
2963 LOperand* key = instr->key(); 3007 LOperand* key = instr->key();
(...skipping 589 matching lines...) Expand 10 before | Expand all | Expand 10 after
3553 3597
3554 __ bind(&done); 3598 __ bind(&done);
3555 } 3599 }
3556 } 3600 }
3557 3601
3558 3602
3559 void LCodeGen::DoMathRound(LMathRound* instr) { 3603 void LCodeGen::DoMathRound(LMathRound* instr) {
3560 const XMMRegister xmm_scratch = double_scratch0(); 3604 const XMMRegister xmm_scratch = double_scratch0();
3561 Register output_reg = ToRegister(instr->result()); 3605 Register output_reg = ToRegister(instr->result());
3562 XMMRegister input_reg = ToDoubleRegister(instr->value()); 3606 XMMRegister input_reg = ToDoubleRegister(instr->value());
3607 XMMRegister input_temp = ToDoubleRegister(instr->temp());
3563 static int64_t one_half = V8_INT64_C(0x3FE0000000000000); // 0.5 3608 static int64_t one_half = V8_INT64_C(0x3FE0000000000000); // 0.5
3564 static int64_t minus_one_half = V8_INT64_C(0xBFE0000000000000); // -0.5 3609 static int64_t minus_one_half = V8_INT64_C(0xBFE0000000000000); // -0.5
3565 3610
3566 Label done, round_to_zero, below_one_half, do_not_compensate, restore; 3611 Label done, round_to_zero, below_one_half;
3567 Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear; 3612 Label::Distance dist = DeoptEveryNTimes() ? Label::kFar : Label::kNear;
3568 __ movq(kScratchRegister, one_half); 3613 __ movq(kScratchRegister, one_half);
3569 __ movq(xmm_scratch, kScratchRegister); 3614 __ movq(xmm_scratch, kScratchRegister);
3570 __ ucomisd(xmm_scratch, input_reg); 3615 __ ucomisd(xmm_scratch, input_reg);
3571 __ j(above, &below_one_half, Label::kNear); 3616 __ j(above, &below_one_half, Label::kNear);
3572 3617
3573 // CVTTSD2SI rounds towards zero, since 0.5 <= x, we use floor(0.5 + x). 3618 // CVTTSD2SI rounds towards zero, since 0.5 <= x, we use floor(0.5 + x).
3574 __ addsd(xmm_scratch, input_reg); 3619 __ addsd(xmm_scratch, input_reg);
3575 __ cvttsd2si(output_reg, xmm_scratch); 3620 __ cvttsd2si(output_reg, xmm_scratch);
3576 // Overflow is signalled with minint. 3621 // Overflow is signalled with minint.
3577 __ cmpl(output_reg, Immediate(0x80000000)); 3622 __ cmpl(output_reg, Immediate(0x80000000));
3578 __ RecordComment("D2I conversion overflow"); 3623 __ RecordComment("D2I conversion overflow");
3579 DeoptimizeIf(equal, instr->environment()); 3624 DeoptimizeIf(equal, instr->environment());
3580 __ jmp(&done, dist); 3625 __ jmp(&done, dist);
3581 3626
3582 __ bind(&below_one_half); 3627 __ bind(&below_one_half);
3583 __ movq(kScratchRegister, minus_one_half); 3628 __ movq(kScratchRegister, minus_one_half);
3584 __ movq(xmm_scratch, kScratchRegister); 3629 __ movq(xmm_scratch, kScratchRegister);
3585 __ ucomisd(xmm_scratch, input_reg); 3630 __ ucomisd(xmm_scratch, input_reg);
3586 __ j(below_equal, &round_to_zero, Label::kNear); 3631 __ j(below_equal, &round_to_zero, Label::kNear);
3587 3632
3588 // CVTTSD2SI rounds towards zero, we use ceil(x - (-0.5)) and then 3633 // CVTTSD2SI rounds towards zero, we use ceil(x - (-0.5)) and then
3589 // compare and compensate. 3634 // compare and compensate.
3590 __ movq(kScratchRegister, input_reg); // Back up input_reg. 3635 __ movq(input_temp, input_reg); // Do not alter input_reg.
3591 __ subsd(input_reg, xmm_scratch); 3636 __ subsd(input_temp, xmm_scratch);
3592 __ cvttsd2si(output_reg, input_reg); 3637 __ cvttsd2si(output_reg, input_temp);
3593 // Catch minint due to overflow, and to prevent overflow when compensating. 3638 // Catch minint due to overflow, and to prevent overflow when compensating.
3594 __ cmpl(output_reg, Immediate(0x80000000)); 3639 __ cmpl(output_reg, Immediate(0x80000000));
3595 __ RecordComment("D2I conversion overflow"); 3640 __ RecordComment("D2I conversion overflow");
3596 DeoptimizeIf(equal, instr->environment()); 3641 DeoptimizeIf(equal, instr->environment());
3597 3642
3598 __ Cvtlsi2sd(xmm_scratch, output_reg); 3643 __ Cvtlsi2sd(xmm_scratch, output_reg);
3599 __ ucomisd(input_reg, xmm_scratch); 3644 __ ucomisd(xmm_scratch, input_temp);
3600 __ j(equal, &restore, Label::kNear); 3645 __ j(equal, &done, dist);
3601 __ subl(output_reg, Immediate(1)); 3646 __ subl(output_reg, Immediate(1));
3602 // No overflow because we already ruled out minint. 3647 // No overflow because we already ruled out minint.
3603 __ bind(&restore);
3604 __ movq(input_reg, kScratchRegister); // Restore input_reg.
3605 __ jmp(&done, dist); 3648 __ jmp(&done, dist);
3606 3649
3607 __ bind(&round_to_zero); 3650 __ bind(&round_to_zero);
3608 // We return 0 for the input range [+0, 0.5[, or [-0.5, 0.5[ if 3651 // We return 0 for the input range [+0, 0.5[, or [-0.5, 0.5[ if
3609 // we can ignore the difference between a result of -0 and +0. 3652 // we can ignore the difference between a result of -0 and +0.
3610 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { 3653 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) {
3611 __ movq(output_reg, input_reg); 3654 __ movq(output_reg, input_reg);
3612 __ testq(output_reg, output_reg); 3655 __ testq(output_reg, output_reg);
3613 __ RecordComment("Minus zero"); 3656 __ RecordComment("Minus zero");
3614 DeoptimizeIf(negative, instr->environment()); 3657 DeoptimizeIf(negative, instr->environment());
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
3782 } 3825 }
3783 3826
3784 3827
3785 void LCodeGen::DoCallNew(LCallNew* instr) { 3828 void LCodeGen::DoCallNew(LCallNew* instr) {
3786 ASSERT(ToRegister(instr->context()).is(rsi)); 3829 ASSERT(ToRegister(instr->context()).is(rsi));
3787 ASSERT(ToRegister(instr->constructor()).is(rdi)); 3830 ASSERT(ToRegister(instr->constructor()).is(rdi));
3788 ASSERT(ToRegister(instr->result()).is(rax)); 3831 ASSERT(ToRegister(instr->result()).is(rax));
3789 3832
3790 __ Set(rax, instr->arity()); 3833 __ Set(rax, instr->arity());
3791 // No cell in ebx for construct type feedback in optimized code 3834 // No cell in ebx for construct type feedback in optimized code
3792 Handle<Object> undefined_value(isolate()->factory()->undefined_value()); 3835 Handle<Object> megamorphic_symbol =
3793 __ Move(rbx, undefined_value); 3836 TypeFeedbackInfo::MegamorphicSentinel(isolate());
3837 __ Move(rbx, megamorphic_symbol);
3794 CallConstructStub stub(NO_CALL_FUNCTION_FLAGS); 3838 CallConstructStub stub(NO_CALL_FUNCTION_FLAGS);
3795 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); 3839 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
3796 } 3840 }
3797 3841
3798 3842
3799 void LCodeGen::DoCallNewArray(LCallNewArray* instr) { 3843 void LCodeGen::DoCallNewArray(LCallNewArray* instr) {
3800 ASSERT(ToRegister(instr->context()).is(rsi)); 3844 ASSERT(ToRegister(instr->context()).is(rsi));
3801 ASSERT(ToRegister(instr->constructor()).is(rdi)); 3845 ASSERT(ToRegister(instr->constructor()).is(rdi));
3802 ASSERT(ToRegister(instr->result()).is(rax)); 3846 ASSERT(ToRegister(instr->result()).is(rax));
3803 3847
3804 __ Set(rax, instr->arity()); 3848 __ Set(rax, instr->arity());
3805 __ Move(rbx, factory()->undefined_value()); 3849 __ Move(rbx, TypeFeedbackInfo::MegamorphicSentinel(isolate()));
3806 ElementsKind kind = instr->hydrogen()->elements_kind(); 3850 ElementsKind kind = instr->hydrogen()->elements_kind();
3807 AllocationSiteOverrideMode override_mode = 3851 AllocationSiteOverrideMode override_mode =
3808 (AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE) 3852 (AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE)
3809 ? DISABLE_ALLOCATION_SITES 3853 ? DISABLE_ALLOCATION_SITES
3810 : DONT_OVERRIDE; 3854 : DONT_OVERRIDE;
3811 3855
3812 if (instr->arity() == 0) { 3856 if (instr->arity() == 0) {
3813 ArrayNoArgumentConstructorStub stub(kind, override_mode); 3857 ArrayNoArgumentConstructorStub stub(kind, override_mode);
3814 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); 3858 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr);
3815 } else if (instr->arity() == 1) { 3859 } else if (instr->arity() == 1) {
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
3885 __ Store(MemOperand(object, offset), value, representation); 3929 __ Store(MemOperand(object, offset), value, representation);
3886 } 3930 }
3887 return; 3931 return;
3888 } 3932 }
3889 3933
3890 Register object = ToRegister(instr->object()); 3934 Register object = ToRegister(instr->object());
3891 Handle<Map> transition = instr->transition(); 3935 Handle<Map> transition = instr->transition();
3892 SmiCheck check_needed = hinstr->value()->IsHeapObject() 3936 SmiCheck check_needed = hinstr->value()->IsHeapObject()
3893 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; 3937 ? OMIT_SMI_CHECK : INLINE_SMI_CHECK;
3894 3938
3895 if (FLAG_track_fields && representation.IsSmi()) { 3939 if (representation.IsSmi()) {
3896 if (instr->value()->IsConstantOperand()) { 3940 if (instr->value()->IsConstantOperand()) {
3897 LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); 3941 LConstantOperand* operand_value = LConstantOperand::cast(instr->value());
3898 if (!IsInteger32Constant(operand_value) && 3942 if (!IsInteger32Constant(operand_value) &&
3899 !IsSmiConstant(operand_value)) { 3943 !IsSmiConstant(operand_value)) {
3900 DeoptimizeIf(no_condition, instr->environment()); 3944 DeoptimizeIf(no_condition, instr->environment());
3901 } 3945 }
3902 } 3946 }
3903 } else if (FLAG_track_heap_object_fields && representation.IsHeapObject()) { 3947 } else if (representation.IsHeapObject()) {
3904 if (instr->value()->IsConstantOperand()) { 3948 if (instr->value()->IsConstantOperand()) {
3905 LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); 3949 LConstantOperand* operand_value = LConstantOperand::cast(instr->value());
3906 if (IsInteger32Constant(operand_value)) { 3950 if (IsInteger32Constant(operand_value)) {
3907 DeoptimizeIf(no_condition, instr->environment()); 3951 DeoptimizeIf(no_condition, instr->environment());
3908 } 3952 }
3909 } else { 3953 } else {
3910 if (!hinstr->value()->type().IsHeapObject()) { 3954 if (!hinstr->value()->type().IsHeapObject()) {
3911 Register value = ToRegister(instr->value()); 3955 Register value = ToRegister(instr->value());
3912 Condition cc = masm()->CheckSmi(value); 3956 Condition cc = masm()->CheckSmi(value);
3913 DeoptimizeIf(cc, instr->environment()); 3957 DeoptimizeIf(cc, instr->environment());
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
4003 } 4047 }
4004 } 4048 }
4005 4049
4006 4050
4007 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { 4051 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) {
4008 ASSERT(ToRegister(instr->context()).is(rsi)); 4052 ASSERT(ToRegister(instr->context()).is(rsi));
4009 ASSERT(ToRegister(instr->object()).is(rdx)); 4053 ASSERT(ToRegister(instr->object()).is(rdx));
4010 ASSERT(ToRegister(instr->value()).is(rax)); 4054 ASSERT(ToRegister(instr->value()).is(rax));
4011 4055
4012 __ Move(rcx, instr->hydrogen()->name()); 4056 __ Move(rcx, instr->hydrogen()->name());
4013 Handle<Code> ic = StoreIC::initialize_stub(isolate(), 4057 Handle<Code> ic = StoreIC::initialize_stub(isolate(), instr->strict_mode());
4014 instr->strict_mode_flag());
4015 CallCode(ic, RelocInfo::CODE_TARGET, instr); 4058 CallCode(ic, RelocInfo::CODE_TARGET, instr);
4016 } 4059 }
4017 4060
4018 4061
4019 void LCodeGen::ApplyCheckIf(Condition cc, LBoundsCheck* check) { 4062 void LCodeGen::ApplyCheckIf(Condition cc, LBoundsCheck* check) {
4020 if (FLAG_debug_code && check->hydrogen()->skip_check()) { 4063 if (FLAG_debug_code && check->hydrogen()->skip_check()) {
4021 Label done; 4064 Label done;
4022 __ j(NegateCondition(cc), &done, Label::kNear); 4065 __ j(NegateCondition(cc), &done, Label::kNear);
4023 __ int3(); 4066 __ int3();
4024 __ bind(&done); 4067 __ bind(&done);
4025 } else { 4068 } else {
4026 DeoptimizeIf(cc, check->environment()); 4069 DeoptimizeIf(cc, check->environment());
4027 } 4070 }
4028 } 4071 }
4029 4072
4030 4073
4031 void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) { 4074 void LCodeGen::DoBoundsCheck(LBoundsCheck* instr) {
4032 if (instr->hydrogen()->skip_check()) return; 4075 HBoundsCheck* hinstr = instr->hydrogen();
4076 if (hinstr->skip_check()) return;
4077
4078 Representation representation = hinstr->length()->representation();
4079 ASSERT(representation.Equals(hinstr->index()->representation()));
4080 ASSERT(representation.IsSmiOrInteger32());
4033 4081
4034 if (instr->length()->IsRegister()) { 4082 if (instr->length()->IsRegister()) {
4035 Register reg = ToRegister(instr->length()); 4083 Register reg = ToRegister(instr->length());
4036 if (!instr->hydrogen()->length()->representation().IsSmi()) { 4084
4037 __ AssertZeroExtended(reg);
4038 }
4039 if (instr->index()->IsConstantOperand()) { 4085 if (instr->index()->IsConstantOperand()) {
4040 int32_t constant_index = 4086 int32_t constant_index =
4041 ToInteger32(LConstantOperand::cast(instr->index())); 4087 ToInteger32(LConstantOperand::cast(instr->index()));
4042 if (instr->hydrogen()->length()->representation().IsSmi()) { 4088 if (representation.IsSmi()) {
4043 __ Cmp(reg, Smi::FromInt(constant_index)); 4089 __ Cmp(reg, Smi::FromInt(constant_index));
4044 } else { 4090 } else {
4045 __ cmpq(reg, Immediate(constant_index)); 4091 __ cmpl(reg, Immediate(constant_index));
4046 } 4092 }
4047 } else { 4093 } else {
4048 Register reg2 = ToRegister(instr->index()); 4094 Register reg2 = ToRegister(instr->index());
4049 if (!instr->hydrogen()->index()->representation().IsSmi()) { 4095 if (representation.IsSmi()) {
4050 __ AssertZeroExtended(reg2); 4096 __ cmpq(reg, reg2);
4097 } else {
4098 __ cmpl(reg, reg2);
4051 } 4099 }
4052 __ cmpq(reg, reg2);
4053 } 4100 }
4054 } else { 4101 } else {
4055 Operand length = ToOperand(instr->length()); 4102 Operand length = ToOperand(instr->length());
4056 if (instr->index()->IsConstantOperand()) { 4103 if (instr->index()->IsConstantOperand()) {
4057 int32_t constant_index = 4104 int32_t constant_index =
4058 ToInteger32(LConstantOperand::cast(instr->index())); 4105 ToInteger32(LConstantOperand::cast(instr->index()));
4059 if (instr->hydrogen()->length()->representation().IsSmi()) { 4106 if (representation.IsSmi()) {
4060 __ Cmp(length, Smi::FromInt(constant_index)); 4107 __ Cmp(length, Smi::FromInt(constant_index));
4061 } else { 4108 } else {
4062 __ cmpq(length, Immediate(constant_index)); 4109 __ cmpl(length, Immediate(constant_index));
4063 } 4110 }
4064 } else { 4111 } else {
4065 __ cmpq(length, ToRegister(instr->index())); 4112 if (representation.IsSmi()) {
4113 __ cmpq(length, ToRegister(instr->index()));
4114 } else {
4115 __ cmpl(length, ToRegister(instr->index()));
4116 }
4066 } 4117 }
4067 } 4118 }
4068 Condition condition = 4119 Condition condition = hinstr->allow_equality() ? below : below_equal;
4069 instr->hydrogen()->allow_equality() ? below : below_equal;
4070 ApplyCheckIf(condition, instr); 4120 ApplyCheckIf(condition, instr);
4071 } 4121 }
4072 4122
4073 4123
4074 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) { 4124 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) {
4075 ElementsKind elements_kind = instr->elements_kind(); 4125 ElementsKind elements_kind = instr->elements_kind();
4076 LOperand* key = instr->key(); 4126 LOperand* key = instr->key();
4077 if (!key->IsConstantOperand()) { 4127 if (!key->IsConstantOperand()) {
4078 Register key_reg = ToRegister(key); 4128 Register key_reg = ToRegister(key);
4079 // Even though the HLoad/StoreKeyedFastElement instructions force 4129 // Even though the HLoad/StoreKeyedFastElement instructions force
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
4132 case EXTERNAL_FLOAT64_ELEMENTS: 4182 case EXTERNAL_FLOAT64_ELEMENTS:
4133 case FLOAT32_ELEMENTS: 4183 case FLOAT32_ELEMENTS:
4134 case FLOAT64_ELEMENTS: 4184 case FLOAT64_ELEMENTS:
4135 case FAST_ELEMENTS: 4185 case FAST_ELEMENTS:
4136 case FAST_SMI_ELEMENTS: 4186 case FAST_SMI_ELEMENTS:
4137 case FAST_DOUBLE_ELEMENTS: 4187 case FAST_DOUBLE_ELEMENTS:
4138 case FAST_HOLEY_ELEMENTS: 4188 case FAST_HOLEY_ELEMENTS:
4139 case FAST_HOLEY_SMI_ELEMENTS: 4189 case FAST_HOLEY_SMI_ELEMENTS:
4140 case FAST_HOLEY_DOUBLE_ELEMENTS: 4190 case FAST_HOLEY_DOUBLE_ELEMENTS:
4141 case DICTIONARY_ELEMENTS: 4191 case DICTIONARY_ELEMENTS:
4142 case NON_STRICT_ARGUMENTS_ELEMENTS: 4192 case SLOPPY_ARGUMENTS_ELEMENTS:
4143 UNREACHABLE(); 4193 UNREACHABLE();
4144 break; 4194 break;
4145 } 4195 }
4146 } 4196 }
4147 } 4197 }
4148 4198
4149 4199
4150 void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) { 4200 void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) {
4151 XMMRegister value = ToDoubleRegister(instr->value()); 4201 XMMRegister value = ToDoubleRegister(instr->value());
4152 LOperand* key = instr->key(); 4202 LOperand* key = instr->key();
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
4283 } 4333 }
4284 } 4334 }
4285 4335
4286 4336
4287 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { 4337 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) {
4288 ASSERT(ToRegister(instr->context()).is(rsi)); 4338 ASSERT(ToRegister(instr->context()).is(rsi));
4289 ASSERT(ToRegister(instr->object()).is(rdx)); 4339 ASSERT(ToRegister(instr->object()).is(rdx));
4290 ASSERT(ToRegister(instr->key()).is(rcx)); 4340 ASSERT(ToRegister(instr->key()).is(rcx));
4291 ASSERT(ToRegister(instr->value()).is(rax)); 4341 ASSERT(ToRegister(instr->value()).is(rax));
4292 4342
4293 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) 4343 Handle<Code> ic = instr->strict_mode() == STRICT
4294 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() 4344 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict()
4295 : isolate()->builtins()->KeyedStoreIC_Initialize(); 4345 : isolate()->builtins()->KeyedStoreIC_Initialize();
4296 CallCode(ic, RelocInfo::CODE_TARGET, instr); 4346 CallCode(ic, RelocInfo::CODE_TARGET, instr);
4297 } 4347 }
4298 4348
4299 4349
4300 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { 4350 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) {
4301 Register object_reg = ToRegister(instr->object()); 4351 Register object_reg = ToRegister(instr->object());
4302 4352
4303 Handle<Map> from_map = instr->original_map(); 4353 Handle<Map> from_map = instr->original_map();
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
4464 LOperand* output = instr->result(); 4514 LOperand* output = instr->result();
4465 ASSERT(output->IsDoubleRegister()); 4515 ASSERT(output->IsDoubleRegister());
4466 if (input->IsRegister()) { 4516 if (input->IsRegister()) {
4467 __ Cvtlsi2sd(ToDoubleRegister(output), ToRegister(input)); 4517 __ Cvtlsi2sd(ToDoubleRegister(output), ToRegister(input));
4468 } else { 4518 } else {
4469 __ Cvtlsi2sd(ToDoubleRegister(output), ToOperand(input)); 4519 __ Cvtlsi2sd(ToDoubleRegister(output), ToOperand(input));
4470 } 4520 }
4471 } 4521 }
4472 4522
4473 4523
4474 void LCodeGen::DoInteger32ToSmi(LInteger32ToSmi* instr) {
4475 LOperand* input = instr->value();
4476 ASSERT(input->IsRegister());
4477 LOperand* output = instr->result();
4478 __ Integer32ToSmi(ToRegister(output), ToRegister(input));
4479 if (!instr->hydrogen()->value()->HasRange() ||
4480 !instr->hydrogen()->value()->range()->IsInSmiRange()) {
4481 DeoptimizeIf(overflow, instr->environment());
4482 }
4483 }
4484
4485
4486 void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) { 4524 void LCodeGen::DoUint32ToDouble(LUint32ToDouble* instr) {
4487 LOperand* input = instr->value(); 4525 LOperand* input = instr->value();
4488 LOperand* output = instr->result(); 4526 LOperand* output = instr->result();
4489 LOperand* temp = instr->temp(); 4527 LOperand* temp = instr->temp();
4490 4528
4491 __ LoadUint32(ToDoubleRegister(output), 4529 __ LoadUint32(ToDoubleRegister(output),
4492 ToRegister(input), 4530 ToRegister(input),
4493 ToDoubleRegister(temp)); 4531 ToDoubleRegister(temp));
4494 } 4532 }
4495 4533
4496 4534
4497 void LCodeGen::DoUint32ToSmi(LUint32ToSmi* instr) {
4498 LOperand* input = instr->value();
4499 ASSERT(input->IsRegister());
4500 LOperand* output = instr->result();
4501 if (!instr->hydrogen()->value()->HasRange() ||
4502 !instr->hydrogen()->value()->range()->IsInSmiRange() ||
4503 instr->hydrogen()->value()->range()->upper() == kMaxInt) {
4504 // The Range class can't express upper bounds in the (kMaxInt, kMaxUint32]
4505 // interval, so we treat kMaxInt as a sentinel for this entire interval.
4506 __ testl(ToRegister(input), Immediate(0x80000000));
4507 DeoptimizeIf(not_zero, instr->environment());
4508 }
4509 __ Integer32ToSmi(ToRegister(output), ToRegister(input));
4510 }
4511
4512
4513 void LCodeGen::DoNumberTagI(LNumberTagI* instr) { 4535 void LCodeGen::DoNumberTagI(LNumberTagI* instr) {
4514 LOperand* input = instr->value(); 4536 LOperand* input = instr->value();
4515 ASSERT(input->IsRegister() && input->Equals(instr->result())); 4537 ASSERT(input->IsRegister() && input->Equals(instr->result()));
4516 Register reg = ToRegister(input); 4538 Register reg = ToRegister(input);
4517 4539
4518 __ Integer32ToSmi(reg, reg); 4540 __ Integer32ToSmi(reg, reg);
4519 } 4541 }
4520 4542
4521 4543
4522 void LCodeGen::DoNumberTagU(LNumberTagU* instr) { 4544 void LCodeGen::DoNumberTagU(LNumberTagU* instr) {
(...skipping 15 matching lines...) Expand all
4538 4560
4539 DeferredNumberTagU* deferred = new(zone()) DeferredNumberTagU(this, instr); 4561 DeferredNumberTagU* deferred = new(zone()) DeferredNumberTagU(this, instr);
4540 __ cmpl(reg, Immediate(Smi::kMaxValue)); 4562 __ cmpl(reg, Immediate(Smi::kMaxValue));
4541 __ j(above, deferred->entry()); 4563 __ j(above, deferred->entry());
4542 __ Integer32ToSmi(reg, reg); 4564 __ Integer32ToSmi(reg, reg);
4543 __ bind(deferred->exit()); 4565 __ bind(deferred->exit());
4544 } 4566 }
4545 4567
4546 4568
4547 void LCodeGen::DoDeferredNumberTagU(LNumberTagU* instr) { 4569 void LCodeGen::DoDeferredNumberTagU(LNumberTagU* instr) {
4548 Label slow; 4570 Label done, slow;
4549 Register reg = ToRegister(instr->value()); 4571 Register reg = ToRegister(instr->value());
4550 Register tmp = reg.is(rax) ? rcx : rax; 4572 Register tmp = ToRegister(instr->temp1());
4551 XMMRegister temp_xmm = ToDoubleRegister(instr->temp()); 4573 XMMRegister temp_xmm = ToDoubleRegister(instr->temp2());
4552 4574
4553 // Preserve the value of all registers.
4554 PushSafepointRegistersScope scope(this);
4555
4556 Label done;
4557 // Load value into temp_xmm which will be preserved across potential call to 4575 // Load value into temp_xmm which will be preserved across potential call to
4558 // runtime (MacroAssembler::EnterExitFrameEpilogue preserves only allocatable 4576 // runtime (MacroAssembler::EnterExitFrameEpilogue preserves only allocatable
4559 // XMM registers on x64). 4577 // XMM registers on x64).
4560 XMMRegister xmm_scratch = double_scratch0(); 4578 XMMRegister xmm_scratch = double_scratch0();
4561 __ LoadUint32(temp_xmm, reg, xmm_scratch); 4579 __ LoadUint32(temp_xmm, reg, xmm_scratch);
4562 4580
4563 if (FLAG_inline_new) { 4581 if (FLAG_inline_new) {
4564 __ AllocateHeapNumber(reg, tmp, &slow); 4582 __ AllocateHeapNumber(reg, tmp, &slow);
4565 __ jmp(&done, Label::kNear); 4583 __ jmp(&done, Label::kNear);
4566 } 4584 }
4567 4585
4568 // Slow case: Call the runtime system to do the number allocation. 4586 // Slow case: Call the runtime system to do the number allocation.
4569 __ bind(&slow); 4587 __ bind(&slow);
4588 {
4589 // Put a valid pointer value in the stack slot where the result
4590 // register is stored, as this register is in the pointer map, but contains
4591 // an integer value.
4592 __ Set(reg, 0);
4570 4593
4571 // Put a valid pointer value in the stack slot where the result 4594 // Preserve the value of all registers.
4572 // register is stored, as this register is in the pointer map, but contains an 4595 PushSafepointRegistersScope scope(this);
4573 // integer value.
4574 __ StoreToSafepointRegisterSlot(reg, Immediate(0));
4575 4596
4576 // NumberTagU uses the context from the frame, rather than 4597 // NumberTagU uses the context from the frame, rather than
4577 // the environment's HContext or HInlinedContext value. 4598 // the environment's HContext or HInlinedContext value.
4578 // They only call Runtime::kAllocateHeapNumber. 4599 // They only call Runtime::kAllocateHeapNumber.
4579 // The corresponding HChange instructions are added in a phase that does 4600 // The corresponding HChange instructions are added in a phase that does
4580 // not have easy access to the local context. 4601 // not have easy access to the local context.
4581 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 4602 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
4582 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); 4603 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
4583 RecordSafepointWithRegisters( 4604 RecordSafepointWithRegisters(
4584 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); 4605 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
4585 4606 __ StoreToSafepointRegisterSlot(reg, rax);
4586 if (!reg.is(rax)) __ movp(reg, rax); 4607 }
4587 4608
4588 // Done. Put the value in temp_xmm into the value of the allocated heap 4609 // Done. Put the value in temp_xmm into the value of the allocated heap
4589 // number. 4610 // number.
4590 __ bind(&done); 4611 __ bind(&done);
4591 __ movsd(FieldOperand(reg, HeapNumber::kValueOffset), temp_xmm); 4612 __ movsd(FieldOperand(reg, HeapNumber::kValueOffset), temp_xmm);
4592 __ StoreToSafepointRegisterSlot(reg, reg);
4593 } 4613 }
4594 4614
4595 4615
4596 void LCodeGen::DoNumberTagD(LNumberTagD* instr) { 4616 void LCodeGen::DoNumberTagD(LNumberTagD* instr) {
4597 class DeferredNumberTagD V8_FINAL : public LDeferredCode { 4617 class DeferredNumberTagD V8_FINAL : public LDeferredCode {
4598 public: 4618 public:
4599 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr) 4619 DeferredNumberTagD(LCodeGen* codegen, LNumberTagD* instr)
4600 : LDeferredCode(codegen), instr_(instr) { } 4620 : LDeferredCode(codegen), instr_(instr) { }
4601 virtual void Generate() V8_OVERRIDE { 4621 virtual void Generate() V8_OVERRIDE {
4602 codegen()->DoDeferredNumberTagD(instr_); 4622 codegen()->DoDeferredNumberTagD(instr_);
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
4639 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); 4659 __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber);
4640 RecordSafepointWithRegisters( 4660 RecordSafepointWithRegisters(
4641 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); 4661 instr->pointer_map(), 0, Safepoint::kNoLazyDeopt);
4642 __ movp(kScratchRegister, rax); 4662 __ movp(kScratchRegister, rax);
4643 } 4663 }
4644 __ movp(reg, kScratchRegister); 4664 __ movp(reg, kScratchRegister);
4645 } 4665 }
4646 4666
4647 4667
4648 void LCodeGen::DoSmiTag(LSmiTag* instr) { 4668 void LCodeGen::DoSmiTag(LSmiTag* instr) {
4649 ASSERT(instr->value()->Equals(instr->result())); 4669 HChange* hchange = instr->hydrogen();
4650 Register input = ToRegister(instr->value()); 4670 Register input = ToRegister(instr->value());
4651 ASSERT(!instr->hydrogen_value()->CheckFlag(HValue::kCanOverflow)); 4671 Register output = ToRegister(instr->result());
4652 __ Integer32ToSmi(input, input); 4672 if (hchange->CheckFlag(HValue::kCanOverflow) &&
4673 hchange->value()->CheckFlag(HValue::kUint32)) {
4674 __ testl(input, Immediate(0x80000000));
4675 DeoptimizeIf(not_zero, instr->environment());
4676 }
4677 __ Integer32ToSmi(output, input);
4678 if (hchange->CheckFlag(HValue::kCanOverflow) &&
4679 !hchange->value()->CheckFlag(HValue::kUint32)) {
4680 DeoptimizeIf(overflow, instr->environment());
4681 }
4653 } 4682 }
4654 4683
4655 4684
4656 void LCodeGen::DoSmiUntag(LSmiUntag* instr) { 4685 void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
4657 ASSERT(instr->value()->Equals(instr->result())); 4686 ASSERT(instr->value()->Equals(instr->result()));
4658 Register input = ToRegister(instr->value()); 4687 Register input = ToRegister(instr->value());
4659 if (instr->needs_check()) { 4688 if (instr->needs_check()) {
4660 Condition is_smi = __ CheckSmi(input); 4689 Condition is_smi = __ CheckSmi(input);
4661 DeoptimizeIf(NegateCondition(is_smi), instr->environment()); 4690 DeoptimizeIf(NegateCondition(is_smi), instr->environment());
4662 } else { 4691 } else {
(...skipping 386 matching lines...) Expand 10 before | Expand all | Expand 10 after
5049 5078
5050 // smi 5079 // smi
5051 __ bind(&is_smi); 5080 __ bind(&is_smi);
5052 __ SmiToInteger32(input_reg, input_reg); 5081 __ SmiToInteger32(input_reg, input_reg);
5053 __ ClampUint8(input_reg); 5082 __ ClampUint8(input_reg);
5054 5083
5055 __ bind(&done); 5084 __ bind(&done);
5056 } 5085 }
5057 5086
5058 5087
5088 void LCodeGen::DoDoubleBits(LDoubleBits* instr) {
5089 XMMRegister value_reg = ToDoubleRegister(instr->value());
5090 Register result_reg = ToRegister(instr->result());
5091 if (instr->hydrogen()->bits() == HDoubleBits::HIGH) {
5092 __ movq(result_reg, value_reg);
5093 __ shr(result_reg, Immediate(32));
5094 } else {
5095 __ movd(result_reg, value_reg);
5096 }
5097 }
5098
5099
5100 void LCodeGen::DoConstructDouble(LConstructDouble* instr) {
5101 Register hi_reg = ToRegister(instr->hi());
5102 Register lo_reg = ToRegister(instr->lo());
5103 XMMRegister result_reg = ToDoubleRegister(instr->result());
5104 XMMRegister xmm_scratch = double_scratch0();
5105 __ movd(result_reg, hi_reg);
5106 __ psllq(result_reg, 32);
5107 __ movd(xmm_scratch, lo_reg);
5108 __ orps(result_reg, xmm_scratch);
5109 }
5110
5111
5059 void LCodeGen::DoAllocate(LAllocate* instr) { 5112 void LCodeGen::DoAllocate(LAllocate* instr) {
5060 class DeferredAllocate V8_FINAL : public LDeferredCode { 5113 class DeferredAllocate V8_FINAL : public LDeferredCode {
5061 public: 5114 public:
5062 DeferredAllocate(LCodeGen* codegen, LAllocate* instr) 5115 DeferredAllocate(LCodeGen* codegen, LAllocate* instr)
5063 : LDeferredCode(codegen), instr_(instr) { } 5116 : LDeferredCode(codegen), instr_(instr) { }
5064 virtual void Generate() V8_OVERRIDE { 5117 virtual void Generate() V8_OVERRIDE {
5065 codegen()->DoDeferredAllocate(instr_); 5118 codegen()->DoDeferredAllocate(instr_);
5066 } 5119 }
5067 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } 5120 virtual LInstruction* instr() V8_OVERRIDE { return instr_; }
5068 private: 5121 private:
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
5217 } 5270 }
5218 } 5271 }
5219 5272
5220 5273
5221 void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) { 5274 void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) {
5222 ASSERT(ToRegister(instr->context()).is(rsi)); 5275 ASSERT(ToRegister(instr->context()).is(rsi));
5223 // Use the fast case closure allocation code that allocates in new 5276 // Use the fast case closure allocation code that allocates in new
5224 // space for nested functions that don't need literals cloning. 5277 // space for nested functions that don't need literals cloning.
5225 bool pretenure = instr->hydrogen()->pretenure(); 5278 bool pretenure = instr->hydrogen()->pretenure();
5226 if (!pretenure && instr->hydrogen()->has_no_literals()) { 5279 if (!pretenure && instr->hydrogen()->has_no_literals()) {
5227 FastNewClosureStub stub(instr->hydrogen()->language_mode(), 5280 FastNewClosureStub stub(instr->hydrogen()->strict_mode(),
5228 instr->hydrogen()->is_generator()); 5281 instr->hydrogen()->is_generator());
5229 __ Move(rbx, instr->hydrogen()->shared_info()); 5282 __ Move(rbx, instr->hydrogen()->shared_info());
5230 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); 5283 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr);
5231 } else { 5284 } else {
5232 __ push(rsi); 5285 __ push(rsi);
5233 __ Push(instr->hydrogen()->shared_info()); 5286 __ Push(instr->hydrogen()->shared_info());
5234 __ PushRoot(pretenure ? Heap::kTrueValueRootIndex : 5287 __ PushRoot(pretenure ? Heap::kTrueValueRootIndex :
5235 Heap::kFalseValueRootIndex); 5288 Heap::kFalseValueRootIndex);
5236 CallRuntime(Runtime::kNewClosure, 3, instr); 5289 CallRuntime(Runtime::kNewClosure, 3, instr);
5237 } 5290 }
(...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after
5589 FixedArray::kHeaderSize - kPointerSize)); 5642 FixedArray::kHeaderSize - kPointerSize));
5590 __ bind(&done); 5643 __ bind(&done);
5591 } 5644 }
5592 5645
5593 5646
5594 #undef __ 5647 #undef __
5595 5648
5596 } } // namespace v8::internal 5649 } } // namespace v8::internal
5597 5650
5598 #endif // V8_TARGET_ARCH_X64 5651 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/lithium-codegen-x64.h ('k') | src/x64/lithium-x64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698