| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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, ÷nd_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(÷nd_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, ¬_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(¬_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, ÷nd_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(÷nd_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, ÷nd_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(÷nd_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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |