Chromium Code Reviews| 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 |