| 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" | 5 #include "vm/globals.h" |
| 6 #if defined(TARGET_ARCH_X64) | 6 #if defined(TARGET_ARCH_X64) |
| 7 | 7 |
| 8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
| 9 #include "vm/compiler.h" | 9 #include "vm/compiler.h" |
| 10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
| (...skipping 544 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 555 | 555 |
| 556 | 556 |
| 557 // Called for inline allocation of arrays. | 557 // Called for inline allocation of arrays. |
| 558 // Input parameters: | 558 // Input parameters: |
| 559 // R10 : Array length as Smi. | 559 // R10 : Array length as Smi. |
| 560 // RBX : array element type (either NULL or an instantiated type). | 560 // RBX : array element type (either NULL or an instantiated type). |
| 561 // NOTE: R10 cannot be clobbered here as the caller relies on it being saved. | 561 // NOTE: R10 cannot be clobbered here as the caller relies on it being saved. |
| 562 // The newly allocated object is returned in RAX. | 562 // The newly allocated object is returned in RAX. |
| 563 void StubCode::GenerateAllocateArrayStub(Assembler* assembler) { | 563 void StubCode::GenerateAllocateArrayStub(Assembler* assembler) { |
| 564 Label slow_case; | 564 Label slow_case; |
| 565 // Compute the size to be allocated, it is based on the array length |
| 566 // and is computed as: |
| 567 // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)). |
| 568 __ movq(RDI, R10); // Array Length. |
| 569 // Check that length is a positive Smi. |
| 570 __ testq(RDI, Immediate(kSmiTagMask)); |
| 571 __ j(NOT_ZERO, &slow_case); |
| 572 __ cmpq(RDI, Immediate(0)); |
| 573 __ j(LESS, &slow_case); |
| 574 // Check for maximum allowed length. |
| 575 const Immediate& max_len = |
| 576 Immediate(reinterpret_cast<int64_t>(Smi::New(Array::kMaxElements))); |
| 577 __ cmpq(RDI, max_len); |
| 578 __ j(GREATER, &slow_case); |
| 579 const intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1; |
| 580 __ leaq(RDI, Address(RDI, TIMES_4, fixed_size)); // RDI is a Smi. |
| 581 ASSERT(kSmiTagShift == 1); |
| 582 __ andq(RDI, Immediate(-kObjectAlignment)); |
| 565 | 583 |
| 566 if (FLAG_inline_alloc) { | 584 Isolate* isolate = Isolate::Current(); |
| 567 // Compute the size to be allocated, it is based on the array length | 585 Heap* heap = isolate->heap(); |
| 568 // and is computed as: | |
| 569 // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)). | |
| 570 // Assert that length is a Smi. | |
| 571 __ testq(R10, Immediate(kSmiTagMask)); | |
| 572 if (FLAG_use_slow_path) { | |
| 573 __ jmp(&slow_case); | |
| 574 } else { | |
| 575 __ j(NOT_ZERO, &slow_case); | |
| 576 } | |
| 577 __ cmpq(R10, Immediate(0)); | |
| 578 __ j(LESS, &slow_case); | |
| 579 | 586 |
| 580 // Check for maximum allowed length. | 587 __ movq(RAX, Immediate(heap->TopAddress())); |
| 581 const Immediate& max_len = | 588 __ movq(RAX, Address(RAX, 0)); |
| 582 Immediate(reinterpret_cast<int64_t>(Smi::New(Array::kMaxElements))); | |
| 583 __ cmpq(R10, max_len); | |
| 584 __ j(GREATER, &slow_case); | |
| 585 | 589 |
| 586 __ movq(R13, FieldAddress(CTX, Context::isolate_offset())); | 590 // RDI: allocation size. |
| 587 __ movq(R13, Address(R13, Isolate::heap_offset())); | 591 __ movq(RCX, RAX); |
| 588 __ movq(R13, Address(R13, Heap::new_space_offset())); | 592 __ addq(RCX, RDI); |
| 593 __ j(CARRY, &slow_case); |
| 589 | 594 |
| 590 // Calculate and align allocation size. | 595 // Check if the allocation fits into the remaining space. |
| 591 // Load new object start and calculate next object start. | 596 // RAX: potential new object start. |
| 592 // RBX: array element type. | 597 // RCX: potential next object start. |
| 593 // R10: Array length as Smi. | 598 // RDI: allocation size. |
| 594 // R13: Points to new space object. | 599 __ movq(R13, Immediate(heap->EndAddress())); |
| 595 __ movq(RAX, Address(R13, Scavenger::top_offset())); | 600 __ cmpq(RCX, Address(R13, 0)); |
| 596 intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1; | 601 __ j(ABOVE_EQUAL, &slow_case); |
| 597 __ leaq(R12, Address(R10, TIMES_4, fixed_size)); // R10 is Smi. | |
| 598 ASSERT(kSmiTagShift == 1); | |
| 599 __ andq(R12, Immediate(-kObjectAlignment)); | |
| 600 __ addq(R12, RAX); | |
| 601 __ j(CARRY, &slow_case); | |
| 602 | 602 |
| 603 // Check if the allocation fits into the remaining space. | 603 // Successfully allocated the object(s), now update top to point to |
| 604 // RAX: potential new object start. | 604 // next object start and initialize the object. |
| 605 // R12: potential next object start. | 605 __ movq(R13, Immediate(heap->TopAddress())); |
| 606 // RBX: array element type. | 606 __ movq(Address(R13, 0), RCX); |
| 607 // R10: Array length as Smi. | 607 __ addq(RAX, Immediate(kHeapObjectTag)); |
| 608 // R13: Points to new space object. | 608 __ UpdateAllocationStatsWithSize(kArrayCid, RDI); |
| 609 __ cmpq(R12, Address(R13, Scavenger::end_offset())); | 609 // Initialize the tags. |
| 610 __ j(ABOVE_EQUAL, &slow_case); | 610 // RAX: new object start as a tagged pointer. |
| 611 // RDI: allocation size. |
| 612 { |
| 613 Label size_tag_overflow, done; |
| 614 __ cmpq(RDI, Immediate(RawObject::SizeTag::kMaxSizeTag)); |
| 615 __ j(ABOVE, &size_tag_overflow, Assembler::kNearJump); |
| 616 __ shlq(RDI, Immediate(RawObject::kSizeTagPos - kObjectAlignmentLog2)); |
| 617 __ jmp(&done, Assembler::kNearJump); |
| 611 | 618 |
| 612 // Successfully allocated the object(s), now update top to point to | 619 __ Bind(&size_tag_overflow); |
| 613 // next object start and initialize the object. | 620 __ movq(RDI, Immediate(0)); |
| 614 // RAX: potential new object start. | |
| 615 // R12: potential next object start. | |
| 616 // R13: Points to new space object. | |
| 617 __ movq(Address(R13, Scavenger::top_offset()), R12); | |
| 618 __ addq(RAX, Immediate(kHeapObjectTag)); | |
| 619 // R13: Size of allocation in bytes. | |
| 620 __ movq(R13, R12); | |
| 621 __ subq(R13, RAX); | |
| 622 __ UpdateAllocationStatsWithSize(kArrayCid, R13); | |
| 623 | |
| 624 // RAX: new object start as a tagged pointer. | |
| 625 // R12: new object end address. | |
| 626 // RBX: array element type. | |
| 627 // R10: Array length as Smi. | |
| 628 | |
| 629 // Store the type argument field. | |
| 630 __ StoreIntoObjectNoBarrier( | |
| 631 RAX, FieldAddress(RAX, Array::type_arguments_offset()), RBX); | |
| 632 | |
| 633 // Set the length field. | |
| 634 __ StoreIntoObjectNoBarrier( | |
| 635 RAX, FieldAddress(RAX, Array::length_offset()), R10); | |
| 636 | |
| 637 // Calculate the size tag. | |
| 638 // RAX: new object start as a tagged pointer. | |
| 639 // R12: new object end address. | |
| 640 // R10: Array length as Smi. | |
| 641 { | |
| 642 Label size_tag_overflow, done; | |
| 643 __ leaq(RBX, Address(R10, TIMES_4, fixed_size)); // R10 is Smi. | |
| 644 ASSERT(kSmiTagShift == 1); | |
| 645 __ andq(RBX, Immediate(-kObjectAlignment)); | |
| 646 __ cmpq(RBX, Immediate(RawObject::SizeTag::kMaxSizeTag)); | |
| 647 __ j(ABOVE, &size_tag_overflow, Assembler::kNearJump); | |
| 648 __ shlq(RBX, Immediate(RawObject::kSizeTagPos - kObjectAlignmentLog2)); | |
| 649 __ jmp(&done); | |
| 650 | |
| 651 __ Bind(&size_tag_overflow); | |
| 652 __ movq(RBX, Immediate(0)); | |
| 653 __ Bind(&done); | |
| 654 | |
| 655 // Get the class index and insert it into the tags. | |
| 656 __ orq(RBX, Immediate(RawObject::ClassIdTag::encode(kArrayCid))); | |
| 657 __ movq(FieldAddress(RAX, Array::tags_offset()), RBX); | |
| 658 } | |
| 659 | |
| 660 // Initialize all array elements to raw_null. | |
| 661 // RAX: new object start as a tagged pointer. | |
| 662 // R12: new object end address. | |
| 663 // R10: Array length as Smi. | |
| 664 __ leaq(RBX, FieldAddress(RAX, Array::data_offset())); | |
| 665 // RBX: iterator which initially points to the start of the variable | |
| 666 // data area to be initialized. | |
| 667 __ LoadObject(R13, Object::null_object(), PP); | |
| 668 Label done; | |
| 669 Label init_loop; | |
| 670 __ Bind(&init_loop); | |
| 671 __ cmpq(RBX, R12); | |
| 672 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump); | |
| 673 // TODO(cshapiro): StoreIntoObjectNoBarrier | |
| 674 __ movq(Address(RBX, 0), R13); | |
| 675 __ addq(RBX, Immediate(kWordSize)); | |
| 676 __ jmp(&init_loop, Assembler::kNearJump); | |
| 677 __ Bind(&done); | 621 __ Bind(&done); |
| 678 | 622 |
| 679 // Done allocating and initializing the array. | 623 // Get the class index and insert it into the tags. |
| 680 // RAX: new object. | 624 const Class& cls = Class::Handle(isolate->object_store()->array_class()); |
| 681 // R10: Array length as Smi (preserved for the caller.) | 625 __ orq(RDI, Immediate(RawObject::ClassIdTag::encode(cls.id()))); |
| 682 __ ret(); | 626 __ movq(FieldAddress(RAX, Array::tags_offset()), RDI); // Tags. |
| 683 } | 627 } |
| 684 | 628 |
| 629 // RAX: new object start as a tagged pointer. |
| 630 // Store the type argument field. |
| 631 __ StoreIntoObjectNoBarrier(RAX, |
| 632 FieldAddress(RAX, Array::type_arguments_offset()), |
| 633 RBX); |
| 634 |
| 635 // Set the length field. |
| 636 __ StoreIntoObjectNoBarrier(RAX, |
| 637 FieldAddress(RAX, Array::length_offset()), |
| 638 R10); |
| 639 |
| 640 // Initialize all array elements to raw_null. |
| 641 // RAX: new object start as a tagged pointer. |
| 642 // RCX: new object end address. |
| 643 // RDI: iterator which initially points to the start of the variable |
| 644 // data area to be initialized. |
| 645 __ LoadObject(R12, Object::null_object(), PP); |
| 646 __ leaq(RDI, FieldAddress(RAX, sizeof(RawArray))); |
| 647 Label done; |
| 648 Label init_loop; |
| 649 __ Bind(&init_loop); |
| 650 __ cmpq(RDI, RCX); |
| 651 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump); |
| 652 __ movq(Address(RDI, 0), R12); |
| 653 __ addq(RDI, Immediate(kWordSize)); |
| 654 __ jmp(&init_loop, Assembler::kNearJump); |
| 655 __ Bind(&done); |
| 656 __ ret(); // returns the newly allocated object in RAX. |
| 657 |
| 685 // Unable to allocate the array using the fast inline code, just call | 658 // Unable to allocate the array using the fast inline code, just call |
| 686 // into the runtime. | 659 // into the runtime. |
| 687 __ Bind(&slow_case); | 660 __ Bind(&slow_case); |
| 688 // Create a stub frame as we are pushing some objects on the stack before | 661 // Create a stub frame as we are pushing some objects on the stack before |
| 689 // calling into the runtime. | 662 // calling into the runtime. |
| 690 __ EnterStubFrame(); | 663 __ EnterStubFrame(); |
| 691 // Setup space on stack for return value. | 664 // Setup space on stack for return value. |
| 692 __ PushObject(Object::null_object(), PP); | 665 __ PushObject(Object::null_object(), PP); |
| 693 __ pushq(R10); // Array length as Smi. | 666 __ pushq(R10); // Array length as Smi. |
| 694 __ pushq(RBX); // Element type. | 667 __ pushq(RBX); // Element type. |
| (...skipping 1152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1847 | 1820 |
| 1848 __ movq(left, Address(RSP, 2 * kWordSize)); | 1821 __ movq(left, Address(RSP, 2 * kWordSize)); |
| 1849 __ movq(right, Address(RSP, 1 * kWordSize)); | 1822 __ movq(right, Address(RSP, 1 * kWordSize)); |
| 1850 GenerateIdenticalWithNumberCheckStub(assembler, left, right); | 1823 GenerateIdenticalWithNumberCheckStub(assembler, left, right); |
| 1851 __ ret(); | 1824 __ ret(); |
| 1852 } | 1825 } |
| 1853 | 1826 |
| 1854 } // namespace dart | 1827 } // namespace dart |
| 1855 | 1828 |
| 1856 #endif // defined TARGET_ARCH_X64 | 1829 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |