OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 786 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
797 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { | 797 if (instr->hydrogen()->CheckFlag(HValue::kCanOverflow)) { |
798 DeoptimizeIf(overflow, instr->environment()); | 798 DeoptimizeIf(overflow, instr->environment()); |
799 } | 799 } |
800 | 800 |
801 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { | 801 if (instr->hydrogen()->CheckFlag(HValue::kBailoutOnMinusZero)) { |
802 // Bail out if the result is supposed to be negative zero. | 802 // Bail out if the result is supposed to be negative zero. |
803 NearLabel done; | 803 NearLabel done; |
804 __ test(left, Operand(left)); | 804 __ test(left, Operand(left)); |
805 __ j(not_zero, &done); | 805 __ j(not_zero, &done); |
806 if (right->IsConstantOperand()) { | 806 if (right->IsConstantOperand()) { |
807 if (ToInteger32(LConstantOperand::cast(right)) < 0) { | 807 if (ToInteger32(LConstantOperand::cast(right)) <= 0) { |
808 DeoptimizeIf(no_condition, instr->environment()); | 808 DeoptimizeIf(no_condition, instr->environment()); |
809 } | 809 } |
810 } else { | 810 } else { |
811 // Test the non-zero operand for negative sign. | 811 // Test the non-zero operand for negative sign. |
812 __ or_(ToRegister(instr->TempAt(0)), ToOperand(right)); | 812 __ or_(ToRegister(instr->TempAt(0)), ToOperand(right)); |
813 DeoptimizeIf(sign, instr->environment()); | 813 DeoptimizeIf(sign, instr->environment()); |
814 } | 814 } |
815 __ bind(&done); | 815 __ bind(&done); |
816 } | 816 } |
817 } | 817 } |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
938 | 938 |
939 void LCodeGen::DoConstantD(LConstantD* instr) { | 939 void LCodeGen::DoConstantD(LConstantD* instr) { |
940 ASSERT(instr->result()->IsDoubleRegister()); | 940 ASSERT(instr->result()->IsDoubleRegister()); |
941 XMMRegister res = ToDoubleRegister(instr->result()); | 941 XMMRegister res = ToDoubleRegister(instr->result()); |
942 double v = instr->value(); | 942 double v = instr->value(); |
943 // Use xor to produce +0.0 in a fast and compact way, but avoid to | 943 // Use xor to produce +0.0 in a fast and compact way, but avoid to |
944 // do so if the constant is -0.0. | 944 // do so if the constant is -0.0. |
945 if (BitCast<uint64_t, double>(v) == 0) { | 945 if (BitCast<uint64_t, double>(v) == 0) { |
946 __ xorpd(res, res); | 946 __ xorpd(res, res); |
947 } else { | 947 } else { |
948 int32_t v_int32 = static_cast<int32_t>(v); | 948 Register temp = ToRegister(instr->TempAt(0)); |
949 if (static_cast<double>(v_int32) == v) { | 949 uint64_t int_val = BitCast<uint64_t, double>(v); |
950 __ push_imm32(v_int32); | 950 int32_t lower = static_cast<int32_t>(int_val); |
951 __ cvtsi2sd(res, Operand(esp, 0)); | 951 int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt)); |
952 __ add(Operand(esp), Immediate(kPointerSize)); | 952 if (CpuFeatures::IsSupported(SSE4_1)) { |
| 953 CpuFeatures::Scope scope(SSE4_1); |
| 954 if (lower != 0) { |
| 955 __ Set(temp, Immediate(lower)); |
| 956 __ movd(res, Operand(temp)); |
| 957 __ Set(temp, Immediate(upper)); |
| 958 __ pinsrd(res, Operand(temp), 1); |
| 959 } else { |
| 960 __ xorpd(res, res); |
| 961 __ Set(temp, Immediate(upper)); |
| 962 __ pinsrd(res, Operand(temp), 1); |
| 963 } |
953 } else { | 964 } else { |
954 uint64_t int_val = BitCast<uint64_t, double>(v); | 965 __ Set(temp, Immediate(upper)); |
955 int32_t lower = static_cast<int32_t>(int_val); | 966 __ movd(res, Operand(temp)); |
956 int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt)); | 967 __ psllq(res, 32); |
957 __ push_imm32(upper); | 968 if (lower != 0) { |
958 __ push_imm32(lower); | 969 __ Set(temp, Immediate(lower)); |
959 __ movdbl(res, Operand(esp, 0)); | 970 __ movd(xmm0, Operand(temp)); |
960 __ add(Operand(esp), Immediate(2 * kPointerSize)); | 971 __ por(res, xmm0); |
| 972 } |
961 } | 973 } |
962 } | 974 } |
963 } | 975 } |
964 | 976 |
965 | 977 |
966 void LCodeGen::DoConstantT(LConstantT* instr) { | 978 void LCodeGen::DoConstantT(LConstantT* instr) { |
967 ASSERT(instr->result()->IsRegister()); | 979 ASSERT(instr->result()->IsRegister()); |
968 __ Set(ToRegister(instr->result()), Immediate(instr->value())); | 980 __ Set(ToRegister(instr->result()), Immediate(instr->value())); |
969 } | 981 } |
970 | 982 |
(...skipping 903 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1874 | 1886 |
1875 void LCodeGen::DoReturn(LReturn* instr) { | 1887 void LCodeGen::DoReturn(LReturn* instr) { |
1876 if (FLAG_trace) { | 1888 if (FLAG_trace) { |
1877 // Preserve the return value on the stack and rely on the runtime | 1889 // Preserve the return value on the stack and rely on the runtime |
1878 // call to return the value in the same register. | 1890 // call to return the value in the same register. |
1879 __ push(eax); | 1891 __ push(eax); |
1880 __ CallRuntime(Runtime::kTraceExit, 1); | 1892 __ CallRuntime(Runtime::kTraceExit, 1); |
1881 } | 1893 } |
1882 __ mov(esp, ebp); | 1894 __ mov(esp, ebp); |
1883 __ pop(ebp); | 1895 __ pop(ebp); |
1884 __ ret((ParameterCount() + 1) * kPointerSize); | 1896 __ Ret((ParameterCount() + 1) * kPointerSize, ecx); |
1885 } | 1897 } |
1886 | 1898 |
1887 | 1899 |
1888 void LCodeGen::DoLoadGlobal(LLoadGlobal* instr) { | 1900 void LCodeGen::DoLoadGlobal(LLoadGlobal* instr) { |
1889 Register result = ToRegister(instr->result()); | 1901 Register result = ToRegister(instr->result()); |
1890 __ mov(result, Operand::Cell(instr->hydrogen()->cell())); | 1902 __ mov(result, Operand::Cell(instr->hydrogen()->cell())); |
1891 if (instr->hydrogen()->check_hole_value()) { | 1903 if (instr->hydrogen()->check_hole_value()) { |
1892 __ cmp(result, Factory::the_hole_value()); | 1904 __ cmp(result, Factory::the_hole_value()); |
1893 DeoptimizeIf(equal, instr->environment()); | 1905 DeoptimizeIf(equal, instr->environment()); |
1894 } | 1906 } |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2028 } | 2040 } |
2029 | 2041 |
2030 | 2042 |
2031 void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) { | 2043 void LCodeGen::DoLoadKeyedFastElement(LLoadKeyedFastElement* instr) { |
2032 Register elements = ToRegister(instr->elements()); | 2044 Register elements = ToRegister(instr->elements()); |
2033 Register key = ToRegister(instr->key()); | 2045 Register key = ToRegister(instr->key()); |
2034 Register result = ToRegister(instr->result()); | 2046 Register result = ToRegister(instr->result()); |
2035 ASSERT(result.is(elements)); | 2047 ASSERT(result.is(elements)); |
2036 | 2048 |
2037 // Load the result. | 2049 // Load the result. |
2038 __ mov(result, FieldOperand(elements, key, times_4, FixedArray::kHeaderSize)); | 2050 __ mov(result, FieldOperand(elements, |
| 2051 key, |
| 2052 times_pointer_size, |
| 2053 FixedArray::kHeaderSize)); |
2039 | 2054 |
2040 // Check for the hole value. | 2055 // Check for the hole value. |
2041 __ cmp(result, Factory::the_hole_value()); | 2056 __ cmp(result, Factory::the_hole_value()); |
2042 DeoptimizeIf(equal, instr->environment()); | 2057 DeoptimizeIf(equal, instr->environment()); |
2043 } | 2058 } |
2044 | 2059 |
2045 | 2060 |
2046 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { | 2061 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { |
2047 ASSERT(ToRegister(instr->object()).is(edx)); | 2062 ASSERT(ToRegister(instr->object()).is(edx)); |
2048 ASSERT(ToRegister(instr->key()).is(eax)); | 2063 ASSERT(ToRegister(instr->key()).is(eax)); |
(...skipping 605 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2654 Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) : no_reg; | 2669 Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) : no_reg; |
2655 | 2670 |
2656 // Do the store. | 2671 // Do the store. |
2657 if (instr->key()->IsConstantOperand()) { | 2672 if (instr->key()->IsConstantOperand()) { |
2658 ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); | 2673 ASSERT(!instr->hydrogen()->NeedsWriteBarrier()); |
2659 LConstantOperand* const_operand = LConstantOperand::cast(instr->key()); | 2674 LConstantOperand* const_operand = LConstantOperand::cast(instr->key()); |
2660 int offset = | 2675 int offset = |
2661 ToInteger32(const_operand) * kPointerSize + FixedArray::kHeaderSize; | 2676 ToInteger32(const_operand) * kPointerSize + FixedArray::kHeaderSize; |
2662 __ mov(FieldOperand(elements, offset), value); | 2677 __ mov(FieldOperand(elements, offset), value); |
2663 } else { | 2678 } else { |
2664 __ mov(FieldOperand(elements, key, times_4, FixedArray::kHeaderSize), | 2679 __ mov(FieldOperand(elements, |
| 2680 key, |
| 2681 times_pointer_size, |
| 2682 FixedArray::kHeaderSize), |
2665 value); | 2683 value); |
2666 } | 2684 } |
2667 | 2685 |
2668 if (instr->hydrogen()->NeedsWriteBarrier()) { | 2686 if (instr->hydrogen()->NeedsWriteBarrier()) { |
2669 // Compute address of modified element and store it into key register. | 2687 // Compute address of modified element and store it into key register. |
2670 __ lea(key, FieldOperand(elements, key, times_4, FixedArray::kHeaderSize)); | 2688 __ lea(key, |
| 2689 FieldOperand(elements, |
| 2690 key, |
| 2691 times_pointer_size, |
| 2692 FixedArray::kHeaderSize)); |
2671 __ RecordWrite(elements, key, value); | 2693 __ RecordWrite(elements, key, value); |
2672 } | 2694 } |
2673 } | 2695 } |
2674 | 2696 |
2675 | 2697 |
2676 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { | 2698 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { |
2677 ASSERT(ToRegister(instr->object()).is(edx)); | 2699 ASSERT(ToRegister(instr->object()).is(edx)); |
2678 ASSERT(ToRegister(instr->key()).is(ecx)); | 2700 ASSERT(ToRegister(instr->key()).is(ecx)); |
2679 ASSERT(ToRegister(instr->value()).is(eax)); | 2701 ASSERT(ToRegister(instr->value()).is(eax)); |
2680 | 2702 |
(...skipping 889 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3570 } else { | 3592 } else { |
3571 final_branch_condition = not_equal; | 3593 final_branch_condition = not_equal; |
3572 __ jmp(false_label); | 3594 __ jmp(false_label); |
3573 // A dead branch instruction will be generated after this point. | 3595 // A dead branch instruction will be generated after this point. |
3574 } | 3596 } |
3575 | 3597 |
3576 return final_branch_condition; | 3598 return final_branch_condition; |
3577 } | 3599 } |
3578 | 3600 |
3579 | 3601 |
| 3602 void LCodeGen::DoIsConstructCall(LIsConstructCall* instr) { |
| 3603 Register result = ToRegister(instr->result()); |
| 3604 NearLabel true_label; |
| 3605 NearLabel false_label; |
| 3606 NearLabel done; |
| 3607 |
| 3608 EmitIsConstructCall(result); |
| 3609 __ j(equal, &true_label); |
| 3610 |
| 3611 __ mov(result, Factory::false_value()); |
| 3612 __ jmp(&done); |
| 3613 |
| 3614 __ bind(&true_label); |
| 3615 __ mov(result, Factory::true_value()); |
| 3616 |
| 3617 __ bind(&done); |
| 3618 } |
| 3619 |
| 3620 |
| 3621 void LCodeGen::DoIsConstructCallAndBranch(LIsConstructCallAndBranch* instr) { |
| 3622 Register temp = ToRegister(instr->TempAt(0)); |
| 3623 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 3624 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 3625 |
| 3626 EmitIsConstructCall(temp); |
| 3627 EmitBranch(true_block, false_block, equal); |
| 3628 } |
| 3629 |
| 3630 |
| 3631 void LCodeGen::EmitIsConstructCall(Register temp) { |
| 3632 // Get the frame pointer for the calling frame. |
| 3633 __ mov(temp, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); |
| 3634 |
| 3635 // Skip the arguments adaptor frame if it exists. |
| 3636 NearLabel check_frame_marker; |
| 3637 __ cmp(Operand(temp, StandardFrameConstants::kContextOffset), |
| 3638 Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
| 3639 __ j(not_equal, &check_frame_marker); |
| 3640 __ mov(temp, Operand(temp, StandardFrameConstants::kCallerFPOffset)); |
| 3641 |
| 3642 // Check the marker in the calling frame. |
| 3643 __ bind(&check_frame_marker); |
| 3644 __ cmp(Operand(temp, StandardFrameConstants::kMarkerOffset), |
| 3645 Immediate(Smi::FromInt(StackFrame::CONSTRUCT))); |
| 3646 } |
| 3647 |
| 3648 |
3580 void LCodeGen::DoLazyBailout(LLazyBailout* instr) { | 3649 void LCodeGen::DoLazyBailout(LLazyBailout* instr) { |
3581 // No code for lazy bailout instruction. Used to capture environment after a | 3650 // No code for lazy bailout instruction. Used to capture environment after a |
3582 // call for populating the safepoint data with deoptimization data. | 3651 // call for populating the safepoint data with deoptimization data. |
3583 } | 3652 } |
3584 | 3653 |
3585 | 3654 |
3586 void LCodeGen::DoDeoptimize(LDeoptimize* instr) { | 3655 void LCodeGen::DoDeoptimize(LDeoptimize* instr) { |
3587 DeoptimizeIf(no_condition, instr->environment()); | 3656 DeoptimizeIf(no_condition, instr->environment()); |
3588 } | 3657 } |
3589 | 3658 |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3637 ASSERT(osr_pc_offset_ == -1); | 3706 ASSERT(osr_pc_offset_ == -1); |
3638 osr_pc_offset_ = masm()->pc_offset(); | 3707 osr_pc_offset_ = masm()->pc_offset(); |
3639 } | 3708 } |
3640 | 3709 |
3641 | 3710 |
3642 #undef __ | 3711 #undef __ |
3643 | 3712 |
3644 } } // namespace v8::internal | 3713 } } // namespace v8::internal |
3645 | 3714 |
3646 #endif // V8_TARGET_ARCH_IA32 | 3715 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |