OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
163 | 163 |
164 Label valid_result; | 164 Label valid_result; |
165 Label return_result; | 165 Label return_result; |
166 // If Invalid Operand or Zero Division exceptions are set, | 166 // If Invalid Operand or Zero Division exceptions are set, |
167 // return NaN. | 167 // return NaN. |
168 __ testb(rax, Immediate(5)); | 168 __ testb(rax, Immediate(5)); |
169 __ j(zero, &valid_result); | 169 __ j(zero, &valid_result); |
170 __ fstp(0); // Drop result in st(0). | 170 __ fstp(0); // Drop result in st(0). |
171 int64_t kNaNValue = V8_INT64_C(0x7ff8000000000000); | 171 int64_t kNaNValue = V8_INT64_C(0x7ff8000000000000); |
172 __ movq(rcx, kNaNValue); | 172 __ movq(rcx, kNaNValue); |
173 __ movq(Operand(rsp, kPointerSize), rcx); | 173 __ movp(Operand(rsp, kPointerSize), rcx); |
174 __ movsd(xmm0, Operand(rsp, kPointerSize)); | 174 __ movsd(xmm0, Operand(rsp, kPointerSize)); |
175 __ jmp(&return_result); | 175 __ jmp(&return_result); |
176 | 176 |
177 // If result is valid, return that. | 177 // If result is valid, return that. |
178 __ bind(&valid_result); | 178 __ bind(&valid_result); |
179 __ fstp_d(Operand(rsp, kPointerSize)); | 179 __ fstp_d(Operand(rsp, kPointerSize)); |
180 __ movsd(xmm0, Operand(rsp, kPointerSize)); | 180 __ movsd(xmm0, Operand(rsp, kPointerSize)); |
181 | 181 |
182 // Clean up FPU stack and exceptions and return xmm0 | 182 // Clean up FPU stack and exceptions and return xmm0 |
183 __ bind(&return_result); | 183 __ bind(&return_result); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
216 // -- rcx : key | 216 // -- rcx : key |
217 // -- rdx : receiver | 217 // -- rdx : receiver |
218 // -- rsp[0] : return address | 218 // -- rsp[0] : return address |
219 // ----------------------------------- | 219 // ----------------------------------- |
220 if (mode == TRACK_ALLOCATION_SITE) { | 220 if (mode == TRACK_ALLOCATION_SITE) { |
221 ASSERT(allocation_memento_found != NULL); | 221 ASSERT(allocation_memento_found != NULL); |
222 __ JumpIfJSArrayHasAllocationMemento(rdx, rdi, allocation_memento_found); | 222 __ JumpIfJSArrayHasAllocationMemento(rdx, rdi, allocation_memento_found); |
223 } | 223 } |
224 | 224 |
225 // Set transitioned map. | 225 // Set transitioned map. |
226 __ movq(FieldOperand(rdx, HeapObject::kMapOffset), rbx); | 226 __ movp(FieldOperand(rdx, HeapObject::kMapOffset), rbx); |
227 __ RecordWriteField(rdx, | 227 __ RecordWriteField(rdx, |
228 HeapObject::kMapOffset, | 228 HeapObject::kMapOffset, |
229 rbx, | 229 rbx, |
230 rdi, | 230 rdi, |
231 kDontSaveFPRegs, | 231 kDontSaveFPRegs, |
232 EMIT_REMEMBERED_SET, | 232 EMIT_REMEMBERED_SET, |
233 OMIT_SMI_CHECK); | 233 OMIT_SMI_CHECK); |
234 } | 234 } |
235 | 235 |
236 | 236 |
237 void ElementsTransitionGenerator::GenerateSmiToDouble( | 237 void ElementsTransitionGenerator::GenerateSmiToDouble( |
238 MacroAssembler* masm, AllocationSiteMode mode, Label* fail) { | 238 MacroAssembler* masm, AllocationSiteMode mode, Label* fail) { |
239 // ----------- S t a t e ------------- | 239 // ----------- S t a t e ------------- |
240 // -- rax : value | 240 // -- rax : value |
241 // -- rbx : target map | 241 // -- rbx : target map |
242 // -- rcx : key | 242 // -- rcx : key |
243 // -- rdx : receiver | 243 // -- rdx : receiver |
244 // -- rsp[0] : return address | 244 // -- rsp[0] : return address |
245 // ----------------------------------- | 245 // ----------------------------------- |
246 // The fail label is not actually used since we do not allocate. | 246 // The fail label is not actually used since we do not allocate. |
247 Label allocated, new_backing_store, only_change_map, done; | 247 Label allocated, new_backing_store, only_change_map, done; |
248 | 248 |
249 if (mode == TRACK_ALLOCATION_SITE) { | 249 if (mode == TRACK_ALLOCATION_SITE) { |
250 __ JumpIfJSArrayHasAllocationMemento(rdx, rdi, fail); | 250 __ JumpIfJSArrayHasAllocationMemento(rdx, rdi, fail); |
251 } | 251 } |
252 | 252 |
253 // Check for empty arrays, which only require a map transition and no changes | 253 // Check for empty arrays, which only require a map transition and no changes |
254 // to the backing store. | 254 // to the backing store. |
255 __ movq(r8, FieldOperand(rdx, JSObject::kElementsOffset)); | 255 __ movp(r8, FieldOperand(rdx, JSObject::kElementsOffset)); |
256 __ CompareRoot(r8, Heap::kEmptyFixedArrayRootIndex); | 256 __ CompareRoot(r8, Heap::kEmptyFixedArrayRootIndex); |
257 __ j(equal, &only_change_map); | 257 __ j(equal, &only_change_map); |
258 | 258 |
259 // Check backing store for COW-ness. For COW arrays we have to | 259 // Check backing store for COW-ness. For COW arrays we have to |
260 // allocate a new backing store. | 260 // allocate a new backing store. |
261 __ SmiToInteger32(r9, FieldOperand(r8, FixedDoubleArray::kLengthOffset)); | 261 __ SmiToInteger32(r9, FieldOperand(r8, FixedDoubleArray::kLengthOffset)); |
262 __ CompareRoot(FieldOperand(r8, HeapObject::kMapOffset), | 262 __ CompareRoot(FieldOperand(r8, HeapObject::kMapOffset), |
263 Heap::kFixedCOWArrayMapRootIndex); | 263 Heap::kFixedCOWArrayMapRootIndex); |
264 __ j(equal, &new_backing_store); | 264 __ j(equal, &new_backing_store); |
265 // Check if the backing store is in new-space. If not, we need to allocate | 265 // Check if the backing store is in new-space. If not, we need to allocate |
266 // a new one since the old one is in pointer-space. | 266 // a new one since the old one is in pointer-space. |
267 // If in new space, we can reuse the old backing store because it is | 267 // If in new space, we can reuse the old backing store because it is |
268 // the same size. | 268 // the same size. |
269 __ JumpIfNotInNewSpace(r8, rdi, &new_backing_store); | 269 __ JumpIfNotInNewSpace(r8, rdi, &new_backing_store); |
270 | 270 |
271 __ movq(r14, r8); // Destination array equals source array. | 271 __ movp(r14, r8); // Destination array equals source array. |
272 | 272 |
273 // r8 : source FixedArray | 273 // r8 : source FixedArray |
274 // r9 : elements array length | 274 // r9 : elements array length |
275 // r14: destination FixedDoubleArray | 275 // r14: destination FixedDoubleArray |
276 // Set backing store's map | 276 // Set backing store's map |
277 __ LoadRoot(rdi, Heap::kFixedDoubleArrayMapRootIndex); | 277 __ LoadRoot(rdi, Heap::kFixedDoubleArrayMapRootIndex); |
278 __ movq(FieldOperand(r14, HeapObject::kMapOffset), rdi); | 278 __ movp(FieldOperand(r14, HeapObject::kMapOffset), rdi); |
279 | 279 |
280 __ bind(&allocated); | 280 __ bind(&allocated); |
281 // Set transitioned map. | 281 // Set transitioned map. |
282 __ movq(FieldOperand(rdx, HeapObject::kMapOffset), rbx); | 282 __ movp(FieldOperand(rdx, HeapObject::kMapOffset), rbx); |
283 __ RecordWriteField(rdx, | 283 __ RecordWriteField(rdx, |
284 HeapObject::kMapOffset, | 284 HeapObject::kMapOffset, |
285 rbx, | 285 rbx, |
286 rdi, | 286 rdi, |
287 kDontSaveFPRegs, | 287 kDontSaveFPRegs, |
288 EMIT_REMEMBERED_SET, | 288 EMIT_REMEMBERED_SET, |
289 OMIT_SMI_CHECK); | 289 OMIT_SMI_CHECK); |
290 | 290 |
291 // Convert smis to doubles and holes to hole NaNs. The Array's length | 291 // Convert smis to doubles and holes to hole NaNs. The Array's length |
292 // remains unchanged. | 292 // remains unchanged. |
293 STATIC_ASSERT(FixedDoubleArray::kLengthOffset == FixedArray::kLengthOffset); | 293 STATIC_ASSERT(FixedDoubleArray::kLengthOffset == FixedArray::kLengthOffset); |
294 STATIC_ASSERT(FixedDoubleArray::kHeaderSize == FixedArray::kHeaderSize); | 294 STATIC_ASSERT(FixedDoubleArray::kHeaderSize == FixedArray::kHeaderSize); |
295 | 295 |
296 Label loop, entry, convert_hole; | 296 Label loop, entry, convert_hole; |
297 __ movq(r15, BitCast<int64_t, uint64_t>(kHoleNanInt64)); | 297 __ movq(r15, BitCast<int64_t, uint64_t>(kHoleNanInt64)); |
298 // r15: the-hole NaN | 298 // r15: the-hole NaN |
299 __ jmp(&entry); | 299 __ jmp(&entry); |
300 | 300 |
301 // Allocate new backing store. | 301 // Allocate new backing store. |
302 __ bind(&new_backing_store); | 302 __ bind(&new_backing_store); |
303 __ lea(rdi, Operand(r9, times_8, FixedArray::kHeaderSize)); | 303 __ lea(rdi, Operand(r9, times_8, FixedArray::kHeaderSize)); |
304 __ Allocate(rdi, r14, r11, r15, fail, TAG_OBJECT); | 304 __ Allocate(rdi, r14, r11, r15, fail, TAG_OBJECT); |
305 // Set backing store's map | 305 // Set backing store's map |
306 __ LoadRoot(rdi, Heap::kFixedDoubleArrayMapRootIndex); | 306 __ LoadRoot(rdi, Heap::kFixedDoubleArrayMapRootIndex); |
307 __ movq(FieldOperand(r14, HeapObject::kMapOffset), rdi); | 307 __ movp(FieldOperand(r14, HeapObject::kMapOffset), rdi); |
308 // Set receiver's backing store. | 308 // Set receiver's backing store. |
309 __ movq(FieldOperand(rdx, JSObject::kElementsOffset), r14); | 309 __ movp(FieldOperand(rdx, JSObject::kElementsOffset), r14); |
310 __ movq(r11, r14); | 310 __ movp(r11, r14); |
311 __ RecordWriteField(rdx, | 311 __ RecordWriteField(rdx, |
312 JSObject::kElementsOffset, | 312 JSObject::kElementsOffset, |
313 r11, | 313 r11, |
314 r15, | 314 r15, |
315 kDontSaveFPRegs, | 315 kDontSaveFPRegs, |
316 EMIT_REMEMBERED_SET, | 316 EMIT_REMEMBERED_SET, |
317 OMIT_SMI_CHECK); | 317 OMIT_SMI_CHECK); |
318 // Set backing store's length. | 318 // Set backing store's length. |
319 __ Integer32ToSmi(r11, r9); | 319 __ Integer32ToSmi(r11, r9); |
320 __ movq(FieldOperand(r14, FixedDoubleArray::kLengthOffset), r11); | 320 __ movp(FieldOperand(r14, FixedDoubleArray::kLengthOffset), r11); |
321 __ jmp(&allocated); | 321 __ jmp(&allocated); |
322 | 322 |
323 __ bind(&only_change_map); | 323 __ bind(&only_change_map); |
324 // Set transitioned map. | 324 // Set transitioned map. |
325 __ movq(FieldOperand(rdx, HeapObject::kMapOffset), rbx); | 325 __ movp(FieldOperand(rdx, HeapObject::kMapOffset), rbx); |
326 __ RecordWriteField(rdx, | 326 __ RecordWriteField(rdx, |
327 HeapObject::kMapOffset, | 327 HeapObject::kMapOffset, |
328 rbx, | 328 rbx, |
329 rdi, | 329 rdi, |
330 kDontSaveFPRegs, | 330 kDontSaveFPRegs, |
331 OMIT_REMEMBERED_SET, | 331 OMIT_REMEMBERED_SET, |
332 OMIT_SMI_CHECK); | 332 OMIT_SMI_CHECK); |
333 __ jmp(&done); | 333 __ jmp(&done); |
334 | 334 |
335 // Conversion loop. | 335 // Conversion loop. |
336 __ bind(&loop); | 336 __ bind(&loop); |
337 __ movq(rbx, | 337 __ movp(rbx, |
338 FieldOperand(r8, r9, times_pointer_size, FixedArray::kHeaderSize)); | 338 FieldOperand(r8, r9, times_pointer_size, FixedArray::kHeaderSize)); |
339 // r9 : current element's index | 339 // r9 : current element's index |
340 // rbx: current element (smi-tagged) | 340 // rbx: current element (smi-tagged) |
341 __ JumpIfNotSmi(rbx, &convert_hole); | 341 __ JumpIfNotSmi(rbx, &convert_hole); |
342 __ SmiToInteger32(rbx, rbx); | 342 __ SmiToInteger32(rbx, rbx); |
343 __ Cvtlsi2sd(xmm0, rbx); | 343 __ Cvtlsi2sd(xmm0, rbx); |
344 __ movsd(FieldOperand(r14, r9, times_8, FixedDoubleArray::kHeaderSize), | 344 __ movsd(FieldOperand(r14, r9, times_8, FixedDoubleArray::kHeaderSize), |
345 xmm0); | 345 xmm0); |
346 __ jmp(&entry); | 346 __ jmp(&entry); |
347 __ bind(&convert_hole); | 347 __ bind(&convert_hole); |
(...skipping 22 matching lines...) Expand all Loading... |
370 // -- rsp[0] : return address | 370 // -- rsp[0] : return address |
371 // ----------------------------------- | 371 // ----------------------------------- |
372 Label loop, entry, convert_hole, gc_required, only_change_map; | 372 Label loop, entry, convert_hole, gc_required, only_change_map; |
373 | 373 |
374 if (mode == TRACK_ALLOCATION_SITE) { | 374 if (mode == TRACK_ALLOCATION_SITE) { |
375 __ JumpIfJSArrayHasAllocationMemento(rdx, rdi, fail); | 375 __ JumpIfJSArrayHasAllocationMemento(rdx, rdi, fail); |
376 } | 376 } |
377 | 377 |
378 // Check for empty arrays, which only require a map transition and no changes | 378 // Check for empty arrays, which only require a map transition and no changes |
379 // to the backing store. | 379 // to the backing store. |
380 __ movq(r8, FieldOperand(rdx, JSObject::kElementsOffset)); | 380 __ movp(r8, FieldOperand(rdx, JSObject::kElementsOffset)); |
381 __ CompareRoot(r8, Heap::kEmptyFixedArrayRootIndex); | 381 __ CompareRoot(r8, Heap::kEmptyFixedArrayRootIndex); |
382 __ j(equal, &only_change_map); | 382 __ j(equal, &only_change_map); |
383 | 383 |
384 __ push(rax); | 384 __ push(rax); |
385 | 385 |
386 __ movq(r8, FieldOperand(rdx, JSObject::kElementsOffset)); | 386 __ movp(r8, FieldOperand(rdx, JSObject::kElementsOffset)); |
387 __ SmiToInteger32(r9, FieldOperand(r8, FixedDoubleArray::kLengthOffset)); | 387 __ SmiToInteger32(r9, FieldOperand(r8, FixedDoubleArray::kLengthOffset)); |
388 // r8 : source FixedDoubleArray | 388 // r8 : source FixedDoubleArray |
389 // r9 : number of elements | 389 // r9 : number of elements |
390 __ lea(rdi, Operand(r9, times_pointer_size, FixedArray::kHeaderSize)); | 390 __ lea(rdi, Operand(r9, times_pointer_size, FixedArray::kHeaderSize)); |
391 __ Allocate(rdi, r11, r14, r15, &gc_required, TAG_OBJECT); | 391 __ Allocate(rdi, r11, r14, r15, &gc_required, TAG_OBJECT); |
392 // r11: destination FixedArray | 392 // r11: destination FixedArray |
393 __ LoadRoot(rdi, Heap::kFixedArrayMapRootIndex); | 393 __ LoadRoot(rdi, Heap::kFixedArrayMapRootIndex); |
394 __ movq(FieldOperand(r11, HeapObject::kMapOffset), rdi); | 394 __ movp(FieldOperand(r11, HeapObject::kMapOffset), rdi); |
395 __ Integer32ToSmi(r14, r9); | 395 __ Integer32ToSmi(r14, r9); |
396 __ movq(FieldOperand(r11, FixedArray::kLengthOffset), r14); | 396 __ movp(FieldOperand(r11, FixedArray::kLengthOffset), r14); |
397 | 397 |
398 // Prepare for conversion loop. | 398 // Prepare for conversion loop. |
399 __ movq(rsi, BitCast<int64_t, uint64_t>(kHoleNanInt64)); | 399 __ movq(rsi, BitCast<int64_t, uint64_t>(kHoleNanInt64)); |
400 __ LoadRoot(rdi, Heap::kTheHoleValueRootIndex); | 400 __ LoadRoot(rdi, Heap::kTheHoleValueRootIndex); |
401 // rsi: the-hole NaN | 401 // rsi: the-hole NaN |
402 // rdi: pointer to the-hole | 402 // rdi: pointer to the-hole |
403 __ jmp(&entry); | 403 __ jmp(&entry); |
404 | 404 |
405 // Call into runtime if GC is required. | 405 // Call into runtime if GC is required. |
406 __ bind(&gc_required); | 406 __ bind(&gc_required); |
407 __ pop(rax); | 407 __ pop(rax); |
408 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 408 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
409 __ jmp(fail); | 409 __ jmp(fail); |
410 | 410 |
411 // Box doubles into heap numbers. | 411 // Box doubles into heap numbers. |
412 __ bind(&loop); | 412 __ bind(&loop); |
413 __ movq(r14, FieldOperand(r8, | 413 __ movq(r14, FieldOperand(r8, |
414 r9, | 414 r9, |
415 times_8, | 415 times_8, |
416 FixedDoubleArray::kHeaderSize)); | 416 FixedDoubleArray::kHeaderSize)); |
417 // r9 : current element's index | 417 // r9 : current element's index |
418 // r14: current element | 418 // r14: current element |
419 __ cmpq(r14, rsi); | 419 __ cmpq(r14, rsi); |
420 __ j(equal, &convert_hole); | 420 __ j(equal, &convert_hole); |
421 | 421 |
422 // Non-hole double, copy value into a heap number. | 422 // Non-hole double, copy value into a heap number. |
423 __ AllocateHeapNumber(rax, r15, &gc_required); | 423 __ AllocateHeapNumber(rax, r15, &gc_required); |
424 // rax: new heap number | 424 // rax: new heap number |
425 __ MoveDouble(FieldOperand(rax, HeapNumber::kValueOffset), r14); | 425 __ MoveDouble(FieldOperand(rax, HeapNumber::kValueOffset), r14); |
426 __ movq(FieldOperand(r11, | 426 __ movp(FieldOperand(r11, |
427 r9, | 427 r9, |
428 times_pointer_size, | 428 times_pointer_size, |
429 FixedArray::kHeaderSize), | 429 FixedArray::kHeaderSize), |
430 rax); | 430 rax); |
431 __ movq(r15, r9); | 431 __ movp(r15, r9); |
432 __ RecordWriteArray(r11, | 432 __ RecordWriteArray(r11, |
433 rax, | 433 rax, |
434 r15, | 434 r15, |
435 kDontSaveFPRegs, | 435 kDontSaveFPRegs, |
436 EMIT_REMEMBERED_SET, | 436 EMIT_REMEMBERED_SET, |
437 OMIT_SMI_CHECK); | 437 OMIT_SMI_CHECK); |
438 __ jmp(&entry, Label::kNear); | 438 __ jmp(&entry, Label::kNear); |
439 | 439 |
440 // Replace the-hole NaN with the-hole pointer. | 440 // Replace the-hole NaN with the-hole pointer. |
441 __ bind(&convert_hole); | 441 __ bind(&convert_hole); |
442 __ movq(FieldOperand(r11, | 442 __ movp(FieldOperand(r11, |
443 r9, | 443 r9, |
444 times_pointer_size, | 444 times_pointer_size, |
445 FixedArray::kHeaderSize), | 445 FixedArray::kHeaderSize), |
446 rdi); | 446 rdi); |
447 | 447 |
448 __ bind(&entry); | 448 __ bind(&entry); |
449 __ decq(r9); | 449 __ decq(r9); |
450 __ j(not_sign, &loop); | 450 __ j(not_sign, &loop); |
451 | 451 |
452 // Replace receiver's backing store with newly created and filled FixedArray. | 452 // Replace receiver's backing store with newly created and filled FixedArray. |
453 __ movq(FieldOperand(rdx, JSObject::kElementsOffset), r11); | 453 __ movp(FieldOperand(rdx, JSObject::kElementsOffset), r11); |
454 __ RecordWriteField(rdx, | 454 __ RecordWriteField(rdx, |
455 JSObject::kElementsOffset, | 455 JSObject::kElementsOffset, |
456 r11, | 456 r11, |
457 r15, | 457 r15, |
458 kDontSaveFPRegs, | 458 kDontSaveFPRegs, |
459 EMIT_REMEMBERED_SET, | 459 EMIT_REMEMBERED_SET, |
460 OMIT_SMI_CHECK); | 460 OMIT_SMI_CHECK); |
461 __ pop(rax); | 461 __ pop(rax); |
462 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 462 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
463 | 463 |
464 __ bind(&only_change_map); | 464 __ bind(&only_change_map); |
465 // Set transitioned map. | 465 // Set transitioned map. |
466 __ movq(FieldOperand(rdx, HeapObject::kMapOffset), rbx); | 466 __ movp(FieldOperand(rdx, HeapObject::kMapOffset), rbx); |
467 __ RecordWriteField(rdx, | 467 __ RecordWriteField(rdx, |
468 HeapObject::kMapOffset, | 468 HeapObject::kMapOffset, |
469 rbx, | 469 rbx, |
470 rdi, | 470 rdi, |
471 kDontSaveFPRegs, | 471 kDontSaveFPRegs, |
472 OMIT_REMEMBERED_SET, | 472 OMIT_REMEMBERED_SET, |
473 OMIT_SMI_CHECK); | 473 OMIT_SMI_CHECK); |
474 } | 474 } |
475 | 475 |
476 | 476 |
477 void StringCharLoadGenerator::Generate(MacroAssembler* masm, | 477 void StringCharLoadGenerator::Generate(MacroAssembler* masm, |
478 Register string, | 478 Register string, |
479 Register index, | 479 Register index, |
480 Register result, | 480 Register result, |
481 Label* call_runtime) { | 481 Label* call_runtime) { |
482 // Fetch the instance type of the receiver into result register. | 482 // Fetch the instance type of the receiver into result register. |
483 __ movq(result, FieldOperand(string, HeapObject::kMapOffset)); | 483 __ movp(result, FieldOperand(string, HeapObject::kMapOffset)); |
484 __ movzxbl(result, FieldOperand(result, Map::kInstanceTypeOffset)); | 484 __ movzxbl(result, FieldOperand(result, Map::kInstanceTypeOffset)); |
485 | 485 |
486 // We need special handling for indirect strings. | 486 // We need special handling for indirect strings. |
487 Label check_sequential; | 487 Label check_sequential; |
488 __ testb(result, Immediate(kIsIndirectStringMask)); | 488 __ testb(result, Immediate(kIsIndirectStringMask)); |
489 __ j(zero, &check_sequential, Label::kNear); | 489 __ j(zero, &check_sequential, Label::kNear); |
490 | 490 |
491 // Dispatch on the indirect string shape: slice or cons. | 491 // Dispatch on the indirect string shape: slice or cons. |
492 Label cons_string; | 492 Label cons_string; |
493 __ testb(result, Immediate(kSlicedNotConsMask)); | 493 __ testb(result, Immediate(kSlicedNotConsMask)); |
494 __ j(zero, &cons_string, Label::kNear); | 494 __ j(zero, &cons_string, Label::kNear); |
495 | 495 |
496 // Handle slices. | 496 // Handle slices. |
497 Label indirect_string_loaded; | 497 Label indirect_string_loaded; |
498 __ SmiToInteger32(result, FieldOperand(string, SlicedString::kOffsetOffset)); | 498 __ SmiToInteger32(result, FieldOperand(string, SlicedString::kOffsetOffset)); |
499 __ addq(index, result); | 499 __ addq(index, result); |
500 __ movq(string, FieldOperand(string, SlicedString::kParentOffset)); | 500 __ movp(string, FieldOperand(string, SlicedString::kParentOffset)); |
501 __ jmp(&indirect_string_loaded, Label::kNear); | 501 __ jmp(&indirect_string_loaded, Label::kNear); |
502 | 502 |
503 // Handle cons strings. | 503 // Handle cons strings. |
504 // Check whether the right hand side is the empty string (i.e. if | 504 // Check whether the right hand side is the empty string (i.e. if |
505 // this is really a flat string in a cons string). If that is not | 505 // this is really a flat string in a cons string). If that is not |
506 // the case we would rather go to the runtime system now to flatten | 506 // the case we would rather go to the runtime system now to flatten |
507 // the string. | 507 // the string. |
508 __ bind(&cons_string); | 508 __ bind(&cons_string); |
509 __ CompareRoot(FieldOperand(string, ConsString::kSecondOffset), | 509 __ CompareRoot(FieldOperand(string, ConsString::kSecondOffset), |
510 Heap::kempty_stringRootIndex); | 510 Heap::kempty_stringRootIndex); |
511 __ j(not_equal, call_runtime); | 511 __ j(not_equal, call_runtime); |
512 __ movq(string, FieldOperand(string, ConsString::kFirstOffset)); | 512 __ movp(string, FieldOperand(string, ConsString::kFirstOffset)); |
513 | 513 |
514 __ bind(&indirect_string_loaded); | 514 __ bind(&indirect_string_loaded); |
515 __ movq(result, FieldOperand(string, HeapObject::kMapOffset)); | 515 __ movp(result, FieldOperand(string, HeapObject::kMapOffset)); |
516 __ movzxbl(result, FieldOperand(result, Map::kInstanceTypeOffset)); | 516 __ movzxbl(result, FieldOperand(result, Map::kInstanceTypeOffset)); |
517 | 517 |
518 // Distinguish sequential and external strings. Only these two string | 518 // Distinguish sequential and external strings. Only these two string |
519 // representations can reach here (slices and flat cons strings have been | 519 // representations can reach here (slices and flat cons strings have been |
520 // reduced to the underlying sequential or external string). | 520 // reduced to the underlying sequential or external string). |
521 Label seq_string; | 521 Label seq_string; |
522 __ bind(&check_sequential); | 522 __ bind(&check_sequential); |
523 STATIC_ASSERT(kSeqStringTag == 0); | 523 STATIC_ASSERT(kSeqStringTag == 0); |
524 __ testb(result, Immediate(kStringRepresentationMask)); | 524 __ testb(result, Immediate(kStringRepresentationMask)); |
525 __ j(zero, &seq_string, Label::kNear); | 525 __ j(zero, &seq_string, Label::kNear); |
526 | 526 |
527 // Handle external strings. | 527 // Handle external strings. |
528 Label ascii_external, done; | 528 Label ascii_external, done; |
529 if (FLAG_debug_code) { | 529 if (FLAG_debug_code) { |
530 // Assert that we do not have a cons or slice (indirect strings) here. | 530 // Assert that we do not have a cons or slice (indirect strings) here. |
531 // Sequential strings have already been ruled out. | 531 // Sequential strings have already been ruled out. |
532 __ testb(result, Immediate(kIsIndirectStringMask)); | 532 __ testb(result, Immediate(kIsIndirectStringMask)); |
533 __ Assert(zero, kExternalStringExpectedButNotFound); | 533 __ Assert(zero, kExternalStringExpectedButNotFound); |
534 } | 534 } |
535 // Rule out short external strings. | 535 // Rule out short external strings. |
536 STATIC_CHECK(kShortExternalStringTag != 0); | 536 STATIC_CHECK(kShortExternalStringTag != 0); |
537 __ testb(result, Immediate(kShortExternalStringTag)); | 537 __ testb(result, Immediate(kShortExternalStringTag)); |
538 __ j(not_zero, call_runtime); | 538 __ j(not_zero, call_runtime); |
539 // Check encoding. | 539 // Check encoding. |
540 STATIC_ASSERT(kTwoByteStringTag == 0); | 540 STATIC_ASSERT(kTwoByteStringTag == 0); |
541 __ testb(result, Immediate(kStringEncodingMask)); | 541 __ testb(result, Immediate(kStringEncodingMask)); |
542 __ movq(result, FieldOperand(string, ExternalString::kResourceDataOffset)); | 542 __ movp(result, FieldOperand(string, ExternalString::kResourceDataOffset)); |
543 __ j(not_equal, &ascii_external, Label::kNear); | 543 __ j(not_equal, &ascii_external, Label::kNear); |
544 // Two-byte string. | 544 // Two-byte string. |
545 __ movzxwl(result, Operand(result, index, times_2, 0)); | 545 __ movzxwl(result, Operand(result, index, times_2, 0)); |
546 __ jmp(&done, Label::kNear); | 546 __ jmp(&done, Label::kNear); |
547 __ bind(&ascii_external); | 547 __ bind(&ascii_external); |
548 // Ascii string. | 548 // Ascii string. |
549 __ movzxbl(result, Operand(result, index, times_1, 0)); | 549 __ movzxbl(result, Operand(result, index, times_1, 0)); |
550 __ jmp(&done, Label::kNear); | 550 __ jmp(&done, Label::kNear); |
551 | 551 |
552 // Dispatch on the encoding: ASCII or two-byte. | 552 // Dispatch on the encoding: ASCII or two-byte. |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
634 static byte* GetNoCodeAgeSequence(uint32_t* length) { | 634 static byte* GetNoCodeAgeSequence(uint32_t* length) { |
635 static bool initialized = false; | 635 static bool initialized = false; |
636 static byte sequence[kNoCodeAgeSequenceLength]; | 636 static byte sequence[kNoCodeAgeSequenceLength]; |
637 *length = kNoCodeAgeSequenceLength; | 637 *length = kNoCodeAgeSequenceLength; |
638 if (!initialized) { | 638 if (!initialized) { |
639 // The sequence of instructions that is patched out for aging code is the | 639 // The sequence of instructions that is patched out for aging code is the |
640 // following boilerplate stack-building prologue that is found both in | 640 // following boilerplate stack-building prologue that is found both in |
641 // FUNCTION and OPTIMIZED_FUNCTION code: | 641 // FUNCTION and OPTIMIZED_FUNCTION code: |
642 CodePatcher patcher(sequence, kNoCodeAgeSequenceLength); | 642 CodePatcher patcher(sequence, kNoCodeAgeSequenceLength); |
643 patcher.masm()->push(rbp); | 643 patcher.masm()->push(rbp); |
644 patcher.masm()->movq(rbp, rsp); | 644 patcher.masm()->movp(rbp, rsp); |
645 patcher.masm()->push(rsi); | 645 patcher.masm()->push(rsi); |
646 patcher.masm()->push(rdi); | 646 patcher.masm()->push(rdi); |
647 initialized = true; | 647 initialized = true; |
648 } | 648 } |
649 return sequence; | 649 return sequence; |
650 } | 650 } |
651 | 651 |
652 | 652 |
653 bool Code::IsYoungSequence(byte* sequence) { | 653 bool Code::IsYoungSequence(byte* sequence) { |
654 uint32_t young_length; | 654 uint32_t young_length; |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
710 // argument_count_reg_ * times_pointer_size + (receiver - 1) * kPointerSize. | 710 // argument_count_reg_ * times_pointer_size + (receiver - 1) * kPointerSize. |
711 return Operand(base_reg_, argument_count_reg_, times_pointer_size, | 711 return Operand(base_reg_, argument_count_reg_, times_pointer_size, |
712 displacement_to_last_argument + (receiver - 1 - index) * kPointerSize); | 712 displacement_to_last_argument + (receiver - 1 - index) * kPointerSize); |
713 } | 713 } |
714 } | 714 } |
715 | 715 |
716 | 716 |
717 } } // namespace v8::internal | 717 } } // namespace v8::internal |
718 | 718 |
719 #endif // V8_TARGET_ARCH_X64 | 719 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |