| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64. |
| 6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
| 7 | 7 |
| 8 #include "vm/intrinsifier.h" | 8 #include "vm/intrinsifier.h" |
| 9 | 9 |
| 10 #include "vm/assembler.h" | 10 #include "vm/assembler.h" |
| (...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 404 RAX); | 404 RAX); |
| 405 const Immediate& raw_null = | 405 const Immediate& raw_null = |
| 406 Immediate(reinterpret_cast<int64_t>(Object::null())); | 406 Immediate(reinterpret_cast<int64_t>(Object::null())); |
| 407 __ movq(RAX, raw_null); | 407 __ movq(RAX, raw_null); |
| 408 __ ret(); | 408 __ ret(); |
| 409 __ Bind(&fall_through); | 409 __ Bind(&fall_through); |
| 410 return false; | 410 return false; |
| 411 } | 411 } |
| 412 | 412 |
| 413 | 413 |
| 414 bool Intrinsifier::ByteArrayBase_getLength(Assembler* assembler) { | |
| 415 __ movq(RAX, Address(RSP, + 1 * kWordSize)); | |
| 416 __ movq(RAX, FieldAddress(RAX, ByteArray::length_offset())); | |
| 417 __ ret(); | |
| 418 // Generate enough code to satisfy patchability constraint. | |
| 419 intptr_t offset = __ CodeSize(); | |
| 420 __ nop(JumpPattern::InstructionLength() - offset); | |
| 421 return true; | |
| 422 } | |
| 423 | |
| 424 | |
| 425 | 414 |
| 426 // Tests if index is a valid length (Smi and within valid index range), | 415 // Tests if index is a valid length (Smi and within valid index range), |
| 427 // jumps to fall_through if it is not. | 416 // jumps to fall_through if it is not. |
| 428 // Returns index in R12, array in RAX. | 417 // Returns index in R12, array in RAX. |
| 429 // This should be used only on getIndexed intrinsics. | 418 // This should be used only on getIndexed intrinsics. |
| 430 void TestByteArrayGetIndex(Assembler* assembler, Label* fall_through) { | 419 void TestByteArrayGetIndex(Assembler* assembler, Label* fall_through) { |
| 431 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Array. | 420 __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Array. |
| 432 __ movq(R12, Address(RSP, + 1 * kWordSize)); // Index. | 421 __ movq(R12, Address(RSP, + 1 * kWordSize)); // Index. |
| 433 __ testq(R12, Immediate(kSmiTagMask)); | 422 __ testq(R12, Immediate(kSmiTagMask)); |
| 434 __ j(NOT_ZERO, fall_through, Assembler::kNearJump); // Non-smi index. | 423 __ j(NOT_ZERO, fall_through, Assembler::kNearJump); // Non-smi index. |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 530 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump); \ | 519 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump); \ |
| 531 __ movq(Address(RDI, 0), RBX); \ | 520 __ movq(Address(RDI, 0), RBX); \ |
| 532 __ addq(RDI, Immediate(kWordSize)); \ | 521 __ addq(RDI, Immediate(kWordSize)); \ |
| 533 __ jmp(&init_loop, Assembler::kNearJump); \ | 522 __ jmp(&init_loop, Assembler::kNearJump); \ |
| 534 __ Bind(&done); \ | 523 __ Bind(&done); \ |
| 535 \ | 524 \ |
| 536 __ ret(); \ | 525 __ ret(); \ |
| 537 __ Bind(&fall_through); \ | 526 __ Bind(&fall_through); \ |
| 538 | 527 |
| 539 | 528 |
| 540 #define SCALARLIST_ALLOCATOR(clazz, scale) \ | |
| 541 bool Intrinsifier::clazz##_new(Assembler* assembler) { \ | |
| 542 ScaleFactor scale_fac = scale; \ | |
| 543 TYPED_ARRAY_ALLOCATION(clazz, k##clazz##Cid, clazz::kMaxElements, scale_fac);\ | |
| 544 return false; \ | |
| 545 } \ | |
| 546 bool Intrinsifier::clazz##_factory(Assembler* assembler) { \ | |
| 547 ScaleFactor scale_fac = scale; \ | |
| 548 TYPED_ARRAY_ALLOCATION(clazz, k##clazz##Cid, clazz::kMaxElements, scale_fac);\ | |
| 549 return false; \ | |
| 550 } | |
| 551 | |
| 552 | |
| 553 SCALARLIST_ALLOCATOR(Int8Array, TIMES_1) | |
| 554 SCALARLIST_ALLOCATOR(Uint8Array, TIMES_1) | |
| 555 SCALARLIST_ALLOCATOR(Uint8ClampedArray, TIMES_1) | |
| 556 SCALARLIST_ALLOCATOR(Int16Array, TIMES_2) | |
| 557 SCALARLIST_ALLOCATOR(Uint16Array, TIMES_2) | |
| 558 SCALARLIST_ALLOCATOR(Int32Array, TIMES_4) | |
| 559 SCALARLIST_ALLOCATOR(Uint32Array, TIMES_4) | |
| 560 SCALARLIST_ALLOCATOR(Int64Array, TIMES_8) | |
| 561 SCALARLIST_ALLOCATOR(Uint64Array, TIMES_8) | |
| 562 SCALARLIST_ALLOCATOR(Float32Array, TIMES_4) | |
| 563 SCALARLIST_ALLOCATOR(Float64Array, TIMES_8) | |
| 564 | |
| 565 | |
| 566 bool Intrinsifier::Int64Array_getIndexed(Assembler* assembler) { | |
| 567 Label fall_through; | |
| 568 TestByteArrayGetIndex(assembler, &fall_through); | |
| 569 // R12: index as Smi. | |
| 570 // RAX: array. | |
| 571 __ movq(RAX, FieldAddress(RAX, | |
| 572 R12, | |
| 573 TIMES_4, | |
| 574 Int64Array::data_offset())); | |
| 575 // Copy RAX into R12. | |
| 576 // We destroy R12 while testing if RAX can fit inside a Smi. | |
| 577 __ movq(R12, RAX); | |
| 578 // Verify that the signed value in RAX can fit inside a Smi. | |
| 579 __ shlq(R12, Immediate(0x1)); | |
| 580 // Jump to fall_through if it can not. | |
| 581 __ j(OVERFLOW, &fall_through, Assembler::kNearJump); | |
| 582 __ SmiTag(RAX); | |
| 583 __ ret(); | |
| 584 __ Bind(&fall_through); | |
| 585 return false; | |
| 586 } | |
| 587 | |
| 588 | |
| 589 bool Intrinsifier::Uint64Array_getIndexed(Assembler* assembler) { | |
| 590 Label fall_through; | |
| 591 TestByteArrayGetIndex(assembler, &fall_through); | |
| 592 // R12: index as Smi. | |
| 593 // RAX: array. | |
| 594 __ movq(RAX, FieldAddress(RAX, | |
| 595 R12, | |
| 596 TIMES_4, | |
| 597 Uint64Array::data_offset())); | |
| 598 // Copy RAX into R12. | |
| 599 // We destroy R12 while testing if RAX can fit inside a Smi. | |
| 600 __ movq(R12, RAX); | |
| 601 // Verify that the unsigned value in RAX can be stored in a Smi. | |
| 602 __ shrq(R12, Immediate(kSmiBits)); | |
| 603 __ j(NOT_ZERO, &fall_through, Assembler::kNearJump); // Won't fit Smi. | |
| 604 __ SmiTag(RAX); | |
| 605 __ ret(); | |
| 606 __ Bind(&fall_through); | |
| 607 return false; | |
| 608 } | |
| 609 | |
| 610 | |
| 611 // Gets the length of a TypedData. | 529 // Gets the length of a TypedData. |
| 612 bool Intrinsifier::TypedData_getLength(Assembler* assembler) { | 530 bool Intrinsifier::TypedData_getLength(Assembler* assembler) { |
| 613 __ movq(RAX, Address(RSP, + 1 * kWordSize)); | 531 __ movq(RAX, Address(RSP, + 1 * kWordSize)); |
| 614 __ movq(RAX, FieldAddress(RAX, TypedData::length_offset())); | 532 __ movq(RAX, FieldAddress(RAX, TypedData::length_offset())); |
| 615 __ ret(); | 533 __ ret(); |
| 616 // Generate enough code to satisfy patchability constraint. | 534 // Generate enough code to satisfy patchability constraint. |
| 617 intptr_t offset = __ CodeSize(); | 535 intptr_t offset = __ CodeSize(); |
| 618 __ nop(JumpPattern::InstructionLength() - offset); | 536 __ nop(JumpPattern::InstructionLength() - offset); |
| 619 return true; | 537 return true; |
| 620 } | 538 } |
| (...skipping 896 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1517 __ ret(); | 1435 __ ret(); |
| 1518 return true; | 1436 return true; |
| 1519 } | 1437 } |
| 1520 | 1438 |
| 1521 | 1439 |
| 1522 #undef __ | 1440 #undef __ |
| 1523 | 1441 |
| 1524 } // namespace dart | 1442 } // namespace dart |
| 1525 | 1443 |
| 1526 #endif // defined TARGET_ARCH_X64 | 1444 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |