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 2542 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2553 } | 2553 } |
2554 if (NeedsEagerFrame()) { | 2554 if (NeedsEagerFrame()) { |
2555 __ movq(rsp, rbp); | 2555 __ movq(rsp, rbp); |
2556 __ pop(rbp); | 2556 __ pop(rbp); |
2557 } | 2557 } |
2558 if (instr->has_constant_parameter_count()) { | 2558 if (instr->has_constant_parameter_count()) { |
2559 __ Ret((ToInteger32(instr->constant_parameter_count()) + 1) * kPointerSize, | 2559 __ Ret((ToInteger32(instr->constant_parameter_count()) + 1) * kPointerSize, |
2560 rcx); | 2560 rcx); |
2561 } else { | 2561 } else { |
2562 Register reg = ToRegister(instr->parameter_count()); | 2562 Register reg = ToRegister(instr->parameter_count()); |
| 2563 __ SmiToInteger32(reg, reg); |
2563 Register return_addr_reg = reg.is(rcx) ? rbx : rcx; | 2564 Register return_addr_reg = reg.is(rcx) ? rbx : rcx; |
2564 __ pop(return_addr_reg); | 2565 __ pop(return_addr_reg); |
2565 __ shl(reg, Immediate(kPointerSizeLog2)); | 2566 __ shl(reg, Immediate(kPointerSizeLog2)); |
2566 __ addq(rsp, reg); | 2567 __ addq(rsp, reg); |
2567 __ jmp(return_addr_reg); | 2568 __ jmp(return_addr_reg); |
2568 } | 2569 } |
2569 } | 2570 } |
2570 | 2571 |
2571 | 2572 |
2572 void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) { | 2573 void LCodeGen::DoLoadGlobalCell(LLoadGlobalCell* instr) { |
(...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2893 LLoadExternalArrayPointer* instr) { | 2894 LLoadExternalArrayPointer* instr) { |
2894 Register result = ToRegister(instr->result()); | 2895 Register result = ToRegister(instr->result()); |
2895 Register input = ToRegister(instr->object()); | 2896 Register input = ToRegister(instr->object()); |
2896 __ movq(result, FieldOperand(input, | 2897 __ movq(result, FieldOperand(input, |
2897 ExternalPixelArray::kExternalPointerOffset)); | 2898 ExternalPixelArray::kExternalPointerOffset)); |
2898 } | 2899 } |
2899 | 2900 |
2900 | 2901 |
2901 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { | 2902 void LCodeGen::DoAccessArgumentsAt(LAccessArgumentsAt* instr) { |
2902 Register arguments = ToRegister(instr->arguments()); | 2903 Register arguments = ToRegister(instr->arguments()); |
2903 Register length = ToRegister(instr->length()); | |
2904 Register result = ToRegister(instr->result()); | 2904 Register result = ToRegister(instr->result()); |
2905 // There are two words between the frame pointer and the last argument. | 2905 |
2906 // Subtracting from length accounts for one of them add one more. | 2906 if (instr->length()->IsConstantOperand() && |
2907 if (instr->index()->IsRegister()) { | 2907 instr->index()->IsConstantOperand()) { |
2908 __ 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)); |
2909 } else { | 2912 } else { |
2910 __ 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)); |
2911 } | 2923 } |
2912 __ movq(result, Operand(arguments, length, times_pointer_size, kPointerSize)); | |
2913 } | 2924 } |
2914 | 2925 |
2915 | 2926 |
2916 void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) { | 2927 void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) { |
2917 ElementsKind elements_kind = instr->elements_kind(); | 2928 ElementsKind elements_kind = instr->elements_kind(); |
2918 LOperand* key = instr->key(); | 2929 LOperand* key = instr->key(); |
2919 if (!key->IsConstantOperand()) { | 2930 if (!key->IsConstantOperand()) { |
2920 Register key_reg = ToRegister(key); | 2931 Register key_reg = ToRegister(key); |
2921 // Even though the HLoad/StoreKeyed (in this case) instructions force | 2932 // Even though the HLoad/StoreKeyed (in this case) instructions force |
2922 // 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 967 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3890 } | 3901 } |
3891 | 3902 |
3892 | 3903 |
3893 void LCodeGen::DoCallNewArray(LCallNewArray* instr) { | 3904 void LCodeGen::DoCallNewArray(LCallNewArray* instr) { |
3894 ASSERT(ToRegister(instr->constructor()).is(rdi)); | 3905 ASSERT(ToRegister(instr->constructor()).is(rdi)); |
3895 ASSERT(ToRegister(instr->result()).is(rax)); | 3906 ASSERT(ToRegister(instr->result()).is(rax)); |
3896 ASSERT(FLAG_optimize_constructed_arrays); | 3907 ASSERT(FLAG_optimize_constructed_arrays); |
3897 | 3908 |
3898 __ Set(rax, instr->arity()); | 3909 __ Set(rax, instr->arity()); |
3899 __ Move(rbx, instr->hydrogen()->property_cell()); | 3910 __ Move(rbx, instr->hydrogen()->property_cell()); |
3900 Handle<Code> array_construct_code = | 3911 Object* cell_value = instr->hydrogen()->property_cell()->value(); |
3901 isolate()->builtins()->ArrayConstructCode(); | 3912 ElementsKind kind = static_cast<ElementsKind>(Smi::cast(cell_value)->value()); |
3902 CallCode(array_construct_code, RelocInfo::CONSTRUCT_CALL, instr); | 3913 if (instr->arity() == 0) { |
| 3914 ArrayNoArgumentConstructorStub stub(kind); |
| 3915 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); |
| 3916 } else if (instr->arity() == 1) { |
| 3917 ArraySingleArgumentConstructorStub stub(kind); |
| 3918 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); |
| 3919 } else { |
| 3920 ArrayNArgumentsConstructorStub stub(kind); |
| 3921 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); |
| 3922 } |
3903 } | 3923 } |
3904 | 3924 |
3905 | 3925 |
3906 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { | 3926 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { |
3907 CallRuntime(instr->function(), instr->arity(), instr); | 3927 CallRuntime(instr->function(), instr->arity(), instr); |
3908 } | 3928 } |
3909 | 3929 |
3910 | 3930 |
3911 void LCodeGen::DoInnerAllocatedObject(LInnerAllocatedObject* instr) { | 3931 void LCodeGen::DoInnerAllocatedObject(LInnerAllocatedObject* instr) { |
3912 Register result = ToRegister(instr->result()); | 3932 Register result = ToRegister(instr->result()); |
3913 Register base = ToRegister(instr->base_object()); | 3933 Register base = ToRegister(instr->base_object()); |
3914 __ lea(result, Operand(base, instr->offset())); | 3934 __ lea(result, Operand(base, instr->offset())); |
3915 } | 3935 } |
3916 | 3936 |
3917 | 3937 |
3918 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { | 3938 void LCodeGen::DoStoreNamedField(LStoreNamedField* instr) { |
3919 Register object = ToRegister(instr->object()); | 3939 Register object = ToRegister(instr->object()); |
3920 Register value = ToRegister(instr->value()); | |
3921 int offset = instr->offset(); | 3940 int offset = instr->offset(); |
3922 | 3941 |
3923 if (!instr->transition().is_null()) { | 3942 if (!instr->transition().is_null()) { |
3924 if (!instr->hydrogen()->NeedsWriteBarrierForMap()) { | 3943 if (!instr->hydrogen()->NeedsWriteBarrierForMap()) { |
3925 __ Move(FieldOperand(object, HeapObject::kMapOffset), | 3944 __ Move(FieldOperand(object, HeapObject::kMapOffset), |
3926 instr->transition()); | 3945 instr->transition()); |
3927 } else { | 3946 } else { |
3928 Register temp = ToRegister(instr->temp()); | 3947 Register temp = ToRegister(instr->temp()); |
3929 __ Move(kScratchRegister, instr->transition()); | 3948 __ Move(kScratchRegister, instr->transition()); |
3930 __ movq(FieldOperand(object, HeapObject::kMapOffset), kScratchRegister); | 3949 __ movq(FieldOperand(object, HeapObject::kMapOffset), kScratchRegister); |
3931 // Update the write barrier for the map field. | 3950 // Update the write barrier for the map field. |
3932 __ RecordWriteField(object, | 3951 __ RecordWriteField(object, |
3933 HeapObject::kMapOffset, | 3952 HeapObject::kMapOffset, |
3934 kScratchRegister, | 3953 kScratchRegister, |
3935 temp, | 3954 temp, |
3936 kSaveFPRegs, | 3955 kSaveFPRegs, |
3937 OMIT_REMEMBERED_SET, | 3956 OMIT_REMEMBERED_SET, |
3938 OMIT_SMI_CHECK); | 3957 OMIT_SMI_CHECK); |
3939 } | 3958 } |
3940 } | 3959 } |
3941 | 3960 |
3942 // Do the store. | 3961 // Do the store. |
3943 HType type = instr->hydrogen()->value()->type(); | 3962 HType type = instr->hydrogen()->value()->type(); |
3944 SmiCheck check_needed = | 3963 SmiCheck check_needed = |
3945 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; | 3964 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; |
3946 if (instr->is_in_object()) { | 3965 if (instr->is_in_object()) { |
3947 __ movq(FieldOperand(object, offset), value); | 3966 if (instr->value()->IsConstantOperand()) { |
| 3967 LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); |
| 3968 if (IsInteger32Constant(operand_value)) { |
| 3969 int const_value = ToInteger32(operand_value); |
| 3970 __ movq(FieldOperand(object, offset), Immediate(const_value)); |
| 3971 } else { |
| 3972 if (operand_value->IsRegister()) { |
| 3973 __ movq(FieldOperand(object, offset), ToRegister(operand_value)); |
| 3974 } else { |
| 3975 Handle<Object> handle_value = ToHandle(operand_value); |
| 3976 __ Move(FieldOperand(object, offset), handle_value); |
| 3977 } |
| 3978 } |
| 3979 } else { |
| 3980 __ movq(FieldOperand(object, offset), ToRegister(instr->value())); |
| 3981 } |
| 3982 |
3948 if (instr->hydrogen()->NeedsWriteBarrier()) { | 3983 if (instr->hydrogen()->NeedsWriteBarrier()) { |
| 3984 Register value = ToRegister(instr->value()); |
3949 Register temp = ToRegister(instr->temp()); | 3985 Register temp = ToRegister(instr->temp()); |
3950 // Update the write barrier for the object for in-object properties. | 3986 // Update the write barrier for the object for in-object properties. |
3951 __ RecordWriteField(object, | 3987 __ RecordWriteField(object, |
3952 offset, | 3988 offset, |
3953 value, | 3989 value, |
3954 temp, | 3990 temp, |
3955 kSaveFPRegs, | 3991 kSaveFPRegs, |
3956 EMIT_REMEMBERED_SET, | 3992 EMIT_REMEMBERED_SET, |
3957 check_needed); | 3993 check_needed); |
3958 } | 3994 } |
3959 } else { | 3995 } else { |
3960 Register temp = ToRegister(instr->temp()); | 3996 Register temp = ToRegister(instr->temp()); |
3961 __ movq(temp, FieldOperand(object, JSObject::kPropertiesOffset)); | 3997 __ movq(temp, FieldOperand(object, JSObject::kPropertiesOffset)); |
3962 __ movq(FieldOperand(temp, offset), value); | 3998 |
| 3999 if (instr->value()->IsConstantOperand()) { |
| 4000 LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); |
| 4001 if (IsInteger32Constant(operand_value)) { |
| 4002 int const_value = ToInteger32(operand_value); |
| 4003 __ movq(FieldOperand(temp, offset), Immediate(const_value)); |
| 4004 } else { |
| 4005 if (operand_value->IsRegister()) { |
| 4006 __ movq(FieldOperand(temp, offset), ToRegister(operand_value)); |
| 4007 } else { |
| 4008 Handle<Object> handle_value = ToHandle(operand_value); |
| 4009 __ Move(FieldOperand(temp, offset), handle_value); |
| 4010 } |
| 4011 } |
| 4012 } else { |
| 4013 __ movq(FieldOperand(temp, offset), ToRegister(instr->value())); |
| 4014 } |
| 4015 |
3963 if (instr->hydrogen()->NeedsWriteBarrier()) { | 4016 if (instr->hydrogen()->NeedsWriteBarrier()) { |
| 4017 Register value = ToRegister(instr->value()); |
3964 // Update the write barrier for the properties array. | 4018 // Update the write barrier for the properties array. |
3965 // object is used as a scratch register. | 4019 // object is used as a scratch register. |
3966 __ RecordWriteField(temp, | 4020 __ RecordWriteField(temp, |
3967 offset, | 4021 offset, |
3968 value, | 4022 value, |
3969 object, | 4023 object, |
3970 kSaveFPRegs, | 4024 kSaveFPRegs, |
3971 EMIT_REMEMBERED_SET, | 4025 EMIT_REMEMBERED_SET, |
3972 check_needed); | 4026 check_needed); |
3973 } | 4027 } |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4129 key, | 4183 key, |
4130 FAST_DOUBLE_ELEMENTS, | 4184 FAST_DOUBLE_ELEMENTS, |
4131 FixedDoubleArray::kHeaderSize - kHeapObjectTag, | 4185 FixedDoubleArray::kHeaderSize - kHeapObjectTag, |
4132 instr->additional_index()); | 4186 instr->additional_index()); |
4133 | 4187 |
4134 __ movsd(double_store_operand, value); | 4188 __ movsd(double_store_operand, value); |
4135 } | 4189 } |
4136 | 4190 |
4137 | 4191 |
4138 void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) { | 4192 void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) { |
4139 Register value = ToRegister(instr->value()); | |
4140 Register elements = ToRegister(instr->elements()); | 4193 Register elements = ToRegister(instr->elements()); |
4141 LOperand* key = instr->key(); | 4194 LOperand* key = instr->key(); |
4142 if (!key->IsConstantOperand()) { | 4195 if (!key->IsConstantOperand()) { |
4143 Register key_reg = ToRegister(key); | 4196 Register key_reg = ToRegister(key); |
4144 // Even though the HLoad/StoreKeyedFastElement instructions force | 4197 // Even though the HLoad/StoreKeyedFastElement instructions force |
4145 // the input representation for the key to be an integer, the | 4198 // the input representation for the key to be an integer, the |
4146 // input gets replaced during bound check elimination with the index | 4199 // input gets replaced during bound check elimination with the index |
4147 // argument to the bounds check, which can be tagged, so that case | 4200 // argument to the bounds check, which can be tagged, so that case |
4148 // must be handled here, too. | 4201 // must be handled here, too. |
4149 if (instr->hydrogen()->key()->representation().IsTagged()) { | 4202 if (instr->hydrogen()->key()->representation().IsTagged()) { |
4150 __ SmiToInteger64(key_reg, key_reg); | 4203 __ SmiToInteger64(key_reg, key_reg); |
4151 } else if (instr->hydrogen()->IsDehoisted()) { | 4204 } else if (instr->hydrogen()->IsDehoisted()) { |
4152 // Sign extend key because it could be a 32 bit negative value | 4205 // Sign extend key because it could be a 32 bit negative value |
4153 // and the dehoisted address computation happens in 64 bits | 4206 // and the dehoisted address computation happens in 64 bits |
4154 __ movsxlq(key_reg, key_reg); | 4207 __ movsxlq(key_reg, key_reg); |
4155 } | 4208 } |
4156 } | 4209 } |
4157 | 4210 |
4158 Operand operand = | 4211 Operand operand = |
4159 BuildFastArrayOperand(instr->elements(), | 4212 BuildFastArrayOperand(instr->elements(), |
4160 key, | 4213 key, |
4161 FAST_ELEMENTS, | 4214 FAST_ELEMENTS, |
4162 FixedArray::kHeaderSize - kHeapObjectTag, | 4215 FixedArray::kHeaderSize - kHeapObjectTag, |
4163 instr->additional_index()); | 4216 instr->additional_index()); |
| 4217 if (instr->value()->IsRegister()) { |
| 4218 __ movq(operand, ToRegister(instr->value())); |
| 4219 } else { |
| 4220 LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); |
| 4221 if (IsInteger32Constant(operand_value)) { |
| 4222 int const_value = ToInteger32(operand_value); |
| 4223 __ movq(operand, Immediate(const_value)); |
| 4224 } else { |
| 4225 Handle<Object> handle_value = ToHandle(operand_value); |
| 4226 __ Move(operand, handle_value); |
| 4227 } |
| 4228 } |
4164 | 4229 |
4165 if (instr->hydrogen()->NeedsWriteBarrier()) { | 4230 if (instr->hydrogen()->NeedsWriteBarrier()) { |
| 4231 ASSERT(instr->value()->IsRegister()); |
| 4232 Register value = ToRegister(instr->value()); |
4166 ASSERT(!instr->key()->IsConstantOperand()); | 4233 ASSERT(!instr->key()->IsConstantOperand()); |
4167 HType type = instr->hydrogen()->value()->type(); | 4234 HType type = instr->hydrogen()->value()->type(); |
4168 SmiCheck check_needed = | 4235 SmiCheck check_needed = |
4169 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; | 4236 type.IsHeapObject() ? OMIT_SMI_CHECK : INLINE_SMI_CHECK; |
4170 // Compute address of modified element and store it into key register. | 4237 // Compute address of modified element and store it into key register. |
4171 Register key_reg(ToRegister(key)); | 4238 Register key_reg(ToRegister(key)); |
4172 __ lea(key_reg, operand); | 4239 __ lea(key_reg, operand); |
4173 __ movq(Operand(key_reg, 0), value); | 4240 __ movq(Operand(key_reg, 0), value); |
4174 __ RecordWrite(elements, | 4241 __ RecordWrite(elements, |
4175 key_reg, | 4242 key_reg, |
4176 value, | 4243 value, |
4177 kSaveFPRegs, | 4244 kSaveFPRegs, |
4178 EMIT_REMEMBERED_SET, | 4245 EMIT_REMEMBERED_SET, |
4179 check_needed); | 4246 check_needed); |
4180 } else { | |
4181 __ movq(operand, value); | |
4182 } | 4247 } |
| 4248 |
| 4249 // TODO(mvstanton): we don't need this line, do we? |
| 4250 // else { |
| 4251 // __ movq(operand, value); |
| 4252 // } |
4183 } | 4253 } |
4184 | 4254 |
4185 | 4255 |
4186 void LCodeGen::DoStoreKeyed(LStoreKeyed* instr) { | 4256 void LCodeGen::DoStoreKeyed(LStoreKeyed* instr) { |
4187 if (instr->is_external()) { | 4257 if (instr->is_external()) { |
4188 DoStoreKeyedExternalArray(instr); | 4258 DoStoreKeyedExternalArray(instr); |
4189 } else if (instr->hydrogen()->value()->representation().IsDouble()) { | 4259 } else if (instr->hydrogen()->value()->representation().IsDouble()) { |
4190 DoStoreKeyedFixedDoubleArray(instr); | 4260 DoStoreKeyedFixedDoubleArray(instr); |
4191 } else { | 4261 } else { |
4192 DoStoreKeyedFixedArray(instr); | 4262 DoStoreKeyedFixedArray(instr); |
(...skipping 1467 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5660 FixedArray::kHeaderSize - kPointerSize)); | 5730 FixedArray::kHeaderSize - kPointerSize)); |
5661 __ bind(&done); | 5731 __ bind(&done); |
5662 } | 5732 } |
5663 | 5733 |
5664 | 5734 |
5665 #undef __ | 5735 #undef __ |
5666 | 5736 |
5667 } } // namespace v8::internal | 5737 } } // namespace v8::internal |
5668 | 5738 |
5669 #endif // V8_TARGET_ARCH_X64 | 5739 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |