| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 1715 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1726 break; | 1726 break; |
| 1727 case 5: | 1727 case 5: |
| 1728 __ lea(left, Operand(left, left, times_4, 0)); | 1728 __ lea(left, Operand(left, left, times_4, 0)); |
| 1729 break; | 1729 break; |
| 1730 case 8: | 1730 case 8: |
| 1731 __ shl(left, 3); | 1731 __ shl(left, 3); |
| 1732 break; | 1732 break; |
| 1733 case 9: | 1733 case 9: |
| 1734 __ lea(left, Operand(left, left, times_8, 0)); | 1734 __ lea(left, Operand(left, left, times_8, 0)); |
| 1735 break; | 1735 break; |
| 1736 case 16: | 1736 case 16: |
| 1737 __ shl(left, 4); | 1737 __ shl(left, 4); |
| 1738 break; | 1738 break; |
| 1739 default: | 1739 default: |
| 1740 __ imul(left, left, constant); | 1740 __ imul(left, left, constant); |
| 1741 break; | 1741 break; |
| 1742 } | 1742 } |
| 1743 } else { | 1743 } else { |
| 1744 __ imul(left, left, constant); | 1744 __ imul(left, left, constant); |
| 1745 } | 1745 } |
| 1746 } else { | 1746 } else { |
| 1747 if (instr->hydrogen()->representation().IsSmi()) { | 1747 if (instr->hydrogen()->representation().IsSmi()) { |
| 1748 __ SmiUntag(left); | 1748 __ SmiUntag(left); |
| (...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2201 } | 2201 } |
| 2202 } | 2202 } |
| 2203 | 2203 |
| 2204 | 2204 |
| 2205 void LCodeGen::DoArithmeticD(LArithmeticD* instr) { | 2205 void LCodeGen::DoArithmeticD(LArithmeticD* instr) { |
| 2206 if (CpuFeatures::IsSafeForSnapshot(SSE2)) { | 2206 if (CpuFeatures::IsSafeForSnapshot(SSE2)) { |
| 2207 CpuFeatureScope scope(masm(), SSE2); | 2207 CpuFeatureScope scope(masm(), SSE2); |
| 2208 XMMRegister left = ToDoubleRegister(instr->left()); | 2208 XMMRegister left = ToDoubleRegister(instr->left()); |
| 2209 XMMRegister right = ToDoubleRegister(instr->right()); | 2209 XMMRegister right = ToDoubleRegister(instr->right()); |
| 2210 XMMRegister result = ToDoubleRegister(instr->result()); | 2210 XMMRegister result = ToDoubleRegister(instr->result()); |
| 2211 // Modulo uses a fixed result register. |
| 2212 ASSERT(instr->op() == Token::MOD || left.is(result)); |
| 2211 switch (instr->op()) { | 2213 switch (instr->op()) { |
| 2212 case Token::ADD: | 2214 case Token::ADD: |
| 2213 __ addsd(left, right); | 2215 __ addsd(left, right); |
| 2214 break; | 2216 break; |
| 2215 case Token::SUB: | 2217 case Token::SUB: |
| 2216 __ subsd(left, right); | 2218 __ subsd(left, right); |
| 2217 break; | 2219 break; |
| 2218 case Token::MUL: | 2220 case Token::MUL: |
| 2219 __ mulsd(left, right); | 2221 __ mulsd(left, right); |
| 2220 break; | 2222 break; |
| 2221 case Token::DIV: | 2223 case Token::DIV: |
| 2222 __ divsd(left, right); | 2224 __ divsd(left, right); |
| 2223 // Don't delete this mov. It may improve performance on some CPUs, | 2225 // Don't delete this mov. It may improve performance on some CPUs, |
| 2224 // when there is a mulsd depending on the result | 2226 // when there is a mulsd depending on the result |
| 2225 __ movaps(left, left); | 2227 __ movaps(left, left); |
| 2226 break; | 2228 break; |
| 2227 case Token::MOD: { | 2229 case Token::MOD: { |
| 2228 // Pass two doubles as arguments on the stack. | 2230 // Pass two doubles as arguments on the stack. |
| 2229 __ PrepareCallCFunction(4, eax); | 2231 __ PrepareCallCFunction(4, eax); |
| 2230 __ movdbl(Operand(esp, 0 * kDoubleSize), left); | 2232 __ movdbl(Operand(esp, 0 * kDoubleSize), left); |
| 2231 __ movdbl(Operand(esp, 1 * kDoubleSize), right); | 2233 __ movdbl(Operand(esp, 1 * kDoubleSize), right); |
| 2232 __ CallCFunction( | 2234 __ CallCFunction( |
| 2233 ExternalReference::double_fp_operation(Token::MOD, isolate()), | 2235 ExternalReference::double_fp_operation(Token::MOD, isolate()), |
| 2234 4); | 2236 4); |
| 2235 | 2237 |
| 2236 // Return value is in st(0) on ia32. | 2238 // Return value is in st(0) on ia32. |
| 2237 // Store it into the result register. | 2239 // Store it into the (fixed) result register. |
| 2238 __ sub(Operand(esp), Immediate(kDoubleSize)); | 2240 __ sub(Operand(esp), Immediate(kDoubleSize)); |
| 2239 __ fstp_d(Operand(esp, 0)); | 2241 __ fstp_d(Operand(esp, 0)); |
| 2240 __ movdbl(result, Operand(esp, 0)); | 2242 __ movdbl(result, Operand(esp, 0)); |
| 2241 __ add(Operand(esp), Immediate(kDoubleSize)); | 2243 __ add(Operand(esp), Immediate(kDoubleSize)); |
| 2242 break; | 2244 break; |
| 2243 } | 2245 } |
| 2244 default: | 2246 default: |
| 2245 UNREACHABLE(); | 2247 UNREACHABLE(); |
| 2246 break; | 2248 break; |
| 2247 } | 2249 } |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2331 void LCodeGen::EmitFalseBranch(InstrType instr, Condition cc) { | 2333 void LCodeGen::EmitFalseBranch(InstrType instr, Condition cc) { |
| 2332 int false_block = instr->FalseDestination(chunk_); | 2334 int false_block = instr->FalseDestination(chunk_); |
| 2333 if (cc == no_condition) { | 2335 if (cc == no_condition) { |
| 2334 __ jmp(chunk_->GetAssemblyLabel(false_block)); | 2336 __ jmp(chunk_->GetAssemblyLabel(false_block)); |
| 2335 } else { | 2337 } else { |
| 2336 __ j(cc, chunk_->GetAssemblyLabel(false_block)); | 2338 __ j(cc, chunk_->GetAssemblyLabel(false_block)); |
| 2337 } | 2339 } |
| 2338 } | 2340 } |
| 2339 | 2341 |
| 2340 | 2342 |
| 2343 void LCodeGen::DoIsNumberAndBranch(LIsNumberAndBranch* instr) { |
| 2344 Representation r = instr->hydrogen()->value()->representation(); |
| 2345 if (r.IsSmiOrInteger32() || r.IsDouble()) { |
| 2346 EmitBranch(instr, no_condition); |
| 2347 } else { |
| 2348 ASSERT(r.IsTagged()); |
| 2349 Register reg = ToRegister(instr->value()); |
| 2350 HType type = instr->hydrogen()->value()->type(); |
| 2351 if (type.IsTaggedNumber()) { |
| 2352 EmitBranch(instr, no_condition); |
| 2353 } |
| 2354 __ JumpIfSmi(reg, instr->TrueLabel(chunk_)); |
| 2355 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), |
| 2356 factory()->heap_number_map()); |
| 2357 EmitBranch(instr, equal); |
| 2358 } |
| 2359 } |
| 2360 |
| 2361 |
| 2341 void LCodeGen::DoBranch(LBranch* instr) { | 2362 void LCodeGen::DoBranch(LBranch* instr) { |
| 2342 Representation r = instr->hydrogen()->value()->representation(); | 2363 Representation r = instr->hydrogen()->value()->representation(); |
| 2343 if (r.IsSmiOrInteger32()) { | 2364 if (r.IsSmiOrInteger32()) { |
| 2344 Register reg = ToRegister(instr->value()); | 2365 Register reg = ToRegister(instr->value()); |
| 2345 __ test(reg, Operand(reg)); | 2366 __ test(reg, Operand(reg)); |
| 2346 EmitBranch(instr, not_zero); | 2367 EmitBranch(instr, not_zero); |
| 2347 } else if (r.IsDouble()) { | 2368 } else if (r.IsDouble()) { |
| 2348 ASSERT(!info()->IsStub()); | 2369 ASSERT(!info()->IsStub()); |
| 2349 CpuFeatureScope scope(masm(), SSE2); | 2370 CpuFeatureScope scope(masm(), SSE2); |
| 2350 XMMRegister reg = ToDoubleRegister(instr->value()); | 2371 XMMRegister reg = ToDoubleRegister(instr->value()); |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2528 | 2549 |
| 2529 if (left->IsConstantOperand() && right->IsConstantOperand()) { | 2550 if (left->IsConstantOperand() && right->IsConstantOperand()) { |
| 2530 // We can statically evaluate the comparison. | 2551 // We can statically evaluate the comparison. |
| 2531 double left_val = ToDouble(LConstantOperand::cast(left)); | 2552 double left_val = ToDouble(LConstantOperand::cast(left)); |
| 2532 double right_val = ToDouble(LConstantOperand::cast(right)); | 2553 double right_val = ToDouble(LConstantOperand::cast(right)); |
| 2533 int next_block = EvalComparison(instr->op(), left_val, right_val) ? | 2554 int next_block = EvalComparison(instr->op(), left_val, right_val) ? |
| 2534 instr->TrueDestination(chunk_) : instr->FalseDestination(chunk_); | 2555 instr->TrueDestination(chunk_) : instr->FalseDestination(chunk_); |
| 2535 EmitGoto(next_block); | 2556 EmitGoto(next_block); |
| 2536 } else { | 2557 } else { |
| 2537 if (instr->is_double()) { | 2558 if (instr->is_double()) { |
| 2538 if (CpuFeatures::IsSafeForSnapshot(SSE2)) { | 2559 CpuFeatureScope scope(masm(), SSE2); |
| 2539 CpuFeatureScope scope(masm(), SSE2); | |
| 2540 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right)); | |
| 2541 } else { | |
| 2542 X87Fxch(ToX87Register(right)); | |
| 2543 X87Fxch(ToX87Register(left), 1); | |
| 2544 __ fld(0); | |
| 2545 __ fld(2); | |
| 2546 __ FCmp(); | |
| 2547 } | |
| 2548 // Don't base result on EFLAGS when a NaN is involved. Instead | 2560 // Don't base result on EFLAGS when a NaN is involved. Instead |
| 2549 // jump to the false block. | 2561 // jump to the false block. |
| 2562 __ ucomisd(ToDoubleRegister(left), ToDoubleRegister(right)); |
| 2550 __ j(parity_even, instr->FalseLabel(chunk_)); | 2563 __ j(parity_even, instr->FalseLabel(chunk_)); |
| 2551 } else { | 2564 } else { |
| 2552 if (right->IsConstantOperand()) { | 2565 if (right->IsConstantOperand()) { |
| 2553 __ cmp(ToOperand(left), | 2566 __ cmp(ToOperand(left), |
| 2554 ToImmediate(right, instr->hydrogen()->representation())); | 2567 ToImmediate(right, instr->hydrogen()->representation())); |
| 2555 } else if (left->IsConstantOperand()) { | 2568 } else if (left->IsConstantOperand()) { |
| 2556 __ cmp(ToOperand(right), | 2569 __ cmp(ToOperand(right), |
| 2557 ToImmediate(left, instr->hydrogen()->representation())); | 2570 ToImmediate(left, instr->hydrogen()->representation())); |
| 2558 // We transposed the operands. Reverse the condition. | 2571 // We transposed the operands. Reverse the condition. |
| 2559 cc = ReverseCondition(cc); | 2572 cc = ReverseCondition(cc); |
| (...skipping 1397 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3957 __ cvttsd2si(output_reg, Operand(input_reg)); | 3970 __ cvttsd2si(output_reg, Operand(input_reg)); |
| 3958 // Overflow is signalled with minint. | 3971 // Overflow is signalled with minint. |
| 3959 __ cmp(output_reg, 0x80000000u); | 3972 __ cmp(output_reg, 0x80000000u); |
| 3960 DeoptimizeIf(equal, instr->environment()); | 3973 DeoptimizeIf(equal, instr->environment()); |
| 3961 __ jmp(&done, Label::kNear); | 3974 __ jmp(&done, Label::kNear); |
| 3962 | 3975 |
| 3963 // Non-zero negative reaches here. | 3976 // Non-zero negative reaches here. |
| 3964 __ bind(&negative_sign); | 3977 __ bind(&negative_sign); |
| 3965 // Truncate, then compare and compensate. | 3978 // Truncate, then compare and compensate. |
| 3966 __ cvttsd2si(output_reg, Operand(input_reg)); | 3979 __ cvttsd2si(output_reg, Operand(input_reg)); |
| 3967 __ Cvtsi2sd(xmm_scratch, output_reg); | 3980 __ cvtsi2sd(xmm_scratch, output_reg); |
| 3968 __ ucomisd(input_reg, xmm_scratch); | 3981 __ ucomisd(input_reg, xmm_scratch); |
| 3969 __ j(equal, &done, Label::kNear); | 3982 __ j(equal, &done, Label::kNear); |
| 3970 __ sub(output_reg, Immediate(1)); | 3983 __ sub(output_reg, Immediate(1)); |
| 3971 DeoptimizeIf(overflow, instr->environment()); | 3984 DeoptimizeIf(overflow, instr->environment()); |
| 3972 | 3985 |
| 3973 __ bind(&done); | 3986 __ bind(&done); |
| 3974 } | 3987 } |
| 3975 } | 3988 } |
| 3976 | 3989 |
| 3977 | 3990 |
| (...skipping 29 matching lines...) Expand all Loading... |
| 4007 // CVTTSD2SI rounds towards zero, we use ceil(x - (-0.5)) and then | 4020 // CVTTSD2SI rounds towards zero, we use ceil(x - (-0.5)) and then |
| 4008 // compare and compensate. | 4021 // compare and compensate. |
| 4009 __ movsd(input_temp, input_reg); // Do not alter input_reg. | 4022 __ movsd(input_temp, input_reg); // Do not alter input_reg. |
| 4010 __ subsd(input_temp, xmm_scratch); | 4023 __ subsd(input_temp, xmm_scratch); |
| 4011 __ cvttsd2si(output_reg, Operand(input_temp)); | 4024 __ cvttsd2si(output_reg, Operand(input_temp)); |
| 4012 // Catch minint due to overflow, and to prevent overflow when compensating. | 4025 // Catch minint due to overflow, and to prevent overflow when compensating. |
| 4013 __ cmp(output_reg, 0x80000000u); | 4026 __ cmp(output_reg, 0x80000000u); |
| 4014 __ RecordComment("D2I conversion overflow"); | 4027 __ RecordComment("D2I conversion overflow"); |
| 4015 DeoptimizeIf(equal, instr->environment()); | 4028 DeoptimizeIf(equal, instr->environment()); |
| 4016 | 4029 |
| 4017 __ Cvtsi2sd(xmm_scratch, output_reg); | 4030 __ cvtsi2sd(xmm_scratch, output_reg); |
| 4018 __ ucomisd(xmm_scratch, input_temp); | 4031 __ ucomisd(xmm_scratch, input_temp); |
| 4019 __ j(equal, &done); | 4032 __ j(equal, &done); |
| 4020 __ sub(output_reg, Immediate(1)); | 4033 __ sub(output_reg, Immediate(1)); |
| 4021 // No overflow because we already ruled out minint. | 4034 // No overflow because we already ruled out minint. |
| 4022 __ jmp(&done); | 4035 __ jmp(&done); |
| 4023 | 4036 |
| 4024 __ bind(&round_to_zero); | 4037 __ bind(&round_to_zero); |
| 4025 // We return 0 for the input range [+0, 0.5[, or [-0.5, 0.5[ if | 4038 // We return 0 for the input range [+0, 0.5[, or [-0.5, 0.5[ if |
| 4026 // we can ignore the difference between a result of -0 and +0. | 4039 // we can ignore the difference between a result of -0 and +0. |
| 4027 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 4040 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
| (...skipping 930 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4958 } | 4971 } |
| 4959 | 4972 |
| 4960 | 4973 |
| 4961 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { | 4974 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { |
| 4962 LOperand* input = instr->value(); | 4975 LOperand* input = instr->value(); |
| 4963 LOperand* output = instr->result(); | 4976 LOperand* output = instr->result(); |
| 4964 ASSERT(input->IsRegister() || input->IsStackSlot()); | 4977 ASSERT(input->IsRegister() || input->IsStackSlot()); |
| 4965 ASSERT(output->IsDoubleRegister()); | 4978 ASSERT(output->IsDoubleRegister()); |
| 4966 if (CpuFeatures::IsSupported(SSE2)) { | 4979 if (CpuFeatures::IsSupported(SSE2)) { |
| 4967 CpuFeatureScope scope(masm(), SSE2); | 4980 CpuFeatureScope scope(masm(), SSE2); |
| 4968 __ Cvtsi2sd(ToDoubleRegister(output), ToOperand(input)); | 4981 __ cvtsi2sd(ToDoubleRegister(output), ToOperand(input)); |
| 4969 } else if (input->IsRegister()) { | 4982 } else if (input->IsRegister()) { |
| 4970 Register input_reg = ToRegister(input); | 4983 Register input_reg = ToRegister(input); |
| 4971 __ push(input_reg); | 4984 __ push(input_reg); |
| 4972 X87Mov(ToX87Register(output), Operand(esp, 0), kX87IntOperand); | 4985 X87Mov(ToX87Register(output), Operand(esp, 0), kX87IntOperand); |
| 4973 __ pop(input_reg); | 4986 __ pop(input_reg); |
| 4974 } else { | 4987 } else { |
| 4975 X87Mov(ToX87Register(output), ToOperand(input), kX87IntOperand); | 4988 X87Mov(ToX87Register(output), ToOperand(input), kX87IntOperand); |
| 4976 } | 4989 } |
| 4977 } | 4990 } |
| 4978 | 4991 |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5067 Label done; | 5080 Label done; |
| 5068 | 5081 |
| 5069 if (signedness == SIGNED_INT32) { | 5082 if (signedness == SIGNED_INT32) { |
| 5070 // There was overflow, so bits 30 and 31 of the original integer | 5083 // There was overflow, so bits 30 and 31 of the original integer |
| 5071 // disagree. Try to allocate a heap number in new space and store | 5084 // disagree. Try to allocate a heap number in new space and store |
| 5072 // the value in there. If that fails, call the runtime system. | 5085 // the value in there. If that fails, call the runtime system. |
| 5073 __ SmiUntag(reg); | 5086 __ SmiUntag(reg); |
| 5074 __ xor_(reg, 0x80000000); | 5087 __ xor_(reg, 0x80000000); |
| 5075 if (CpuFeatures::IsSupported(SSE2)) { | 5088 if (CpuFeatures::IsSupported(SSE2)) { |
| 5076 CpuFeatureScope feature_scope(masm(), SSE2); | 5089 CpuFeatureScope feature_scope(masm(), SSE2); |
| 5077 __ Cvtsi2sd(xmm0, Operand(reg)); | 5090 __ cvtsi2sd(xmm0, Operand(reg)); |
| 5078 } else { | 5091 } else { |
| 5079 __ push(reg); | 5092 __ push(reg); |
| 5080 __ fild_s(Operand(esp, 0)); | 5093 __ fild_s(Operand(esp, 0)); |
| 5081 __ pop(reg); | 5094 __ pop(reg); |
| 5082 } | 5095 } |
| 5083 } else { | 5096 } else { |
| 5084 if (CpuFeatures::IsSupported(SSE2)) { | 5097 if (CpuFeatures::IsSupported(SSE2)) { |
| 5085 CpuFeatureScope feature_scope(masm(), SSE2); | 5098 CpuFeatureScope feature_scope(masm(), SSE2); |
| 5086 __ LoadUint32(xmm0, reg, | 5099 __ LoadUint32(xmm0, reg, |
| 5087 ToDoubleRegister(LNumberTagU::cast(instr)->temp())); | 5100 ToDoubleRegister(LNumberTagU::cast(instr)->temp())); |
| (...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5288 } | 5301 } |
| 5289 | 5302 |
| 5290 | 5303 |
| 5291 void LCodeGen::EmitNumberUntagD(Register input_reg, | 5304 void LCodeGen::EmitNumberUntagD(Register input_reg, |
| 5292 Register temp_reg, | 5305 Register temp_reg, |
| 5293 XMMRegister result_reg, | 5306 XMMRegister result_reg, |
| 5294 bool can_convert_undefined_to_nan, | 5307 bool can_convert_undefined_to_nan, |
| 5295 bool deoptimize_on_minus_zero, | 5308 bool deoptimize_on_minus_zero, |
| 5296 LEnvironment* env, | 5309 LEnvironment* env, |
| 5297 NumberUntagDMode mode) { | 5310 NumberUntagDMode mode) { |
| 5298 Label convert, load_smi, done; | 5311 Label load_smi, done; |
| 5299 | 5312 |
| 5300 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) { | 5313 if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) { |
| 5301 // Smi check. | 5314 // Smi check. |
| 5302 __ JumpIfSmi(input_reg, &load_smi, Label::kNear); | 5315 __ JumpIfSmi(input_reg, &load_smi, Label::kNear); |
| 5303 | 5316 |
| 5304 // Heap number map check. | 5317 // Heap number map check. |
| 5305 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), | 5318 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), |
| 5306 factory()->heap_number_map()); | 5319 factory()->heap_number_map()); |
| 5307 if (can_convert_undefined_to_nan) { | 5320 if (!can_convert_undefined_to_nan) { |
| 5308 __ j(not_equal, &convert, Label::kNear); | 5321 DeoptimizeIf(not_equal, env); |
| 5309 } else { | 5322 } else { |
| 5323 Label heap_number, convert; |
| 5324 __ j(equal, &heap_number, Label::kNear); |
| 5325 |
| 5326 // Convert undefined (and hole) to NaN. |
| 5327 __ cmp(input_reg, factory()->undefined_value()); |
| 5310 DeoptimizeIf(not_equal, env); | 5328 DeoptimizeIf(not_equal, env); |
| 5329 |
| 5330 __ bind(&convert); |
| 5331 ExternalReference nan = |
| 5332 ExternalReference::address_of_canonical_non_hole_nan(); |
| 5333 __ movdbl(result_reg, Operand::StaticVariable(nan)); |
| 5334 __ jmp(&done, Label::kNear); |
| 5335 |
| 5336 __ bind(&heap_number); |
| 5311 } | 5337 } |
| 5312 | |
| 5313 // Heap number to XMM conversion. | 5338 // Heap number to XMM conversion. |
| 5314 __ movdbl(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset)); | 5339 __ movdbl(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
| 5315 | |
| 5316 if (deoptimize_on_minus_zero) { | 5340 if (deoptimize_on_minus_zero) { |
| 5317 XMMRegister xmm_scratch = xmm0; | 5341 XMMRegister xmm_scratch = xmm0; |
| 5318 __ xorps(xmm_scratch, xmm_scratch); | 5342 __ xorps(xmm_scratch, xmm_scratch); |
| 5319 __ ucomisd(result_reg, xmm_scratch); | 5343 __ ucomisd(result_reg, xmm_scratch); |
| 5320 __ j(not_zero, &done, Label::kNear); | 5344 __ j(not_zero, &done, Label::kNear); |
| 5321 __ movmskpd(temp_reg, result_reg); | 5345 __ movmskpd(temp_reg, result_reg); |
| 5322 __ test_b(temp_reg, 1); | 5346 __ test_b(temp_reg, 1); |
| 5323 DeoptimizeIf(not_zero, env); | 5347 DeoptimizeIf(not_zero, env); |
| 5324 } | 5348 } |
| 5325 __ jmp(&done, Label::kNear); | 5349 __ jmp(&done, Label::kNear); |
| 5326 | |
| 5327 if (can_convert_undefined_to_nan) { | |
| 5328 __ bind(&convert); | |
| 5329 | |
| 5330 // Convert undefined (and hole) to NaN. | |
| 5331 __ cmp(input_reg, factory()->undefined_value()); | |
| 5332 DeoptimizeIf(not_equal, env); | |
| 5333 | |
| 5334 ExternalReference nan = | |
| 5335 ExternalReference::address_of_canonical_non_hole_nan(); | |
| 5336 __ movdbl(result_reg, Operand::StaticVariable(nan)); | |
| 5337 __ jmp(&done, Label::kNear); | |
| 5338 } | |
| 5339 } else { | 5350 } else { |
| 5340 ASSERT(mode == NUMBER_CANDIDATE_IS_SMI); | 5351 ASSERT(mode == NUMBER_CANDIDATE_IS_SMI); |
| 5341 } | 5352 } |
| 5342 | 5353 |
| 5343 __ bind(&load_smi); | 5354 __ bind(&load_smi); |
| 5344 // Smi to XMM conversion. Clobbering a temp is faster than re-tagging the | 5355 // Smi to XMM conversion. Clobbering a temp is faster than re-tagging the |
| 5345 // input register since we avoid dependencies. | 5356 // input register since we avoid dependencies. |
| 5346 __ mov(temp_reg, input_reg); | 5357 __ mov(temp_reg, input_reg); |
| 5347 __ SmiUntag(temp_reg); // Untag smi before converting to float. | 5358 __ SmiUntag(temp_reg); // Untag smi before converting to float. |
| 5348 __ Cvtsi2sd(result_reg, Operand(temp_reg)); | 5359 __ cvtsi2sd(result_reg, Operand(temp_reg)); |
| 5349 __ bind(&done); | 5360 __ bind(&done); |
| 5350 } | 5361 } |
| 5351 | 5362 |
| 5352 | 5363 |
| 5353 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr, Label* done) { | 5364 void LCodeGen::DoDeferredTaggedToI(LTaggedToI* instr, Label* done) { |
| 5354 Register input_reg = ToRegister(instr->value()); | 5365 Register input_reg = ToRegister(instr->value()); |
| 5355 | 5366 |
| 5356 | 5367 |
| 5357 if (instr->truncating()) { | 5368 if (instr->truncating()) { |
| 5358 Label heap_number, slow_case; | 5369 Label heap_number, slow_case; |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5399 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } | 5410 virtual LInstruction* instr() V8_OVERRIDE { return instr_; } |
| 5400 private: | 5411 private: |
| 5401 LTaggedToI* instr_; | 5412 LTaggedToI* instr_; |
| 5402 }; | 5413 }; |
| 5403 | 5414 |
| 5404 LOperand* input = instr->value(); | 5415 LOperand* input = instr->value(); |
| 5405 ASSERT(input->IsRegister()); | 5416 ASSERT(input->IsRegister()); |
| 5406 Register input_reg = ToRegister(input); | 5417 Register input_reg = ToRegister(input); |
| 5407 ASSERT(input_reg.is(ToRegister(instr->result()))); | 5418 ASSERT(input_reg.is(ToRegister(instr->result()))); |
| 5408 | 5419 |
| 5409 if (instr->hydrogen()->value()->representation().IsSmi()) { | 5420 DeferredTaggedToI* deferred = |
| 5410 __ SmiUntag(input_reg); | 5421 new(zone()) DeferredTaggedToI(this, instr, x87_stack_); |
| 5411 } else { | |
| 5412 DeferredTaggedToI* deferred = | |
| 5413 new(zone()) DeferredTaggedToI(this, instr, x87_stack_); | |
| 5414 | 5422 |
| 5415 __ JumpIfNotSmi(input_reg, deferred->entry()); | 5423 __ JumpIfNotSmi(input_reg, deferred->entry()); |
| 5416 __ SmiUntag(input_reg); | 5424 __ SmiUntag(input_reg); |
| 5417 __ bind(deferred->exit()); | 5425 __ bind(deferred->exit()); |
| 5418 } | |
| 5419 } | 5426 } |
| 5420 | 5427 |
| 5421 | 5428 |
| 5422 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { | 5429 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { |
| 5423 LOperand* input = instr->value(); | 5430 LOperand* input = instr->value(); |
| 5424 ASSERT(input->IsRegister()); | 5431 ASSERT(input->IsRegister()); |
| 5425 LOperand* temp = instr->temp(); | 5432 LOperand* temp = instr->temp(); |
| 5426 ASSERT(temp->IsRegister()); | 5433 ASSERT(temp->IsRegister()); |
| 5427 LOperand* result = instr->result(); | 5434 LOperand* result = instr->result(); |
| 5428 ASSERT(result->IsDoubleRegister()); | 5435 ASSERT(result->IsDoubleRegister()); |
| (...skipping 921 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6350 FixedArray::kHeaderSize - kPointerSize)); | 6357 FixedArray::kHeaderSize - kPointerSize)); |
| 6351 __ bind(&done); | 6358 __ bind(&done); |
| 6352 } | 6359 } |
| 6353 | 6360 |
| 6354 | 6361 |
| 6355 #undef __ | 6362 #undef __ |
| 6356 | 6363 |
| 6357 } } // namespace v8::internal | 6364 } } // namespace v8::internal |
| 6358 | 6365 |
| 6359 #endif // V8_TARGET_ARCH_IA32 | 6366 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |