| OLD | NEW |
| 1 // Copyright 2011 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 |
| 11 // with the distribution. | 11 // with the distribution. |
| (...skipping 1812 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1824 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1824 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 1825 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1825 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 1826 | 1826 |
| 1827 __ test(FieldOperand(input, String::kHashFieldOffset), | 1827 __ test(FieldOperand(input, String::kHashFieldOffset), |
| 1828 Immediate(String::kContainsCachedArrayIndexMask)); | 1828 Immediate(String::kContainsCachedArrayIndexMask)); |
| 1829 EmitBranch(true_block, false_block, equal); | 1829 EmitBranch(true_block, false_block, equal); |
| 1830 } | 1830 } |
| 1831 | 1831 |
| 1832 | 1832 |
| 1833 // Branches to a label or falls through with the answer in the z flag. Trashes | 1833 // Branches to a label or falls through with the answer in the z flag. Trashes |
| 1834 // the temp registers, but not the input. Only input and temp2 may alias. | 1834 // the temp registers, but not the input. |
| 1835 void LCodeGen::EmitClassOfTest(Label* is_true, | 1835 void LCodeGen::EmitClassOfTest(Label* is_true, |
| 1836 Label* is_false, | 1836 Label* is_false, |
| 1837 Handle<String>class_name, | 1837 Handle<String>class_name, |
| 1838 Register input, | 1838 Register input, |
| 1839 Register temp, | 1839 Register temp, |
| 1840 Register temp2) { | 1840 Register temp2) { |
| 1841 ASSERT(!input.is(temp)); | 1841 ASSERT(!input.is(temp)); |
| 1842 ASSERT(!temp.is(temp2)); // But input and temp2 may be the same register. | 1842 ASSERT(!input.is(temp2)); |
| 1843 ASSERT(!temp.is(temp2)); |
| 1843 __ JumpIfSmi(input, is_false); | 1844 __ JumpIfSmi(input, is_false); |
| 1844 | 1845 |
| 1845 if (class_name->IsEqualTo(CStrVector("Function"))) { | 1846 if (class_name->IsEqualTo(CStrVector("Function"))) { |
| 1846 // Assuming the following assertions, we can use the same compares to test | 1847 // Assuming the following assertions, we can use the same compares to test |
| 1847 // for both being a function type and being in the object type range. | 1848 // for both being a function type and being in the object type range. |
| 1848 STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2); | 1849 STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2); |
| 1849 STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE == | 1850 STATIC_ASSERT(FIRST_NONCALLABLE_SPEC_OBJECT_TYPE == |
| 1850 FIRST_SPEC_OBJECT_TYPE + 1); | 1851 FIRST_SPEC_OBJECT_TYPE + 1); |
| 1851 STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == | 1852 STATIC_ASSERT(LAST_NONCALLABLE_SPEC_OBJECT_TYPE == |
| 1852 LAST_SPEC_OBJECT_TYPE - 1); | 1853 LAST_SPEC_OBJECT_TYPE - 1); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1892 // comparison. | 1893 // comparison. |
| 1893 __ cmp(temp, class_name); | 1894 __ cmp(temp, class_name); |
| 1894 // End with the answer in the z flag. | 1895 // End with the answer in the z flag. |
| 1895 } | 1896 } |
| 1896 | 1897 |
| 1897 | 1898 |
| 1898 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { | 1899 void LCodeGen::DoClassOfTestAndBranch(LClassOfTestAndBranch* instr) { |
| 1899 Register input = ToRegister(instr->InputAt(0)); | 1900 Register input = ToRegister(instr->InputAt(0)); |
| 1900 Register temp = ToRegister(instr->TempAt(0)); | 1901 Register temp = ToRegister(instr->TempAt(0)); |
| 1901 Register temp2 = ToRegister(instr->TempAt(1)); | 1902 Register temp2 = ToRegister(instr->TempAt(1)); |
| 1902 if (input.is(temp)) { | 1903 |
| 1903 // Swap. | |
| 1904 Register swapper = temp; | |
| 1905 temp = temp2; | |
| 1906 temp2 = swapper; | |
| 1907 } | |
| 1908 Handle<String> class_name = instr->hydrogen()->class_name(); | 1904 Handle<String> class_name = instr->hydrogen()->class_name(); |
| 1909 | 1905 |
| 1910 int true_block = chunk_->LookupDestination(instr->true_block_id()); | 1906 int true_block = chunk_->LookupDestination(instr->true_block_id()); |
| 1911 int false_block = chunk_->LookupDestination(instr->false_block_id()); | 1907 int false_block = chunk_->LookupDestination(instr->false_block_id()); |
| 1912 | 1908 |
| 1913 Label* true_label = chunk_->GetAssemblyLabel(true_block); | 1909 Label* true_label = chunk_->GetAssemblyLabel(true_block); |
| 1914 Label* false_label = chunk_->GetAssemblyLabel(false_block); | 1910 Label* false_label = chunk_->GetAssemblyLabel(false_block); |
| 1915 | 1911 |
| 1916 EmitClassOfTest(true_label, false_label, class_name, input, temp, temp2); | 1912 EmitClassOfTest(true_label, false_label, class_name, input, temp, temp2); |
| 1917 | 1913 |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1972 // A Smi is not an instance of anything. | 1968 // A Smi is not an instance of anything. |
| 1973 __ JumpIfSmi(object, &false_result); | 1969 __ JumpIfSmi(object, &false_result); |
| 1974 | 1970 |
| 1975 // This is the inlined call site instanceof cache. The two occurences of the | 1971 // This is the inlined call site instanceof cache. The two occurences of the |
| 1976 // hole value will be patched to the last map/result pair generated by the | 1972 // hole value will be patched to the last map/result pair generated by the |
| 1977 // instanceof stub. | 1973 // instanceof stub. |
| 1978 Label cache_miss; | 1974 Label cache_miss; |
| 1979 Register map = ToRegister(instr->TempAt(0)); | 1975 Register map = ToRegister(instr->TempAt(0)); |
| 1980 __ mov(map, FieldOperand(object, HeapObject::kMapOffset)); | 1976 __ mov(map, FieldOperand(object, HeapObject::kMapOffset)); |
| 1981 __ bind(deferred->map_check()); // Label for calculating code patching. | 1977 __ bind(deferred->map_check()); // Label for calculating code patching. |
| 1982 __ cmp(map, factory()->the_hole_value()); // Patched to cached map. | 1978 Handle<JSGlobalPropertyCell> cache_cell = |
| 1979 factory()->NewJSGlobalPropertyCell(factory()->the_hole_value()); |
| 1980 __ cmp(map, Operand::Cell(cache_cell)); // Patched to cached map. |
| 1983 __ j(not_equal, &cache_miss, Label::kNear); | 1981 __ j(not_equal, &cache_miss, Label::kNear); |
| 1984 __ mov(eax, factory()->the_hole_value()); // Patched to either true or false. | 1982 __ mov(eax, factory()->the_hole_value()); // Patched to either true or false. |
| 1985 __ jmp(&done); | 1983 __ jmp(&done); |
| 1986 | 1984 |
| 1987 // The inlined call site cache did not match. Check for null and string | 1985 // The inlined call site cache did not match. Check for null and string |
| 1988 // before calling the deferred code. | 1986 // before calling the deferred code. |
| 1989 __ bind(&cache_miss); | 1987 __ bind(&cache_miss); |
| 1990 // Null is not an instance of anything. | 1988 // Null is not an instance of anything. |
| 1991 __ cmp(object, factory()->null_value()); | 1989 __ cmp(object, factory()->null_value()); |
| 1992 __ j(equal, &false_result); | 1990 __ j(equal, &false_result); |
| (...skipping 1016 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3009 MathPowStub stub(MathPowStub::INTEGER); | 3007 MathPowStub stub(MathPowStub::INTEGER); |
| 3010 __ CallStub(&stub); | 3008 __ CallStub(&stub); |
| 3011 } else { | 3009 } else { |
| 3012 ASSERT(exponent_type.IsDouble()); | 3010 ASSERT(exponent_type.IsDouble()); |
| 3013 MathPowStub stub(MathPowStub::DOUBLE); | 3011 MathPowStub stub(MathPowStub::DOUBLE); |
| 3014 __ CallStub(&stub); | 3012 __ CallStub(&stub); |
| 3015 } | 3013 } |
| 3016 } | 3014 } |
| 3017 | 3015 |
| 3018 | 3016 |
| 3017 void LCodeGen::DoRandom(LRandom* instr) { |
| 3018 // Having marked this instruction as a call we can use any |
| 3019 // registers. |
| 3020 ASSERT(ToDoubleRegister(instr->result()).is(xmm1)); |
| 3021 ASSERT(ToRegister(instr->InputAt(0)).is(eax)); |
| 3022 |
| 3023 __ PrepareCallCFunction(1, ebx); |
| 3024 __ mov(eax, FieldOperand(eax, GlobalObject::kGlobalContextOffset)); |
| 3025 __ mov(Operand(esp, 0), eax); |
| 3026 __ CallCFunction(ExternalReference::random_uint32_function(isolate()), 1); |
| 3027 |
| 3028 // Convert 32 random bits in eax to 0.(32 random bits) in a double |
| 3029 // by computing: |
| 3030 // ( 1.(20 0s)(32 random bits) x 2^20 ) - (1.0 x 2^20)). |
| 3031 __ mov(ebx, Immediate(0x49800000)); // 1.0 x 2^20 as single. |
| 3032 __ movd(xmm2, ebx); |
| 3033 __ movd(xmm1, eax); |
| 3034 __ cvtss2sd(xmm2, xmm2); |
| 3035 __ xorps(xmm1, xmm2); |
| 3036 __ subsd(xmm1, xmm2); |
| 3037 } |
| 3038 |
| 3039 |
| 3019 void LCodeGen::DoMathLog(LUnaryMathOperation* instr) { | 3040 void LCodeGen::DoMathLog(LUnaryMathOperation* instr) { |
| 3020 ASSERT(instr->value()->Equals(instr->result())); | 3041 ASSERT(instr->value()->Equals(instr->result())); |
| 3021 XMMRegister input_reg = ToDoubleRegister(instr->value()); | 3042 XMMRegister input_reg = ToDoubleRegister(instr->value()); |
| 3022 Label positive, done, zero; | 3043 Label positive, done, zero; |
| 3023 __ xorps(xmm0, xmm0); | 3044 __ xorps(xmm0, xmm0); |
| 3024 __ ucomisd(input_reg, xmm0); | 3045 __ ucomisd(input_reg, xmm0); |
| 3025 __ j(above, &positive, Label::kNear); | 3046 __ j(above, &positive, Label::kNear); |
| 3026 __ j(equal, &zero, Label::kNear); | 3047 __ j(equal, &zero, Label::kNear); |
| 3027 ExternalReference nan = | 3048 ExternalReference nan = |
| 3028 ExternalReference::address_of_canonical_non_hole_nan(); | 3049 ExternalReference::address_of_canonical_non_hole_nan(); |
| (...skipping 642 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3671 ASSERT(input->IsRegister() && input->Equals(instr->result())); | 3692 ASSERT(input->IsRegister() && input->Equals(instr->result())); |
| 3672 if (instr->needs_check()) { | 3693 if (instr->needs_check()) { |
| 3673 __ test(ToRegister(input), Immediate(kSmiTagMask)); | 3694 __ test(ToRegister(input), Immediate(kSmiTagMask)); |
| 3674 DeoptimizeIf(not_zero, instr->environment()); | 3695 DeoptimizeIf(not_zero, instr->environment()); |
| 3675 } | 3696 } |
| 3676 __ SmiUntag(ToRegister(input)); | 3697 __ SmiUntag(ToRegister(input)); |
| 3677 } | 3698 } |
| 3678 | 3699 |
| 3679 | 3700 |
| 3680 void LCodeGen::EmitNumberUntagD(Register input_reg, | 3701 void LCodeGen::EmitNumberUntagD(Register input_reg, |
| 3702 Register temp_reg, |
| 3681 XMMRegister result_reg, | 3703 XMMRegister result_reg, |
| 3682 bool deoptimize_on_undefined, | 3704 bool deoptimize_on_undefined, |
| 3705 bool deoptimize_on_minus_zero, |
| 3683 LEnvironment* env) { | 3706 LEnvironment* env) { |
| 3684 Label load_smi, done; | 3707 Label load_smi, done; |
| 3685 | 3708 |
| 3686 // Smi check. | 3709 // Smi check. |
| 3687 __ JumpIfSmi(input_reg, &load_smi, Label::kNear); | 3710 __ JumpIfSmi(input_reg, &load_smi, Label::kNear); |
| 3688 | 3711 |
| 3689 // Heap number map check. | 3712 // Heap number map check. |
| 3690 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), | 3713 __ cmp(FieldOperand(input_reg, HeapObject::kMapOffset), |
| 3691 factory()->heap_number_map()); | 3714 factory()->heap_number_map()); |
| 3692 if (deoptimize_on_undefined) { | 3715 if (deoptimize_on_undefined) { |
| 3693 DeoptimizeIf(not_equal, env); | 3716 DeoptimizeIf(not_equal, env); |
| 3694 } else { | 3717 } else { |
| 3695 Label heap_number; | 3718 Label heap_number; |
| 3696 __ j(equal, &heap_number, Label::kNear); | 3719 __ j(equal, &heap_number, Label::kNear); |
| 3697 | 3720 |
| 3698 __ cmp(input_reg, factory()->undefined_value()); | 3721 __ cmp(input_reg, factory()->undefined_value()); |
| 3699 DeoptimizeIf(not_equal, env); | 3722 DeoptimizeIf(not_equal, env); |
| 3700 | 3723 |
| 3701 // Convert undefined to NaN. | 3724 // Convert undefined to NaN. |
| 3702 ExternalReference nan = | 3725 ExternalReference nan = |
| 3703 ExternalReference::address_of_canonical_non_hole_nan(); | 3726 ExternalReference::address_of_canonical_non_hole_nan(); |
| 3704 __ movdbl(result_reg, Operand::StaticVariable(nan)); | 3727 __ movdbl(result_reg, Operand::StaticVariable(nan)); |
| 3705 __ jmp(&done, Label::kNear); | 3728 __ jmp(&done, Label::kNear); |
| 3706 | 3729 |
| 3707 __ bind(&heap_number); | 3730 __ bind(&heap_number); |
| 3708 } | 3731 } |
| 3709 // Heap number to XMM conversion. | 3732 // Heap number to XMM conversion. |
| 3710 __ movdbl(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset)); | 3733 __ movdbl(result_reg, FieldOperand(input_reg, HeapNumber::kValueOffset)); |
| 3734 if (deoptimize_on_minus_zero) { |
| 3735 XMMRegister xmm_scratch = xmm0; |
| 3736 __ xorps(xmm_scratch, xmm_scratch); |
| 3737 __ ucomisd(result_reg, xmm_scratch); |
| 3738 __ j(not_zero, &done, Label::kNear); |
| 3739 __ movmskpd(temp_reg, result_reg); |
| 3740 __ test_b(temp_reg, 1); |
| 3741 DeoptimizeIf(not_zero, env); |
| 3742 } |
| 3711 __ jmp(&done, Label::kNear); | 3743 __ jmp(&done, Label::kNear); |
| 3712 | 3744 |
| 3713 // Smi to XMM conversion | 3745 // Smi to XMM conversion |
| 3714 __ bind(&load_smi); | 3746 __ bind(&load_smi); |
| 3715 __ SmiUntag(input_reg); // Untag smi before converting to float. | 3747 __ SmiUntag(input_reg); // Untag smi before converting to float. |
| 3716 __ cvtsi2sd(result_reg, Operand(input_reg)); | 3748 __ cvtsi2sd(result_reg, Operand(input_reg)); |
| 3717 __ SmiTag(input_reg); // Retag smi. | 3749 __ SmiTag(input_reg); // Retag smi. |
| 3718 __ bind(&done); | 3750 __ bind(&done); |
| 3719 } | 3751 } |
| 3720 | 3752 |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3823 // Smi to int32 conversion | 3855 // Smi to int32 conversion |
| 3824 __ SmiUntag(input_reg); // Untag smi. | 3856 __ SmiUntag(input_reg); // Untag smi. |
| 3825 | 3857 |
| 3826 __ bind(deferred->exit()); | 3858 __ bind(deferred->exit()); |
| 3827 } | 3859 } |
| 3828 | 3860 |
| 3829 | 3861 |
| 3830 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { | 3862 void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) { |
| 3831 LOperand* input = instr->InputAt(0); | 3863 LOperand* input = instr->InputAt(0); |
| 3832 ASSERT(input->IsRegister()); | 3864 ASSERT(input->IsRegister()); |
| 3865 LOperand* temp = instr->TempAt(0); |
| 3866 ASSERT(temp == NULL || temp->IsRegister()); |
| 3833 LOperand* result = instr->result(); | 3867 LOperand* result = instr->result(); |
| 3834 ASSERT(result->IsDoubleRegister()); | 3868 ASSERT(result->IsDoubleRegister()); |
| 3835 | 3869 |
| 3836 Register input_reg = ToRegister(input); | 3870 Register input_reg = ToRegister(input); |
| 3837 XMMRegister result_reg = ToDoubleRegister(result); | 3871 XMMRegister result_reg = ToDoubleRegister(result); |
| 3838 | 3872 |
| 3839 EmitNumberUntagD(input_reg, result_reg, | 3873 bool deoptimize_on_minus_zero = |
| 3874 instr->hydrogen()->deoptimize_on_minus_zero(); |
| 3875 Register temp_reg = deoptimize_on_minus_zero ? ToRegister(temp) : no_reg; |
| 3876 |
| 3877 EmitNumberUntagD(input_reg, |
| 3878 temp_reg, |
| 3879 result_reg, |
| 3840 instr->hydrogen()->deoptimize_on_undefined(), | 3880 instr->hydrogen()->deoptimize_on_undefined(), |
| 3881 deoptimize_on_minus_zero, |
| 3841 instr->environment()); | 3882 instr->environment()); |
| 3842 } | 3883 } |
| 3843 | 3884 |
| 3844 | 3885 |
| 3845 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { | 3886 void LCodeGen::DoDoubleToI(LDoubleToI* instr) { |
| 3846 LOperand* input = instr->InputAt(0); | 3887 LOperand* input = instr->InputAt(0); |
| 3847 ASSERT(input->IsDoubleRegister()); | 3888 ASSERT(input->IsDoubleRegister()); |
| 3848 LOperand* result = instr->result(); | 3889 LOperand* result = instr->result(); |
| 3849 ASSERT(result->IsRegister()); | 3890 ASSERT(result->IsRegister()); |
| 3850 | 3891 |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4026 isolate()->factory()->NewJSGlobalPropertyCell(target); | 4067 isolate()->factory()->NewJSGlobalPropertyCell(target); |
| 4027 __ cmp(reg, Operand::Cell(cell)); | 4068 __ cmp(reg, Operand::Cell(cell)); |
| 4028 } else { | 4069 } else { |
| 4029 Operand operand = ToOperand(instr->value()); | 4070 Operand operand = ToOperand(instr->value()); |
| 4030 __ cmp(operand, target); | 4071 __ cmp(operand, target); |
| 4031 } | 4072 } |
| 4032 DeoptimizeIf(not_equal, instr->environment()); | 4073 DeoptimizeIf(not_equal, instr->environment()); |
| 4033 } | 4074 } |
| 4034 | 4075 |
| 4035 | 4076 |
| 4077 void LCodeGen::DoCheckMapCommon(Register reg, |
| 4078 Handle<Map> map, |
| 4079 CompareMapMode mode, |
| 4080 LEnvironment* env) { |
| 4081 Label success; |
| 4082 __ CompareMap(reg, map, &success, mode); |
| 4083 DeoptimizeIf(not_equal, env); |
| 4084 __ bind(&success); |
| 4085 } |
| 4086 |
| 4087 |
| 4036 void LCodeGen::DoCheckMap(LCheckMap* instr) { | 4088 void LCodeGen::DoCheckMap(LCheckMap* instr) { |
| 4037 LOperand* input = instr->InputAt(0); | 4089 LOperand* input = instr->InputAt(0); |
| 4038 ASSERT(input->IsRegister()); | 4090 ASSERT(input->IsRegister()); |
| 4039 Register reg = ToRegister(input); | 4091 Register reg = ToRegister(input); |
| 4040 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), | 4092 Handle<Map> map = instr->hydrogen()->map(); |
| 4041 instr->hydrogen()->map()); | 4093 DoCheckMapCommon(reg, map, instr->hydrogen()->mode(), instr->environment()); |
| 4042 DeoptimizeIf(not_equal, instr->environment()); | |
| 4043 } | 4094 } |
| 4044 | 4095 |
| 4045 | 4096 |
| 4046 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { | 4097 void LCodeGen::DoClampDToUint8(LClampDToUint8* instr) { |
| 4047 XMMRegister value_reg = ToDoubleRegister(instr->unclamped()); | 4098 XMMRegister value_reg = ToDoubleRegister(instr->unclamped()); |
| 4048 Register result_reg = ToRegister(instr->result()); | 4099 Register result_reg = ToRegister(instr->result()); |
| 4049 __ ClampDoubleToUint8(value_reg, xmm0, result_reg); | 4100 __ ClampDoubleToUint8(value_reg, xmm0, result_reg); |
| 4050 } | 4101 } |
| 4051 | 4102 |
| 4052 | 4103 |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4095 Register reg = ToRegister(instr->TempAt(0)); | 4146 Register reg = ToRegister(instr->TempAt(0)); |
| 4096 | 4147 |
| 4097 Handle<JSObject> holder = instr->holder(); | 4148 Handle<JSObject> holder = instr->holder(); |
| 4098 Handle<JSObject> current_prototype = instr->prototype(); | 4149 Handle<JSObject> current_prototype = instr->prototype(); |
| 4099 | 4150 |
| 4100 // Load prototype object. | 4151 // Load prototype object. |
| 4101 __ LoadHeapObject(reg, current_prototype); | 4152 __ LoadHeapObject(reg, current_prototype); |
| 4102 | 4153 |
| 4103 // Check prototype maps up to the holder. | 4154 // Check prototype maps up to the holder. |
| 4104 while (!current_prototype.is_identical_to(holder)) { | 4155 while (!current_prototype.is_identical_to(holder)) { |
| 4105 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), | 4156 DoCheckMapCommon(reg, Handle<Map>(current_prototype->map()), |
| 4106 Handle<Map>(current_prototype->map())); | 4157 ALLOW_ELEMENT_TRANSITION_MAPS, instr->environment()); |
| 4107 DeoptimizeIf(not_equal, instr->environment()); | 4158 |
| 4108 current_prototype = | 4159 current_prototype = |
| 4109 Handle<JSObject>(JSObject::cast(current_prototype->GetPrototype())); | 4160 Handle<JSObject>(JSObject::cast(current_prototype->GetPrototype())); |
| 4110 // Load next prototype object. | 4161 // Load next prototype object. |
| 4111 __ LoadHeapObject(reg, current_prototype); | 4162 __ LoadHeapObject(reg, current_prototype); |
| 4112 } | 4163 } |
| 4113 | 4164 |
| 4114 // Check the holder map. | 4165 // Check the holder map. |
| 4115 __ cmp(FieldOperand(reg, HeapObject::kMapOffset), | 4166 DoCheckMapCommon(reg, Handle<Map>(current_prototype->map()), |
| 4116 Handle<Map>(current_prototype->map())); | 4167 ALLOW_ELEMENT_TRANSITION_MAPS, instr->environment()); |
| 4117 DeoptimizeIf(not_equal, instr->environment()); | |
| 4118 } | 4168 } |
| 4119 | 4169 |
| 4120 | 4170 |
| 4121 void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) { | 4171 void LCodeGen::DoArrayLiteral(LArrayLiteral* instr) { |
| 4122 ASSERT(ToRegister(instr->context()).is(esi)); | 4172 ASSERT(ToRegister(instr->context()).is(esi)); |
| 4123 Heap* heap = isolate()->heap(); | 4173 Heap* heap = isolate()->heap(); |
| 4124 ElementsKind boilerplate_elements_kind = | 4174 ElementsKind boilerplate_elements_kind = |
| 4125 instr->hydrogen()->boilerplate_elements_kind(); | 4175 instr->hydrogen()->boilerplate_elements_kind(); |
| 4126 | 4176 |
| 4127 // Deopt if the array literal boilerplate ElementsKind is of a type different | 4177 // Deopt if the array literal boilerplate ElementsKind is of a type different |
| 4128 // than the expected one. The check isn't necessary if the boilerplate has | 4178 // than the expected one. The check isn't necessary if the boilerplate has |
| 4129 // already been converted to FAST_ELEMENTS. | 4179 // already been converted to FAST_ELEMENTS. |
| 4130 if (boilerplate_elements_kind != FAST_ELEMENTS) { | 4180 if (boilerplate_elements_kind != FAST_ELEMENTS) { |
| 4131 __ LoadHeapObject(eax, instr->hydrogen()->boilerplate_object()); | 4181 __ LoadHeapObject(eax, instr->hydrogen()->boilerplate_object()); |
| 4132 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); | 4182 __ mov(ebx, FieldOperand(eax, HeapObject::kMapOffset)); |
| 4133 // Load the map's "bit field 2". We only need the first byte, | 4183 // Load the map's "bit field 2". We only need the first byte, |
| 4134 // but the following masking takes care of that anyway. | 4184 // but the following masking takes care of that anyway. |
| 4135 __ mov(ebx, FieldOperand(ebx, Map::kBitField2Offset)); | 4185 __ mov(ebx, FieldOperand(ebx, Map::kBitField2Offset)); |
| 4136 // Retrieve elements_kind from bit field 2. | 4186 // Retrieve elements_kind from bit field 2. |
| 4137 __ and_(ebx, Map::kElementsKindMask); | 4187 __ and_(ebx, Map::kElementsKindMask); |
| 4138 __ cmp(ebx, boilerplate_elements_kind << Map::kElementsKindShift); | 4188 __ cmp(ebx, boilerplate_elements_kind << Map::kElementsKindShift); |
| 4139 DeoptimizeIf(not_equal, instr->environment()); | 4189 DeoptimizeIf(not_equal, instr->environment()); |
| 4140 } | 4190 } |
| 4141 | 4191 |
| 4142 // Setup the parameters to the stub/runtime call. | 4192 // Set up the parameters to the stub/runtime call. |
| 4143 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 4193 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
| 4144 __ push(FieldOperand(eax, JSFunction::kLiteralsOffset)); | 4194 __ push(FieldOperand(eax, JSFunction::kLiteralsOffset)); |
| 4145 __ push(Immediate(Smi::FromInt(instr->hydrogen()->literal_index()))); | 4195 __ push(Immediate(Smi::FromInt(instr->hydrogen()->literal_index()))); |
| 4146 // Boilerplate already exists, constant elements are never accessed. | 4196 // Boilerplate already exists, constant elements are never accessed. |
| 4147 // Pass an empty fixed array. | 4197 // Pass an empty fixed array. |
| 4148 __ push(Immediate(Handle<FixedArray>(heap->empty_fixed_array()))); | 4198 __ push(Immediate(Handle<FixedArray>(heap->empty_fixed_array()))); |
| 4149 | 4199 |
| 4150 // Pick the right runtime function or stub to call. | 4200 // Pick the right runtime function or stub to call. |
| 4151 int length = instr->hydrogen()->length(); | 4201 int length = instr->hydrogen()->length(); |
| 4152 if (instr->hydrogen()->IsCopyOnWrite()) { | 4202 if (instr->hydrogen()->IsCopyOnWrite()) { |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4240 EmitDeepCopy(instr->hydrogen()->boilerplate(), eax, ebx, &offset); | 4290 EmitDeepCopy(instr->hydrogen()->boilerplate(), eax, ebx, &offset); |
| 4241 ASSERT_EQ(size, offset); | 4291 ASSERT_EQ(size, offset); |
| 4242 } | 4292 } |
| 4243 | 4293 |
| 4244 | 4294 |
| 4245 void LCodeGen::DoObjectLiteralGeneric(LObjectLiteralGeneric* instr) { | 4295 void LCodeGen::DoObjectLiteralGeneric(LObjectLiteralGeneric* instr) { |
| 4246 ASSERT(ToRegister(instr->context()).is(esi)); | 4296 ASSERT(ToRegister(instr->context()).is(esi)); |
| 4247 Handle<FixedArray> constant_properties = | 4297 Handle<FixedArray> constant_properties = |
| 4248 instr->hydrogen()->constant_properties(); | 4298 instr->hydrogen()->constant_properties(); |
| 4249 | 4299 |
| 4250 // Setup the parameters to the stub/runtime call. | 4300 // Set up the parameters to the stub/runtime call. |
| 4251 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); | 4301 __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); |
| 4252 __ push(FieldOperand(eax, JSFunction::kLiteralsOffset)); | 4302 __ push(FieldOperand(eax, JSFunction::kLiteralsOffset)); |
| 4253 __ push(Immediate(Smi::FromInt(instr->hydrogen()->literal_index()))); | 4303 __ push(Immediate(Smi::FromInt(instr->hydrogen()->literal_index()))); |
| 4254 __ push(Immediate(constant_properties)); | 4304 __ push(Immediate(constant_properties)); |
| 4255 int flags = instr->hydrogen()->fast_elements() | 4305 int flags = instr->hydrogen()->fast_elements() |
| 4256 ? ObjectLiteral::kFastElements | 4306 ? ObjectLiteral::kFastElements |
| 4257 : ObjectLiteral::kNoFlags; | 4307 : ObjectLiteral::kNoFlags; |
| 4258 flags |= instr->hydrogen()->has_function() | 4308 flags |= instr->hydrogen()->has_function() |
| 4259 ? ObjectLiteral::kHasFunction | 4309 ? ObjectLiteral::kHasFunction |
| 4260 : ObjectLiteral::kNoFlags; | 4310 : ObjectLiteral::kNoFlags; |
| (...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4612 this, pointers, Safepoint::kLazyDeopt); | 4662 this, pointers, Safepoint::kLazyDeopt); |
| 4613 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator); | 4663 __ InvokeBuiltin(Builtins::IN, CALL_FUNCTION, safepoint_generator); |
| 4614 } | 4664 } |
| 4615 | 4665 |
| 4616 | 4666 |
| 4617 #undef __ | 4667 #undef __ |
| 4618 | 4668 |
| 4619 } } // namespace v8::internal | 4669 } } // namespace v8::internal |
| 4620 | 4670 |
| 4621 #endif // V8_TARGET_ARCH_IA32 | 4671 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |