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 |