OLD | NEW |
---|---|
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
175 void ElementsTransitionGenerator::GenerateSmiOnlyToDouble( | 175 void ElementsTransitionGenerator::GenerateSmiOnlyToDouble( |
176 MacroAssembler* masm, Label* fail) { | 176 MacroAssembler* masm, Label* fail) { |
177 // ----------- S t a t e ------------- | 177 // ----------- S t a t e ------------- |
178 // -- rax : value | 178 // -- rax : value |
179 // -- rbx : target map | 179 // -- rbx : target map |
180 // -- rcx : key | 180 // -- rcx : key |
181 // -- rdx : receiver | 181 // -- rdx : receiver |
182 // -- rsp[0] : return address | 182 // -- rsp[0] : return address |
183 // ----------------------------------- | 183 // ----------------------------------- |
184 // The fail label is not actually used since we do not allocate. | 184 // The fail label is not actually used since we do not allocate. |
185 Label allocated, cow_array; | |
186 | |
187 // Check backing store for COW-ness. If the negative case, we do not have to | |
188 // allocate a new array, since FixedArray and FixedDoubleArray do not differ | |
189 // in size. | |
190 __ movq(r8, FieldOperand(rdx, JSObject::kElementsOffset)); | |
191 __ SmiToInteger32(r9, FieldOperand(r8, FixedDoubleArray::kLengthOffset)); | |
192 __ CompareRoot(FieldOperand(r8, HeapObject::kMapOffset), | |
193 Heap::kFixedCOWArrayMapRootIndex); | |
194 __ j(equal, &cow_array); | |
195 __ movq(r14, r8); // Destination array equals source array. | |
196 | |
197 __ bind(&allocated); | |
198 // r8 : source FixedArray | |
199 // r9 : elements array length | |
200 // r14: destination FixedDoubleArray | |
201 // Set backing store's map | |
202 __ LoadRoot(rdi, Heap::kFixedDoubleArrayMapRootIndex); | |
203 __ movq(FieldOperand(r14, HeapObject::kMapOffset), rdi); | |
185 | 204 |
186 // Set transitioned map. | 205 // Set transitioned map. |
187 __ movq(FieldOperand(rdx, HeapObject::kMapOffset), rbx); | 206 __ movq(FieldOperand(rdx, HeapObject::kMapOffset), rbx); |
188 __ RecordWriteField(rdx, | 207 __ RecordWriteField(rdx, |
189 HeapObject::kMapOffset, | 208 HeapObject::kMapOffset, |
190 rbx, | 209 rbx, |
191 rdi, | 210 rdi, |
192 kDontSaveFPRegs, | 211 kDontSaveFPRegs, |
193 EMIT_REMEMBERED_SET, | 212 EMIT_REMEMBERED_SET, |
194 OMIT_SMI_CHECK); | 213 OMIT_SMI_CHECK); |
195 // Set backing store's map | |
196 __ movq(r8, FieldOperand(rdx, JSObject::kElementsOffset)); | |
197 __ LoadRoot(rdi, Heap::kFixedDoubleArrayMapRootIndex); | |
198 __ movq(FieldOperand(r8, HeapObject::kMapOffset), rdi); | |
199 | 214 |
200 // Convert smis to doubles and holes to hole NaNs. Since FixedArray and | 215 // Convert smis to doubles and holes to hole NaNs. In the non-COW case the |
201 // FixedDoubleArray do not differ in size, we do not allocate a new array. | 216 // length does not have to be set since we still use the exact same field |
danno
2011/10/24 15:01:47
Or even simpler:
NaNs. The Array's length remains
| |
217 // for length. | |
202 STATIC_ASSERT(FixedDoubleArray::kLengthOffset == FixedArray::kLengthOffset); | 218 STATIC_ASSERT(FixedDoubleArray::kLengthOffset == FixedArray::kLengthOffset); |
203 STATIC_ASSERT(FixedDoubleArray::kHeaderSize == FixedArray::kHeaderSize); | 219 STATIC_ASSERT(FixedDoubleArray::kHeaderSize == FixedArray::kHeaderSize); |
204 __ SmiToInteger32(r9, FieldOperand(r8, FixedDoubleArray::kLengthOffset)); | 220 |
205 // r8 : elements array | |
206 // r9 : elements array length | |
207 Label loop, entry, convert_hole; | 221 Label loop, entry, convert_hole; |
208 __ movq(r15, BitCast<int64_t, uint64_t>(kHoleNanInt64), RelocInfo::NONE); | 222 __ movq(r15, BitCast<int64_t, uint64_t>(kHoleNanInt64), RelocInfo::NONE); |
209 // r15: the-hole NaN | 223 // r15: the-hole NaN |
210 __ jmp(&entry); | 224 __ jmp(&entry); |
225 | |
226 // Allocate new array if the source array is a COW array. | |
227 __ bind(&cow_array); | |
228 __ lea(rdi, Operand(r9, times_pointer_size, FixedArray::kHeaderSize)); | |
229 __ AllocateInNewSpace(rdi, r14, r11, r15, fail, TAG_OBJECT); | |
230 // Set receiver's backing store. | |
231 __ movq(FieldOperand(rdx, JSObject::kElementsOffset), r14); | |
232 __ movq(r11, r14); | |
233 __ RecordWriteField(rdx, | |
234 JSObject::kElementsOffset, | |
235 r11, | |
236 r15, | |
237 kDontSaveFPRegs, | |
238 EMIT_REMEMBERED_SET, | |
239 OMIT_SMI_CHECK); | |
240 // Set backing store's length. | |
241 __ Integer32ToSmi(r11, r9); | |
242 __ movq(FieldOperand(r14, FixedDoubleArray::kLengthOffset), r11); | |
243 __ jmp(&allocated); | |
244 | |
245 // Conversion loop. | |
211 __ bind(&loop); | 246 __ bind(&loop); |
212 __ decq(r9); | 247 __ decq(r9); |
213 __ movq(rbx, | 248 __ movq(rbx, |
214 FieldOperand(r8, r9, times_8, FixedArray::kHeaderSize)); | 249 FieldOperand(r8, r9, times_8, FixedArray::kHeaderSize)); |
215 // r9 : current element's index | 250 // r9 : current element's index |
216 // rbx: current element (smi-tagged) | 251 // rbx: current element (smi-tagged) |
217 __ JumpIfNotSmi(rbx, &convert_hole); | 252 __ JumpIfNotSmi(rbx, &convert_hole); |
218 __ SmiToInteger32(rbx, rbx); | 253 __ SmiToInteger32(rbx, rbx); |
219 __ cvtlsi2sd(xmm0, rbx); | 254 __ cvtlsi2sd(xmm0, rbx); |
220 __ movsd(FieldOperand(r8, r9, times_8, FixedDoubleArray::kHeaderSize), | 255 __ movsd(FieldOperand(r14, r9, times_8, FixedDoubleArray::kHeaderSize), |
221 xmm0); | 256 xmm0); |
222 __ jmp(&entry); | 257 __ jmp(&entry); |
223 __ bind(&convert_hole); | 258 __ bind(&convert_hole); |
224 __ movq(FieldOperand(r8, r9, times_8, FixedDoubleArray::kHeaderSize), r15); | 259 __ movq(FieldOperand(r14, r9, times_8, FixedDoubleArray::kHeaderSize), r15); |
225 __ bind(&entry); | 260 __ bind(&entry); |
226 __ testq(r9, r9); | 261 __ testq(r9, r9); |
227 __ j(not_zero, &loop); | 262 __ j(not_zero, &loop); |
228 } | 263 } |
229 | 264 |
230 | 265 |
231 void ElementsTransitionGenerator::GenerateDoubleToObject( | 266 void ElementsTransitionGenerator::GenerateDoubleToObject( |
232 MacroAssembler* masm, Label* fail) { | 267 MacroAssembler* masm, Label* fail) { |
233 // ----------- S t a t e ------------- | 268 // ----------- S t a t e ------------- |
234 // -- rax : value | 269 // -- rax : value |
235 // -- rbx : target map | 270 // -- rbx : target map |
236 // -- rcx : key | 271 // -- rcx : key |
237 // -- rdx : receiver | 272 // -- rdx : receiver |
238 // -- rsp[0] : return address | 273 // -- rsp[0] : return address |
239 // ----------------------------------- | 274 // ----------------------------------- |
240 Label loop, entry, convert_hole, gc_required; | 275 Label loop, entry, convert_hole, gc_required; |
241 __ push(rax); | 276 __ push(rax); |
242 | 277 |
243 __ movq(r8, FieldOperand(rdx, JSObject::kElementsOffset)); | 278 __ movq(r8, FieldOperand(rdx, JSObject::kElementsOffset)); |
244 __ SmiToInteger32(r9, FieldOperand(r8, FixedDoubleArray::kLengthOffset)); | 279 __ SmiToInteger32(r9, FieldOperand(r8, FixedDoubleArray::kLengthOffset)); |
245 // r8 : source FixedDoubleArray | 280 // r8 : source FixedDoubleArray |
246 // r9 : number of elements | 281 // r9 : number of elements |
247 __ lea(rdi, Operand(r9, times_pointer_size, FixedArray::kHeaderSize)); | 282 __ lea(rdi, Operand(r9, times_pointer_size, FixedArray::kHeaderSize)); |
248 __ AllocateInNewSpace(rdi, rax, r14, r15, &gc_required, TAG_OBJECT); | 283 __ AllocateInNewSpace(rdi, r11, r14, r15, &gc_required, TAG_OBJECT); |
249 // rax: destination FixedArray | 284 // r11: destination FixedArray |
250 __ LoadRoot(rdi, Heap::kFixedArrayMapRootIndex); | 285 __ LoadRoot(rdi, Heap::kFixedArrayMapRootIndex); |
251 __ movq(FieldOperand(rax, HeapObject::kMapOffset), rdi); | 286 __ movq(FieldOperand(r11, HeapObject::kMapOffset), rdi); |
252 __ Integer32ToSmi(r14, r9); | 287 __ Integer32ToSmi(r14, r9); |
253 __ movq(FieldOperand(rax, FixedArray::kLengthOffset), r14); | 288 __ movq(FieldOperand(r11, FixedArray::kLengthOffset), r14); |
254 | 289 |
255 // Prepare for conversion loop. | 290 // Prepare for conversion loop. |
256 __ movq(rsi, BitCast<int64_t, uint64_t>(kHoleNanInt64), RelocInfo::NONE); | 291 __ movq(rsi, BitCast<int64_t, uint64_t>(kHoleNanInt64), RelocInfo::NONE); |
257 __ LoadRoot(rdi, Heap::kTheHoleValueRootIndex); | 292 __ LoadRoot(rdi, Heap::kTheHoleValueRootIndex); |
258 // rsi: the-hole NaN | 293 // rsi: the-hole NaN |
259 // rdi: pointer to the-hole | 294 // rdi: pointer to the-hole |
260 __ jmp(&entry); | 295 __ jmp(&entry); |
261 | 296 |
262 // Call into runtime if GC is required. | 297 // Call into runtime if GC is required. |
263 __ bind(&gc_required); | 298 __ bind(&gc_required); |
264 __ pop(rax); | 299 __ pop(rax); |
265 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 300 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
266 __ jmp(fail); | 301 __ jmp(fail); |
267 | 302 |
268 // Box doubles into heap numbers. | 303 // Box doubles into heap numbers. |
269 __ bind(&loop); | 304 __ bind(&loop); |
270 __ decq(r9); | 305 __ decq(r9); |
271 __ movq(r14, FieldOperand(r8, | 306 __ movq(r14, FieldOperand(r8, |
272 r9, | 307 r9, |
273 times_pointer_size, | 308 times_pointer_size, |
274 FixedDoubleArray::kHeaderSize)); | 309 FixedDoubleArray::kHeaderSize)); |
275 // r9 : current element's index | 310 // r9 : current element's index |
276 // r14: current element | 311 // r14: current element |
277 __ cmpq(r14, rsi); | 312 __ cmpq(r14, rsi); |
278 __ j(equal, &convert_hole); | 313 __ j(equal, &convert_hole); |
279 | 314 |
280 // Non-hole double, copy value into a heap number. | 315 // Non-hole double, copy value into a heap number. |
281 __ AllocateHeapNumber(r11, r15, &gc_required); | 316 __ AllocateHeapNumber(rax, r15, &gc_required); |
282 // r11: new heap number | 317 // rax: new heap number |
283 __ movq(FieldOperand(r11, HeapNumber::kValueOffset), r14); | 318 __ movq(FieldOperand(rax, HeapNumber::kValueOffset), r14); |
284 __ movq(FieldOperand(rax, | 319 __ movq(FieldOperand(r11, |
285 r9, | 320 r9, |
286 times_pointer_size, | 321 times_pointer_size, |
287 FixedArray::kHeaderSize), | 322 FixedArray::kHeaderSize), |
288 r11); | 323 rax); |
289 __ movq(r15, r9); | 324 __ movq(r15, r9); |
290 __ RecordWriteArray(rax, | 325 __ RecordWriteArray(r11, |
291 r11, | 326 rax, |
292 r15, | 327 r15, |
293 kDontSaveFPRegs, | 328 kDontSaveFPRegs, |
294 EMIT_REMEMBERED_SET, | 329 EMIT_REMEMBERED_SET, |
295 OMIT_SMI_CHECK); | 330 OMIT_SMI_CHECK); |
296 __ jmp(&entry, Label::kNear); | 331 __ jmp(&entry, Label::kNear); |
297 | 332 |
298 // Replace the-hole NaN with the-hole pointer. | 333 // Replace the-hole NaN with the-hole pointer. |
299 __ bind(&convert_hole); | 334 __ bind(&convert_hole); |
300 __ movq(FieldOperand(rax, | 335 __ movq(FieldOperand(r11, |
301 r9, | 336 r9, |
302 times_pointer_size, | 337 times_pointer_size, |
303 FixedArray::kHeaderSize), | 338 FixedArray::kHeaderSize), |
304 rdi); | 339 rdi); |
305 | 340 |
306 __ bind(&entry); | 341 __ bind(&entry); |
307 __ testq(r9, r9); | 342 __ testq(r9, r9); |
308 __ j(not_zero, &loop); | 343 __ j(not_zero, &loop); |
309 | 344 |
310 // Set transitioned map. | 345 // Set transitioned map. |
311 __ movq(FieldOperand(rdx, HeapObject::kMapOffset), rbx); | 346 __ movq(FieldOperand(rdx, HeapObject::kMapOffset), rbx); |
312 __ RecordWriteField(rdx, | 347 __ RecordWriteField(rdx, |
313 HeapObject::kMapOffset, | 348 HeapObject::kMapOffset, |
314 rbx, | 349 rbx, |
315 rdi, | 350 rdi, |
316 kDontSaveFPRegs, | 351 kDontSaveFPRegs, |
317 EMIT_REMEMBERED_SET, | 352 EMIT_REMEMBERED_SET, |
318 OMIT_SMI_CHECK); | 353 OMIT_SMI_CHECK); |
319 // Replace receiver's backing store with newly created and filled FixedArray. | 354 // Replace receiver's backing store with newly created and filled FixedArray. |
320 __ movq(FieldOperand(rdx, JSObject::kElementsOffset), rax); | 355 __ movq(FieldOperand(rdx, JSObject::kElementsOffset), r11); |
321 __ RecordWriteField(rdx, | 356 __ RecordWriteField(rdx, |
322 JSObject::kElementsOffset, | 357 JSObject::kElementsOffset, |
323 rax, | 358 r11, |
324 rdi, | 359 r15, |
325 kDontSaveFPRegs, | 360 kDontSaveFPRegs, |
326 EMIT_REMEMBERED_SET, | 361 EMIT_REMEMBERED_SET, |
327 OMIT_SMI_CHECK); | 362 OMIT_SMI_CHECK); |
328 __ pop(rax); | 363 __ pop(rax); |
329 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 364 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
330 } | 365 } |
331 | 366 |
332 #undef __ | 367 #undef __ |
333 | 368 |
334 } } // namespace v8::internal | 369 } } // namespace v8::internal |
335 | 370 |
336 #endif // V8_TARGET_ARCH_X64 | 371 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |