OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_X64 | 7 #if V8_TARGET_ARCH_X64 |
8 | 8 |
9 #include "src/x64/lithium-codegen-x64.h" | 9 #include "src/x64/lithium-codegen-x64.h" |
10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
(...skipping 3024 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3035 StackArgumentsAccessor args(arguments, length, | 3035 StackArgumentsAccessor args(arguments, length, |
3036 ARGUMENTS_DONT_CONTAIN_RECEIVER); | 3036 ARGUMENTS_DONT_CONTAIN_RECEIVER); |
3037 __ movp(result, args.GetArgumentOperand(0)); | 3037 __ movp(result, args.GetArgumentOperand(0)); |
3038 } | 3038 } |
3039 } | 3039 } |
3040 | 3040 |
3041 | 3041 |
3042 void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) { | 3042 void LCodeGen::DoLoadKeyedExternalArray(LLoadKeyed* instr) { |
3043 ElementsKind elements_kind = instr->elements_kind(); | 3043 ElementsKind elements_kind = instr->elements_kind(); |
3044 LOperand* key = instr->key(); | 3044 LOperand* key = instr->key(); |
| 3045 if (kPointerSize == kInt32Size && !key->IsConstantOperand()) { |
| 3046 Register key_reg = ToRegister(key); |
| 3047 Representation key_representation = |
| 3048 instr->hydrogen()->key()->representation(); |
| 3049 if (ExternalArrayOpRequiresTemp(key_representation, elements_kind)) { |
| 3050 __ SmiToInteger64(key_reg, key_reg); |
| 3051 } else if (instr->hydrogen()->IsDehoisted()) { |
| 3052 // Sign extend key because it could be a 32 bit negative value |
| 3053 // and the dehoisted address computation happens in 64 bits |
| 3054 __ movsxlq(key_reg, key_reg); |
| 3055 } |
| 3056 } |
3045 Operand operand(BuildFastArrayOperand( | 3057 Operand operand(BuildFastArrayOperand( |
3046 instr->elements(), | 3058 instr->elements(), |
3047 key, | 3059 key, |
| 3060 instr->hydrogen()->key()->representation(), |
3048 elements_kind, | 3061 elements_kind, |
3049 instr->base_offset())); | 3062 instr->base_offset())); |
3050 | 3063 |
3051 if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS || | 3064 if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS || |
3052 elements_kind == FLOAT32_ELEMENTS) { | 3065 elements_kind == FLOAT32_ELEMENTS) { |
3053 XMMRegister result(ToDoubleRegister(instr->result())); | 3066 XMMRegister result(ToDoubleRegister(instr->result())); |
3054 __ movss(result, operand); | 3067 __ movss(result, operand); |
3055 __ cvtss2sd(result, result); | 3068 __ cvtss2sd(result, result); |
3056 } else if (elements_kind == EXTERNAL_FLOAT64_ELEMENTS || | 3069 } else if (elements_kind == EXTERNAL_FLOAT64_ELEMENTS || |
3057 elements_kind == FLOAT64_ELEMENTS) { | 3070 elements_kind == FLOAT64_ELEMENTS) { |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3104 UNREACHABLE(); | 3117 UNREACHABLE(); |
3105 break; | 3118 break; |
3106 } | 3119 } |
3107 } | 3120 } |
3108 } | 3121 } |
3109 | 3122 |
3110 | 3123 |
3111 void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) { | 3124 void LCodeGen::DoLoadKeyedFixedDoubleArray(LLoadKeyed* instr) { |
3112 XMMRegister result(ToDoubleRegister(instr->result())); | 3125 XMMRegister result(ToDoubleRegister(instr->result())); |
3113 LOperand* key = instr->key(); | 3126 LOperand* key = instr->key(); |
| 3127 if (kPointerSize == kInt32Size && !key->IsConstantOperand() && |
| 3128 instr->hydrogen()->IsDehoisted()) { |
| 3129 // Sign extend key because it could be a 32 bit negative value |
| 3130 // and the dehoisted address computation happens in 64 bits |
| 3131 __ movsxlq(ToRegister(key), ToRegister(key)); |
| 3132 } |
3114 if (instr->hydrogen()->RequiresHoleCheck()) { | 3133 if (instr->hydrogen()->RequiresHoleCheck()) { |
3115 Operand hole_check_operand = BuildFastArrayOperand( | 3134 Operand hole_check_operand = BuildFastArrayOperand( |
3116 instr->elements(), | 3135 instr->elements(), |
3117 key, | 3136 key, |
| 3137 instr->hydrogen()->key()->representation(), |
3118 FAST_DOUBLE_ELEMENTS, | 3138 FAST_DOUBLE_ELEMENTS, |
3119 instr->base_offset() + sizeof(kHoleNanLower32)); | 3139 instr->base_offset() + sizeof(kHoleNanLower32)); |
3120 __ cmpl(hole_check_operand, Immediate(kHoleNanUpper32)); | 3140 __ cmpl(hole_check_operand, Immediate(kHoleNanUpper32)); |
3121 DeoptimizeIf(equal, instr->environment()); | 3141 DeoptimizeIf(equal, instr->environment()); |
3122 } | 3142 } |
3123 | 3143 |
3124 Operand double_load_operand = BuildFastArrayOperand( | 3144 Operand double_load_operand = BuildFastArrayOperand( |
3125 instr->elements(), | 3145 instr->elements(), |
3126 key, | 3146 key, |
| 3147 instr->hydrogen()->key()->representation(), |
3127 FAST_DOUBLE_ELEMENTS, | 3148 FAST_DOUBLE_ELEMENTS, |
3128 instr->base_offset()); | 3149 instr->base_offset()); |
3129 __ movsd(result, double_load_operand); | 3150 __ movsd(result, double_load_operand); |
3130 } | 3151 } |
3131 | 3152 |
3132 | 3153 |
3133 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { | 3154 void LCodeGen::DoLoadKeyedFixedArray(LLoadKeyed* instr) { |
3134 HLoadKeyed* hinstr = instr->hydrogen(); | 3155 HLoadKeyed* hinstr = instr->hydrogen(); |
3135 Register result = ToRegister(instr->result()); | 3156 Register result = ToRegister(instr->result()); |
3136 LOperand* key = instr->key(); | 3157 LOperand* key = instr->key(); |
3137 bool requires_hole_check = hinstr->RequiresHoleCheck(); | 3158 bool requires_hole_check = hinstr->RequiresHoleCheck(); |
3138 Representation representation = hinstr->representation(); | 3159 Representation representation = hinstr->representation(); |
3139 int offset = instr->base_offset(); | 3160 int offset = instr->base_offset(); |
3140 | 3161 |
| 3162 if (kPointerSize == kInt32Size && !key->IsConstantOperand() && |
| 3163 instr->hydrogen()->IsDehoisted()) { |
| 3164 // Sign extend key because it could be a 32 bit negative value |
| 3165 // and the dehoisted address computation happens in 64 bits |
| 3166 __ movsxlq(ToRegister(key), ToRegister(key)); |
| 3167 } |
3141 if (representation.IsInteger32() && SmiValuesAre32Bits() && | 3168 if (representation.IsInteger32() && SmiValuesAre32Bits() && |
3142 hinstr->elements_kind() == FAST_SMI_ELEMENTS) { | 3169 hinstr->elements_kind() == FAST_SMI_ELEMENTS) { |
3143 ASSERT(!requires_hole_check); | 3170 ASSERT(!requires_hole_check); |
3144 if (FLAG_debug_code) { | 3171 if (FLAG_debug_code) { |
3145 Register scratch = kScratchRegister; | 3172 Register scratch = kScratchRegister; |
3146 __ Load(scratch, | 3173 __ Load(scratch, |
3147 BuildFastArrayOperand(instr->elements(), | 3174 BuildFastArrayOperand(instr->elements(), |
3148 key, | 3175 key, |
| 3176 instr->hydrogen()->key()->representation(), |
3149 FAST_ELEMENTS, | 3177 FAST_ELEMENTS, |
3150 offset), | 3178 offset), |
3151 Representation::Smi()); | 3179 Representation::Smi()); |
3152 __ AssertSmi(scratch); | 3180 __ AssertSmi(scratch); |
3153 } | 3181 } |
3154 // Read int value directly from upper half of the smi. | 3182 // Read int value directly from upper half of the smi. |
3155 STATIC_ASSERT(kSmiTag == 0); | 3183 STATIC_ASSERT(kSmiTag == 0); |
3156 ASSERT(kSmiTagSize + kSmiShiftSize == 32); | 3184 ASSERT(kSmiTagSize + kSmiShiftSize == 32); |
3157 offset += kPointerSize / 2; | 3185 offset += kPointerSize / 2; |
3158 } | 3186 } |
3159 | 3187 |
3160 __ Load(result, | 3188 __ Load(result, |
3161 BuildFastArrayOperand(instr->elements(), | 3189 BuildFastArrayOperand(instr->elements(), |
3162 key, | 3190 key, |
| 3191 instr->hydrogen()->key()->representation(), |
3163 FAST_ELEMENTS, | 3192 FAST_ELEMENTS, |
3164 offset), | 3193 offset), |
3165 representation); | 3194 representation); |
3166 | 3195 |
3167 // Check for the hole value. | 3196 // Check for the hole value. |
3168 if (requires_hole_check) { | 3197 if (requires_hole_check) { |
3169 if (IsFastSmiElementsKind(hinstr->elements_kind())) { | 3198 if (IsFastSmiElementsKind(hinstr->elements_kind())) { |
3170 Condition smi = __ CheckSmi(result); | 3199 Condition smi = __ CheckSmi(result); |
3171 DeoptimizeIf(NegateCondition(smi), instr->environment()); | 3200 DeoptimizeIf(NegateCondition(smi), instr->environment()); |
3172 } else { | 3201 } else { |
(...skipping 11 matching lines...) Expand all Loading... |
3184 DoLoadKeyedFixedDoubleArray(instr); | 3213 DoLoadKeyedFixedDoubleArray(instr); |
3185 } else { | 3214 } else { |
3186 DoLoadKeyedFixedArray(instr); | 3215 DoLoadKeyedFixedArray(instr); |
3187 } | 3216 } |
3188 } | 3217 } |
3189 | 3218 |
3190 | 3219 |
3191 Operand LCodeGen::BuildFastArrayOperand( | 3220 Operand LCodeGen::BuildFastArrayOperand( |
3192 LOperand* elements_pointer, | 3221 LOperand* elements_pointer, |
3193 LOperand* key, | 3222 LOperand* key, |
| 3223 Representation key_representation, |
3194 ElementsKind elements_kind, | 3224 ElementsKind elements_kind, |
3195 uint32_t offset) { | 3225 uint32_t offset) { |
3196 Register elements_pointer_reg = ToRegister(elements_pointer); | 3226 Register elements_pointer_reg = ToRegister(elements_pointer); |
3197 int shift_size = ElementsKindToShiftSize(elements_kind); | 3227 int shift_size = ElementsKindToShiftSize(elements_kind); |
3198 if (key->IsConstantOperand()) { | 3228 if (key->IsConstantOperand()) { |
3199 int32_t constant_value = ToInteger32(LConstantOperand::cast(key)); | 3229 int32_t constant_value = ToInteger32(LConstantOperand::cast(key)); |
3200 if (constant_value & 0xF0000000) { | 3230 if (constant_value & 0xF0000000) { |
3201 Abort(kArrayIndexConstantValueTooBig); | 3231 Abort(kArrayIndexConstantValueTooBig); |
3202 } | 3232 } |
3203 return Operand(elements_pointer_reg, | 3233 return Operand(elements_pointer_reg, |
3204 (constant_value << shift_size) + offset); | 3234 (constant_value << shift_size) + offset); |
3205 } else { | 3235 } else { |
| 3236 // Take the tag bit into account while computing the shift size. |
| 3237 if (key_representation.IsSmi() && (shift_size >= 1)) { |
| 3238 ASSERT(SmiValuesAre31Bits()); |
| 3239 shift_size -= kSmiTagSize; |
| 3240 } |
3206 ScaleFactor scale_factor = static_cast<ScaleFactor>(shift_size); | 3241 ScaleFactor scale_factor = static_cast<ScaleFactor>(shift_size); |
3207 return Operand(elements_pointer_reg, | 3242 return Operand(elements_pointer_reg, |
3208 ToRegister(key), | 3243 ToRegister(key), |
3209 scale_factor, | 3244 scale_factor, |
3210 offset); | 3245 offset); |
3211 } | 3246 } |
3212 } | 3247 } |
3213 | 3248 |
3214 | 3249 |
3215 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { | 3250 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { |
(...skipping 953 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4169 __ bind(&done); | 4204 __ bind(&done); |
4170 } else { | 4205 } else { |
4171 DeoptimizeIf(cc, instr->environment()); | 4206 DeoptimizeIf(cc, instr->environment()); |
4172 } | 4207 } |
4173 } | 4208 } |
4174 | 4209 |
4175 | 4210 |
4176 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) { | 4211 void LCodeGen::DoStoreKeyedExternalArray(LStoreKeyed* instr) { |
4177 ElementsKind elements_kind = instr->elements_kind(); | 4212 ElementsKind elements_kind = instr->elements_kind(); |
4178 LOperand* key = instr->key(); | 4213 LOperand* key = instr->key(); |
| 4214 if (kPointerSize == kInt32Size && !key->IsConstantOperand()) { |
| 4215 Register key_reg = ToRegister(key); |
| 4216 Representation key_representation = |
| 4217 instr->hydrogen()->key()->representation(); |
| 4218 if (ExternalArrayOpRequiresTemp(key_representation, elements_kind)) { |
| 4219 __ SmiToInteger64(key_reg, key_reg); |
| 4220 } else if (instr->hydrogen()->IsDehoisted()) { |
| 4221 // Sign extend key because it could be a 32 bit negative value |
| 4222 // and the dehoisted address computation happens in 64 bits |
| 4223 __ movsxlq(key_reg, key_reg); |
| 4224 } |
| 4225 } |
4179 Operand operand(BuildFastArrayOperand( | 4226 Operand operand(BuildFastArrayOperand( |
4180 instr->elements(), | 4227 instr->elements(), |
4181 key, | 4228 key, |
| 4229 instr->hydrogen()->key()->representation(), |
4182 elements_kind, | 4230 elements_kind, |
4183 instr->base_offset())); | 4231 instr->base_offset())); |
4184 | 4232 |
4185 if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS || | 4233 if (elements_kind == EXTERNAL_FLOAT32_ELEMENTS || |
4186 elements_kind == FLOAT32_ELEMENTS) { | 4234 elements_kind == FLOAT32_ELEMENTS) { |
4187 XMMRegister value(ToDoubleRegister(instr->value())); | 4235 XMMRegister value(ToDoubleRegister(instr->value())); |
4188 __ cvtsd2ss(value, value); | 4236 __ cvtsd2ss(value, value); |
4189 __ movss(operand, value); | 4237 __ movss(operand, value); |
4190 } else if (elements_kind == EXTERNAL_FLOAT64_ELEMENTS || | 4238 } else if (elements_kind == EXTERNAL_FLOAT64_ELEMENTS || |
4191 elements_kind == FLOAT64_ELEMENTS) { | 4239 elements_kind == FLOAT64_ELEMENTS) { |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4228 UNREACHABLE(); | 4276 UNREACHABLE(); |
4229 break; | 4277 break; |
4230 } | 4278 } |
4231 } | 4279 } |
4232 } | 4280 } |
4233 | 4281 |
4234 | 4282 |
4235 void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) { | 4283 void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) { |
4236 XMMRegister value = ToDoubleRegister(instr->value()); | 4284 XMMRegister value = ToDoubleRegister(instr->value()); |
4237 LOperand* key = instr->key(); | 4285 LOperand* key = instr->key(); |
| 4286 if (kPointerSize == kInt32Size && !key->IsConstantOperand() && |
| 4287 instr->hydrogen()->IsDehoisted()) { |
| 4288 // Sign extend key because it could be a 32 bit negative value |
| 4289 // and the dehoisted address computation happens in 64 bits |
| 4290 __ movsxlq(ToRegister(key), ToRegister(key)); |
| 4291 } |
4238 if (instr->NeedsCanonicalization()) { | 4292 if (instr->NeedsCanonicalization()) { |
4239 Label have_value; | 4293 Label have_value; |
4240 | 4294 |
4241 __ ucomisd(value, value); | 4295 __ ucomisd(value, value); |
4242 __ j(parity_odd, &have_value, Label::kNear); // NaN. | 4296 __ j(parity_odd, &have_value, Label::kNear); // NaN. |
4243 | 4297 |
4244 __ Set(kScratchRegister, BitCast<uint64_t>( | 4298 __ Set(kScratchRegister, BitCast<uint64_t>( |
4245 FixedDoubleArray::canonical_not_the_hole_nan_as_double())); | 4299 FixedDoubleArray::canonical_not_the_hole_nan_as_double())); |
4246 __ movq(value, kScratchRegister); | 4300 __ movq(value, kScratchRegister); |
4247 | 4301 |
4248 __ bind(&have_value); | 4302 __ bind(&have_value); |
4249 } | 4303 } |
4250 | 4304 |
4251 Operand double_store_operand = BuildFastArrayOperand( | 4305 Operand double_store_operand = BuildFastArrayOperand( |
4252 instr->elements(), | 4306 instr->elements(), |
4253 key, | 4307 key, |
| 4308 instr->hydrogen()->key()->representation(), |
4254 FAST_DOUBLE_ELEMENTS, | 4309 FAST_DOUBLE_ELEMENTS, |
4255 instr->base_offset()); | 4310 instr->base_offset()); |
4256 | 4311 |
4257 __ movsd(double_store_operand, value); | 4312 __ movsd(double_store_operand, value); |
4258 } | 4313 } |
4259 | 4314 |
4260 | 4315 |
4261 void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) { | 4316 void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) { |
4262 HStoreKeyed* hinstr = instr->hydrogen(); | 4317 HStoreKeyed* hinstr = instr->hydrogen(); |
4263 LOperand* key = instr->key(); | 4318 LOperand* key = instr->key(); |
4264 int offset = instr->base_offset(); | 4319 int offset = instr->base_offset(); |
4265 Representation representation = hinstr->value()->representation(); | 4320 Representation representation = hinstr->value()->representation(); |
4266 | 4321 |
| 4322 if (kPointerSize == kInt32Size && !key->IsConstantOperand() && |
| 4323 instr->hydrogen()->IsDehoisted()) { |
| 4324 // Sign extend key because it could be a 32 bit negative value |
| 4325 // and the dehoisted address computation happens in 64 bits |
| 4326 __ movsxlq(ToRegister(key), ToRegister(key)); |
| 4327 } |
4267 if (representation.IsInteger32() && SmiValuesAre32Bits()) { | 4328 if (representation.IsInteger32() && SmiValuesAre32Bits()) { |
4268 ASSERT(hinstr->store_mode() == STORE_TO_INITIALIZED_ENTRY); | 4329 ASSERT(hinstr->store_mode() == STORE_TO_INITIALIZED_ENTRY); |
4269 ASSERT(hinstr->elements_kind() == FAST_SMI_ELEMENTS); | 4330 ASSERT(hinstr->elements_kind() == FAST_SMI_ELEMENTS); |
4270 if (FLAG_debug_code) { | 4331 if (FLAG_debug_code) { |
4271 Register scratch = kScratchRegister; | 4332 Register scratch = kScratchRegister; |
4272 __ Load(scratch, | 4333 __ Load(scratch, |
4273 BuildFastArrayOperand(instr->elements(), | 4334 BuildFastArrayOperand(instr->elements(), |
4274 key, | 4335 key, |
| 4336 instr->hydrogen()->key()->representation(), |
4275 FAST_ELEMENTS, | 4337 FAST_ELEMENTS, |
4276 offset), | 4338 offset), |
4277 Representation::Smi()); | 4339 Representation::Smi()); |
4278 __ AssertSmi(scratch); | 4340 __ AssertSmi(scratch); |
4279 } | 4341 } |
4280 // Store int value directly to upper half of the smi. | 4342 // Store int value directly to upper half of the smi. |
4281 STATIC_ASSERT(kSmiTag == 0); | 4343 STATIC_ASSERT(kSmiTag == 0); |
4282 ASSERT(kSmiTagSize + kSmiShiftSize == 32); | 4344 ASSERT(kSmiTagSize + kSmiShiftSize == 32); |
4283 offset += kPointerSize / 2; | 4345 offset += kPointerSize / 2; |
4284 } | 4346 } |
4285 | 4347 |
4286 Operand operand = | 4348 Operand operand = |
4287 BuildFastArrayOperand(instr->elements(), | 4349 BuildFastArrayOperand(instr->elements(), |
4288 key, | 4350 key, |
| 4351 instr->hydrogen()->key()->representation(), |
4289 FAST_ELEMENTS, | 4352 FAST_ELEMENTS, |
4290 offset); | 4353 offset); |
4291 if (instr->value()->IsRegister()) { | 4354 if (instr->value()->IsRegister()) { |
4292 __ Store(operand, ToRegister(instr->value()), representation); | 4355 __ Store(operand, ToRegister(instr->value()), representation); |
4293 } else { | 4356 } else { |
4294 LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); | 4357 LConstantOperand* operand_value = LConstantOperand::cast(instr->value()); |
4295 if (IsInteger32Constant(operand_value)) { | 4358 if (IsInteger32Constant(operand_value)) { |
4296 int32_t value = ToInteger32(operand_value); | 4359 int32_t value = ToInteger32(operand_value); |
4297 if (representation.IsSmi()) { | 4360 if (representation.IsSmi()) { |
4298 __ Move(operand, Smi::FromInt(value)); | 4361 __ Move(operand, Smi::FromInt(value)); |
(...skipping 1444 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5743 CallRuntime(Runtime::kHiddenPushBlockContext, 2, instr); | 5806 CallRuntime(Runtime::kHiddenPushBlockContext, 2, instr); |
5744 RecordSafepoint(Safepoint::kNoLazyDeopt); | 5807 RecordSafepoint(Safepoint::kNoLazyDeopt); |
5745 } | 5808 } |
5746 | 5809 |
5747 | 5810 |
5748 #undef __ | 5811 #undef __ |
5749 | 5812 |
5750 } } // namespace v8::internal | 5813 } } // namespace v8::internal |
5751 | 5814 |
5752 #endif // V8_TARGET_ARCH_X64 | 5815 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |