| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 2883 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2894 LLoadExternalArrayPointer* instr) { | 2894 LLoadExternalArrayPointer* instr) { |
| 2895 Register result = ToRegister(instr->result()); | 2895 Register result = ToRegister(instr->result()); |
| 2896 Register input = ToRegister(instr->object()); | 2896 Register input = ToRegister(instr->object()); |
| 2897 __ movq(result, FieldOperand(input, | 2897 __ movq(result, FieldOperand(input, |
| 2898 ExternalPixelArray::kExternalPointerOffset)); | 2898 ExternalPixelArray::kExternalPointerOffset)); |
| 2899 } | 2899 } |
| 2900 | 2900 |
| 2901 | 2901 |
| 2902 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { | 2902 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { |
| 2903 Register arguments = ToRegister(instr->arguments()); | 2903 Register arguments = ToRegister(instr->arguments()); |
| 2904 Register length = ToRegister(instr->length()); | |
| 2905 Register result = ToRegister(instr->result()); | 2904 Register result = ToRegister(instr->result()); |
| 2906 // There are two words between the frame pointer and the last argument. | 2905 |
| 2907 // Subtracting from length accounts for one of them add one more. | 2906 if (instr->length()->IsConstantOperand() && |
| 2908 if (instr->index()->IsRegister()) { | 2907 instr->index()->IsConstantOperand()) { |
| 2909 __ subl(length, ToRegister(instr->index())); | 2908 int const_index = ToInteger32(LConstantOperand::cast(instr->index())); |
| 2909 int const_length = ToInteger32(LConstantOperand::cast(instr->length())); |
| 2910 int index = (const_length - const_index) + 1; |
| 2911 __ movq(result, Operand(arguments, index * kPointerSize)); |
| 2910 } else { | 2912 } else { |
| 2911 __ subl(length, ToOperand(instr->index())); | 2913 Register length = ToRegister(instr->length()); |
| 2914 // There are two words between the frame pointer and the last argument. |
| 2915 // Subtracting from length accounts for one of them add one more. |
| 2916 if (instr->index()->IsRegister()) { |
| 2917 __ subl(length, ToRegister(instr->index())); |
| 2918 } else { |
| 2919 __ subl(length, ToOperand(instr->index())); |
| 2920 } |
| 2921 __ movq(result, |
| 2922 Operand(arguments, length, times_pointer_size, kPointerSize)); |
| 2912 } | 2923 } |
| 2913 __ movq(result, Operand(arguments, length, times_pointer_size, kPointerSize)); | |
| 2914 } | 2924 } |
| 2915 | 2925 |
| 2916 | 2926 |
| 2917 void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) { | 2927 void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) { |
| 2918 ElementsKind elements_kind = instr->elements_kind(); | 2928 ElementsKind elements_kind = instr->elements_kind(); |
| 2919 LOperand* key = instr->key(); | 2929 LOperand* key = instr->key(); |
| 2920 if (!key->IsConstantOperand()) { | 2930 if (!key->IsConstantOperand()) { |
| 2921 Register key_reg = ToRegister(key); | 2931 Register key_reg = ToRegister(key); |
| 2922 // Even though the HLoad/StoreKeyed (in this case) instructions force | 2932 // Even though the HLoad/StoreKeyed (in this case) instructions force |
| 2923 // the input representation for the key to be an integer, the input | 2933 // the input representation for the key to be an integer, the input |
| (...skipping 987 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3911 | 3921 |
| 3912 void LCodeGen::DoInnerAllocatedObject(LInnerAllocatedObject* instr) { | 3922 void LCodeGen::DoInnerAllocatedObject(LInnerAllocatedObject* instr) { |
| 3913 Register result = ToRegister(instr->result()); | 3923 Register result = ToRegister(instr->result()); |
| 3914 Register base = ToRegister(instr->base_object()); | 3924 Register base = ToRegister(instr->base_object()); |
| 3915 __ lea(result, Operand(base, instr->offset())); | 3925 __ lea(result, Operand(base, instr->offset())); |
| 3916 } | 3926 } |
| 3917 | 3927 |
| 3918 | 3928 |
| 3919 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { | 3929 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { |
| 3920 Register object = ToRegister(instr->object()); | 3930 Register object = ToRegister(instr->object()); |
| 3921 Register value = ToRegister(instr->value()); | |
| 3922 int offset = instr->offset(); | 3931 int offset = instr->offset(); |
| 3923 | 3932 |
| 3924 if (!instr->transition().is_null()) { | 3933 if (!instr->transition().is_null()) { |
| 3925 if (!instr->hydrogen()->NeedsWriteBarrierForMap()) { | 3934 if (!instr->hydrogen()->NeedsWriteBarrierForMap()) { |
| 3926 __ Move(FieldOperand(object, HeapObject::kMapOffset), | 3935 __ Move(FieldOperand(object, HeapObject::kMapOffset), |
| 3927 instr->transition()); | 3936 instr->transition()); |
| 3928 } else { | 3937 } else { |
| 3929 Register temp = ToRegister(instr->temp()); | 3938 Register temp = ToRegister(instr->temp()); |
| 3930 __ Move(kScratchRegister, instr->transition()); | 3939 __ Move(kScratchRegister, instr->transition()); |
| 3931 __ movq(FieldOperand(object, HeapObject::kMapOffset), kScratchRegister); | 3940 __ movq(FieldOperand(object, HeapObject::kMapOffset), kScratchRegister); |
| 3932 // Update the write barrier for the map field. | 3941 // Update the write barrier for the map field. |
| 3933 __ RecordWriteField(object, | 3942 __ RecordWriteField(object, |
| 3934 HeapObject::kMapOffset, | 3943 HeapObject::kMapOffset, |
| 3935 kScratchRegister, | 3944 kScratchRegister, |
| 3936 temp, | 3945 temp, |
| 3937 kSaveFPRegs, | 3946 kSaveFPRegs, |
| 3938 OMIT_REMEMBERED_SET, | 3947 OMIT_REMEMBERED_SET, |
| 3939 OMIT_SMI_CHECK); | 3948 OMIT_SMI_CHECK); |
| 3940 } | 3949 } |
| 3941 } | 3950 } |
| 3942 | 3951 |
| 3943 // Do the store. | 3952 // Do the store. |
| 3944 HType type = instr->hydrogen()->value()->type(); | 3953 HType type = instr->hydrogen()->value()->type(); |
| 3945 SmiCheck check_needed = | 3954 SmiCheck check_needed = |
| 3946 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; | 3955 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; |
| 3947 if (instr->is_in_object()) { | 3956 |
| 3948 __ movq(FieldOperand(object, offset), value); | 3957 Register write_register = object; |
| 3949 if (instr->hydrogen()->NeedsWriteBarrier()) { | 3958 if (!instr->is_in_object()) { |
| 3950 Register temp = ToRegister(instr->temp()); | 3959 write_register = ToRegister(instr->temp()); |
| 3951 // Update the write barrier for the object for in-object properties. | 3960 __ movq(write_register, FieldOperand(object, JSObject::kPropertiesOffset)); |
| 3952 __ RecordWriteField(object, | 3961 } |
| 3953 offset, | 3962 |
| 3954 value, | 3963 if (instr->value()->IsConstantOperand()) { |
| 3955 temp, | 3964 LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); |
| 3956 kSaveFPRegs, | 3965 if (IsInteger32Constant(operand_value)) { |
| 3957 EMIT_REMEMBERED_SET, | 3966 int const_value = ToInteger32(operand_value); |
| 3958 check_needed); | 3967 __ movq(FieldOperand(write_register, offset), Immediate(const_value)); |
| 3968 } else { |
| 3969 if (operand_value->IsRegister()) { |
| 3970 __ movq(FieldOperand(write_register, offset), |
| 3971 ToRegister(operand_value)); |
| 3972 } else { |
| 3973 Handle<Object> handle_value = ToHandle(operand_value); |
| 3974 __ Move(FieldOperand(write_register, offset), handle_value); |
| 3975 } |
| 3959 } | 3976 } |
| 3960 } else { | 3977 } else { |
| 3961 Register temp = ToRegister(instr->temp()); | 3978 __ movq(FieldOperand(write_register, offset), ToRegister(instr->value())); |
| 3962 __ movq(temp, FieldOperand(object, JSObject::kPropertiesOffset)); | 3979 } |
| 3963 __ movq(FieldOperand(temp, offset), value); | 3980 |
| 3964 if (instr->hydrogen()->NeedsWriteBarrier()) { | 3981 if (instr->hydrogen()->NeedsWriteBarrier()) { |
| 3965 // Update the write barrier for the properties array. | 3982 Register value = ToRegister(instr->value()); |
| 3966 // object is used as a scratch register. | 3983 Register temp = instr->is_in_object() ? ToRegister(instr->temp()) : object; |
| 3967 __ RecordWriteField(temp, | 3984 // Update the write barrier for the object for in-object properties. |
| 3968 offset, | 3985 __ RecordWriteField(write_register, |
| 3969 value, | 3986 offset, |
| 3970 object, | 3987 value, |
| 3971 kSaveFPRegs, | 3988 temp, |
| 3972 EMIT_REMEMBERED_SET, | 3989 kSaveFPRegs, |
| 3973 check_needed); | 3990 EMIT_REMEMBERED_SET, |
| 3974 } | 3991 check_needed); |
| 3975 } | 3992 } |
| 3976 } | 3993 } |
| 3977 | 3994 |
| 3978 | 3995 |
| 3979 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { | 3996 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { |
| 3980 ASSERT(ToRegister(instr->object()).is(rdx)); | 3997 ASSERT(ToRegister(instr->object()).is(rdx)); |
| 3981 ASSERT(ToRegister(instr->value()).is(rax)); | 3998 ASSERT(ToRegister(instr->value()).is(rax)); |
| 3982 | 3999 |
| 3983 __ Move(rcx, instr->hydrogen()->name()); | 4000 __ Move(rcx, instr->hydrogen()->name()); |
| 3984 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) | 4001 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4130 key, | 4147 key, |
| 4131 FAST_DOUBLE_ELEMENTS, | 4148 FAST_DOUBLE_ELEMENTS, |
| 4132 FixedDoubleArray::kHeaderSize - kHeapObjectTag, | 4149 FixedDoubleArray::kHeaderSize - kHeapObjectTag, |
| 4133 instr->additional_index()); | 4150 instr->additional_index()); |
| 4134 | 4151 |
| 4135 __ movsd(double_store_operand, value); | 4152 __ movsd(double_store_operand, value); |
| 4136 } | 4153 } |
| 4137 | 4154 |
| 4138 | 4155 |
| 4139 void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) { | 4156 void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) { |
| 4140 Register value = ToRegister(instr->value()); | |
| 4141 Register elements = ToRegister(instr->elements()); | 4157 Register elements = ToRegister(instr->elements()); |
| 4142 LOperand* key = instr->key(); | 4158 LOperand* key = instr->key(); |
| 4143 if (!key->IsConstantOperand()) { | 4159 if (!key->IsConstantOperand()) { |
| 4144 Register key_reg = ToRegister(key); | 4160 Register key_reg = ToRegister(key); |
| 4145 // Even though the HLoad/StoreKeyedFastElement instructions force | 4161 // Even though the HLoad/StoreKeyedFastElement instructions force |
| 4146 // the input representation for the key to be an integer, the | 4162 // the input representation for the key to be an integer, the |
| 4147 // input gets replaced during bound check elimination with the index | 4163 // input gets replaced during bound check elimination with the index |
| 4148 // argument to the bounds check, which can be tagged, so that case | 4164 // argument to the bounds check, which can be tagged, so that case |
| 4149 // must be handled here, too. | 4165 // must be handled here, too. |
| 4150 if (instr->hydrogen()->key()->representation().IsTagged()) { | 4166 if (instr->hydrogen()->key()->representation().IsTagged()) { |
| 4151 __ SmiToInteger64(key_reg, key_reg); | 4167 __ SmiToInteger64(key_reg, key_reg); |
| 4152 } else if (instr->hydrogen()->IsDehoisted()) { | 4168 } else if (instr->hydrogen()->IsDehoisted()) { |
| 4153 // Sign extend key because it could be a 32 bit negative value | 4169 // Sign extend key because it could be a 32 bit negative value |
| 4154 // and the dehoisted address computation happens in 64 bits | 4170 // and the dehoisted address computation happens in 64 bits |
| 4155 __ movsxlq(key_reg, key_reg); | 4171 __ movsxlq(key_reg, key_reg); |
| 4156 } | 4172 } |
| 4157 } | 4173 } |
| 4158 | 4174 |
| 4159 Operand operand = | 4175 Operand operand = |
| 4160 BuildFastArrayOperand(instr->elements(), | 4176 BuildFastArrayOperand(instr->elements(), |
| 4161 key, | 4177 key, |
| 4162 FAST_ELEMENTS, | 4178 FAST_ELEMENTS, |
| 4163 FixedArray::kHeaderSize - kHeapObjectTag, | 4179 FixedArray::kHeaderSize - kHeapObjectTag, |
| 4164 instr->additional_index()); | 4180 instr->additional_index()); |
| 4181 if (instr->value()->IsRegister()) { |
| 4182 __ movq(operand, ToRegister(instr->value())); |
| 4183 } else { |
| 4184 LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); |
| 4185 if (IsInteger32Constant(operand_value)) { |
| 4186 Smi* smi_value = Smi::FromInt(ToInteger32(operand_value)); |
| 4187 __ Move(operand, smi_value); |
| 4188 } else { |
| 4189 Handle<Object> handle_value = ToHandle(operand_value); |
| 4190 __ Move(operand, handle_value); |
| 4191 } |
| 4192 } |
| 4165 | 4193 |
| 4166 if (instr->hydrogen()->NeedsWriteBarrier()) { | 4194 if (instr->hydrogen()->NeedsWriteBarrier()) { |
| 4195 ASSERT(instr->value()->IsRegister()); |
| 4196 Register value = ToRegister(instr->value()); |
| 4167 ASSERT(!instr->key()->IsConstantOperand()); | 4197 ASSERT(!instr->key()->IsConstantOperand()); |
| 4168 HType type = instr->hydrogen()->value()->type(); | 4198 HType type = instr->hydrogen()->value()->type(); |
| 4169 SmiCheck check_needed = | 4199 SmiCheck check_needed = |
| 4170 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; | 4200 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; |
| 4171 // Compute address of modified element and store it into key register. | 4201 // Compute address of modified element and store it into key register. |
| 4172 Register key_reg(ToRegister(key)); | 4202 Register key_reg(ToRegister(key)); |
| 4173 __ lea(key_reg, operand); | 4203 __ lea(key_reg, operand); |
| 4174 __ movq(Operand(key_reg, 0), value); | |
| 4175 __ RecordWrite(elements, | 4204 __ RecordWrite(elements, |
| 4176 key_reg, | 4205 key_reg, |
| 4177 value, | 4206 value, |
| 4178 kSaveFPRegs, | 4207 kSaveFPRegs, |
| 4179 EMIT_REMEMBERED_SET, | 4208 EMIT_REMEMBERED_SET, |
| 4180 check_needed); | 4209 check_needed); |
| 4181 } else { | |
| 4182 __ movq(operand, value); | |
| 4183 } | 4210 } |
| 4184 } | 4211 } |
| 4185 | 4212 |
| 4186 | 4213 |
| 4187 void LCodeGen::DoStoreKeyed(LStoreKeyed* instr) { | 4214 void LCodeGen::DoStoreKeyed(LStoreKeyed* instr) { |
| 4188 if (instr->is_external()) { | 4215 if (instr->is_external()) { |
| 4189 DoStoreKeyedExternalArray(instr); | 4216 DoStoreKeyedExternalArray(instr); |
| 4190 } else if (instr->hydrogen()->value()->representation().IsDouble()) { | 4217 } else if (instr->hydrogen()->value()->representation().IsDouble()) { |
| 4191 DoStoreKeyedFixedDoubleArray(instr); | 4218 DoStoreKeyedFixedDoubleArray(instr); |
| 4192 } else { | 4219 } else { |
| (...skipping 1468 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5661 FixedArray::kHeaderSize - kPointerSize)); | 5688 FixedArray::kHeaderSize - kPointerSize)); |
| 5662 __ bind(&done); | 5689 __ bind(&done); |
| 5663 } | 5690 } |
| 5664 | 5691 |
| 5665 | 5692 |
| 5666 #undef __ | 5693 #undef __ |
| 5667 | 5694 |
| 5668 } } // namespace v8::internal | 5695 } } // namespace v8::internal |
| 5669 | 5696 |
| 5670 #endif // V8_TARGET_ARCH_X64 | 5697 #endif // V8_TARGET_ARCH_X64 |
| OLD | NEW |