Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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/code_generator.h" | 8 #include "vm/code_generator.h" |
| 9 #include "vm/compiler.h" | 9 #include "vm/compiler.h" |
| 10 #include "vm/ic_data.h" | 10 #include "vm/ic_data.h" |
| (...skipping 553 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 564 | 564 |
| 565 if (FLAG_inline_alloc) { | 565 if (FLAG_inline_alloc) { |
| 566 // Compute the size to be allocated, it is based on the array length | 566 // Compute the size to be allocated, it is based on the array length |
| 567 // and it computed as: | 567 // and it computed as: |
| 568 // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)). | 568 // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)). |
| 569 // Assert that length is a Smi. | 569 // Assert that length is a Smi. |
| 570 __ testq(R10, Immediate(kSmiTagSize)); | 570 __ testq(R10, Immediate(kSmiTagSize)); |
| 571 if (FLAG_use_slow_path) { | 571 if (FLAG_use_slow_path) { |
| 572 __ jmp(&slow_case); | 572 __ jmp(&slow_case); |
| 573 } else { | 573 } else { |
| 574 __ j(NOT_ZERO, &slow_case, Assembler::kNearJump); | 574 __ j(NOT_ZERO, &slow_case); |
| 575 } | 575 } |
| 576 __ movq(R13, FieldAddress(CTX, Context::isolate_offset())); | 576 __ movq(R13, FieldAddress(CTX, Context::isolate_offset())); |
| 577 __ movq(R13, Address(R13, Isolate::heap_offset())); | 577 __ movq(R13, Address(R13, Isolate::heap_offset())); |
| 578 __ movq(R13, Address(R13, Heap::new_space_offset())); | 578 __ movq(R13, Address(R13, Heap::new_space_offset())); |
| 579 | 579 |
| 580 // Calculate and align allocation size. | 580 // Calculate and align allocation size. |
| 581 // Load new object start and calculate next object start. | 581 // Load new object start and calculate next object start. |
| 582 // RBX: array element type. | 582 // RBX: array element type. |
| 583 // R10: Array length as Smi. | 583 // R10: Array length as Smi. |
| 584 // R13: Points to new space object. | 584 // R13: Points to new space object. |
| 585 __ movq(RAX, Address(R13, Scavenger::top_offset())); | 585 __ movq(RAX, Address(R13, Scavenger::top_offset())); |
| 586 intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1; | 586 intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1; |
| 587 __ leaq(R12, Address(R10, TIMES_4, fixed_size)); // R10 is Smi. | 587 __ leaq(R12, Address(R10, TIMES_4, fixed_size)); // R10 is Smi. |
| 588 ASSERT(kSmiTagShift == 1); | 588 ASSERT(kSmiTagShift == 1); |
| 589 __ andq(R12, Immediate(-kObjectAlignment)); | 589 __ andq(R12, Immediate(-kObjectAlignment)); |
| 590 __ leaq(R12, Address(RAX, R12, TIMES_1, 0)); | 590 __ leaq(R12, Address(RAX, R12, TIMES_1, 0)); |
| 591 | 591 |
| 592 // Check if the allocation fits into the remaining space. | 592 // Check if the allocation fits into the remaining space. |
| 593 // RAX: potential new object start. | 593 // RAX: potential new object start. |
| 594 // R12: potential next object start. | 594 // R12: potential next object start. |
| 595 // RBX: array element type. | 595 // RBX: array element type. |
| 596 // R10: Array length as Smi. | 596 // R10: Array length as Smi. |
| 597 // R13: Points to new space object. | 597 // R13: Points to new space object. |
| 598 __ cmpq(R12, Address(R13, Scavenger::end_offset())); | 598 __ cmpq(R12, Address(R13, Scavenger::end_offset())); |
| 599 __ j(ABOVE_EQUAL, &slow_case, Assembler::kNearJump); | 599 __ j(ABOVE_EQUAL, &slow_case); |
| 600 | 600 |
| 601 // Successfully allocated the object(s), now update top to point to | 601 // Successfully allocated the object(s), now update top to point to |
| 602 // next object start and initialize the object. | 602 // next object start and initialize the object. |
| 603 // RAX: potential new object start. | 603 // RAX: potential new object start. |
| 604 // R12: potential next object start. | 604 // R12: potential next object start. |
| 605 // R13: Points to new space object. | 605 // R13: Points to new space object. |
| 606 __ movq(Address(R13, Scavenger::top_offset()), R12); | 606 __ movq(Address(R13, Scavenger::top_offset()), R12); |
| 607 __ addq(RAX, Immediate(kHeapObjectTag)); | 607 __ addq(RAX, Immediate(kHeapObjectTag)); |
| 608 | 608 |
| 609 // RAX: new object start as a tagged pointer. | 609 // RAX: new object start as a tagged pointer. |
| 610 // R12: new object end address. | 610 // R12: new object end address. |
| 611 // RBX: array element type. | 611 // RBX: array element type. |
| 612 // R10: Array length as Smi. | 612 // R10: Array length as Smi. |
| 613 | 613 |
| 614 // Store the type argument field. | 614 // Store the type argument field. |
| 615 __ StoreIntoObject(RAX, | 615 __ StoreIntoObject(RAX, |
| 616 FieldAddress(RAX, Array::type_arguments_offset()), | 616 FieldAddress(RAX, Array::type_arguments_offset()), |
| 617 RBX); | 617 RBX); |
| 618 | 618 |
| 619 // Set the length field. | 619 // Set the length field. |
| 620 __ StoreIntoObject(RAX, FieldAddress(RAX, Array::length_offset()), R10); | 620 __ StoreIntoObject(RAX, FieldAddress(RAX, Array::length_offset()), R10); |
| 621 | 621 |
| 622 // Store class value for array. | 622 // Store class value for array. |
| 623 __ movq(RBX, FieldAddress(CTX, Context::isolate_offset())); | 623 __ movq(RBX, FieldAddress(CTX, Context::isolate_offset())); |
| 624 __ movq(RBX, Address(RBX, Isolate::object_store_offset())); | 624 __ movq(RBX, Address(RBX, Isolate::object_store_offset())); |
| 625 __ movq(RBX, Address(RBX, ObjectStore::array_class_offset())); | 625 __ movq(RBX, Address(RBX, ObjectStore::array_class_offset())); |
| 626 __ StoreIntoObject(RAX, FieldAddress(RAX, Array::class_offset()), RBX); | 626 __ StoreIntoObject(RAX, FieldAddress(RAX, Array::class_offset()), RBX); |
| 627 __ movq(FieldAddress(RAX, Array::tags_offset()), Immediate(0)); // Tags. | 627 // Calculate the size tag. |
| 628 // RAX: new object start as a tagged pointer. | |
| 629 // R12: new object end address. | |
| 630 // R10: Array length as Smi. | |
| 631 { | |
| 632 Label size_tag_overflow, done; | |
| 633 __ leaq(RBX, Address(R10, TIMES_2, fixed_size)); // R10 is Smi. | |
|
regis
2012/01/10 20:27:48
It should be TIMES_4.
I'll fix it in my next cl.
| |
| 634 ASSERT(kSmiTagShift == 1); | |
| 635 __ andq(RBX, Immediate(-kObjectAlignment)); | |
| 636 __ cmpq(RBX, Immediate(RawObject::SizeTag::kMaxSizeTag)); | |
| 637 __ j(ABOVE, &size_tag_overflow, Assembler::kNearJump); | |
| 638 __ shlq(RBX, Immediate(RawObject::kSizeTagBit - kObjectAlignmentLog2)); | |
| 639 __ movq(FieldAddress(RAX, Array::tags_offset()), RBX); | |
| 640 __ jmp(&done); | |
| 641 | |
| 642 __ Bind(&size_tag_overflow); | |
| 643 __ movq(FieldAddress(RAX, Array::tags_offset()), Immediate(0)); | |
| 644 __ Bind(&done); | |
| 645 } | |
| 628 | 646 |
| 629 // Initialize all array elements to raw_null. | 647 // Initialize all array elements to raw_null. |
| 630 // RAX: new object start as a tagged pointer. | 648 // RAX: new object start as a tagged pointer. |
| 631 // R12: new object end address. | 649 // R12: new object end address. |
| 632 // RBX: iterator which initially points to the start of the variable | 650 // RBX: iterator which initially points to the start of the variable |
| 633 // data area to be initialized. | 651 // data area to be initialized. |
| 634 __ leaq(RBX, FieldAddress(RAX, Array::data_offset())); | 652 __ leaq(RBX, FieldAddress(RAX, Array::data_offset())); |
| 635 Label done; | 653 Label done; |
| 636 Label init_loop; | 654 Label init_loop; |
| 637 __ Bind(&init_loop); | 655 __ Bind(&init_loop); |
| 638 __ cmpq(RBX, R12); | 656 __ cmpq(RBX, R12); |
| 639 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump); | 657 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump); |
| 640 __ movq(Address(RBX, 0), raw_null); | 658 __ movq(Address(RBX, 0), raw_null); |
| 641 __ addq(RBX, Immediate(kWordSize)); | 659 __ addq(RBX, Immediate(kWordSize)); |
| 642 __ jmp(&init_loop, Assembler::kNearJump); | 660 __ jmp(&init_loop, Assembler::kNearJump); |
| 643 __ Bind(&done); | 661 __ Bind(&done); |
| 644 | 662 |
| 645 // Done allocating and initializing the array. | 663 // Done allocating and initializing the array. |
| 646 // RAX: new object. | 664 // RAX: new object. |
| 665 // R10: Array length as Smi (preserved for the caller.) | |
| 647 __ ret(); | 666 __ ret(); |
| 648 } | 667 } |
| 649 | 668 |
| 650 // Unable to allocate the array using the fast inline code, just call | 669 // Unable to allocate the array using the fast inline code, just call |
| 651 // into the runtime. | 670 // into the runtime. |
| 652 __ Bind(&slow_case); | 671 __ Bind(&slow_case); |
| 653 __ EnterFrame(0); | 672 __ EnterFrame(0); |
| 654 __ pushq(raw_null); // Setup space on stack for return value. | 673 __ pushq(raw_null); // Setup space on stack for return value. |
| 655 __ pushq(R10); // Array length as Smi. | 674 __ pushq(R10); // Array length as Smi. |
| 656 __ pushq(RBX); // Element type. | 675 __ pushq(RBX); // Element type. |
| (...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 887 __ movq(Address(RCX, | 906 __ movq(Address(RCX, |
| 888 InstantiatedTypeArguments::uninstantiated_type_arguments_offset()), | 907 InstantiatedTypeArguments::uninstantiated_type_arguments_offset()), |
| 889 RDI); | 908 RDI); |
| 890 __ movq(RDX, Address(RSP, kInstantiatorTypeArgumentsOffset)); | 909 __ movq(RDX, Address(RSP, kInstantiatorTypeArgumentsOffset)); |
| 891 __ movq(Address(RCX, | 910 __ movq(Address(RCX, |
| 892 InstantiatedTypeArguments::instantiator_type_arguments_offset()), | 911 InstantiatedTypeArguments::instantiator_type_arguments_offset()), |
| 893 RDX); | 912 RDX); |
| 894 __ LoadObject(RDX, | 913 __ LoadObject(RDX, |
| 895 Class::ZoneHandle(Object::instantiated_type_arguments_class())); | 914 Class::ZoneHandle(Object::instantiated_type_arguments_class())); |
| 896 __ movq(Address(RCX, Instance::class_offset()), RDX); // Set its class. | 915 __ movq(Address(RCX, Instance::class_offset()), RDX); // Set its class. |
| 897 __ movq(Address(RCX, Instance::tags_offset()), Immediate(0)); // Tags. | 916 // Set the tags. |
| 917 __ movq(Address(RCX, Instance::tags_offset()), | |
| 918 Immediate(RawObject::SizeTag::encode(type_args_size))); | |
| 898 // Set the new InstantiatedTypeArguments object (RCX) as the type | 919 // Set the new InstantiatedTypeArguments object (RCX) as the type |
| 899 // arguments (RDI) of the new object (RAX). | 920 // arguments (RDI) of the new object (RAX). |
| 900 __ movq(RDI, RCX); | 921 __ movq(RDI, RCX); |
| 901 __ addq(RDI, Immediate(kHeapObjectTag)); | 922 __ addq(RDI, Immediate(kHeapObjectTag)); |
| 902 // Set RBX to new object end. | 923 // Set RBX to new object end. |
| 903 __ movq(RBX, RCX); | 924 __ movq(RBX, RCX); |
| 904 __ Bind(&type_arguments_ready); | 925 __ Bind(&type_arguments_ready); |
| 905 // RAX: new object. | 926 // RAX: new object. |
| 906 // RDI: new object type arguments. | 927 // RDI: new object type arguments. |
| 907 } | 928 } |
| 908 | 929 |
| 909 // Initialize the class field in the object. | 930 // Initialize the class field in the object. |
| 910 // RAX: new object start. | 931 // RAX: new object start. |
| 911 // RBX: next object start. | 932 // RBX: next object start. |
| 912 // RDI: new object type arguments (if is_cls_parameterized). | 933 // RDI: new object type arguments (if is_cls_parameterized). |
| 913 __ LoadObject(RDX, cls); // Load class of object to be allocated. | 934 __ LoadObject(RDX, cls); // Load class of object to be allocated. |
| 914 __ movq(Address(RAX, Instance::class_offset()), RDX); | 935 __ movq(Address(RAX, Instance::class_offset()), RDX); |
| 915 __ movq(Address(RAX, Instance::tags_offset()), Immediate(0)); // Tags. | 936 // Set the tags. |
| 937 __ movq(Address(RAX, Instance::tags_offset()), | |
| 938 Immediate(RawObject::SizeTag::encode(instance_size))); | |
| 916 | 939 |
| 917 // Initialize the remaining words of the object. | 940 // Initialize the remaining words of the object. |
| 918 const Immediate raw_null = | 941 const Immediate raw_null = |
| 919 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 942 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 920 | 943 |
| 921 // RAX: new object start. | 944 // RAX: new object start. |
| 922 // RBX: next object start. | 945 // RBX: next object start. |
| 923 // RDX: class of the object to be allocated. | 946 // RDX: class of the object to be allocated. |
| 924 // First try inlining the initialization without a loop. | 947 // First try inlining the initialization without a loop. |
| 925 if (instance_size < (kInlineInstanceSize * kWordSize) && | 948 if (instance_size < (kInlineInstanceSize * kWordSize) && |
| (...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1243 } | 1266 } |
| 1244 | 1267 |
| 1245 | 1268 |
| 1246 void StubCode::GenerateBreakpointDynamicStub(Assembler* assembler) { | 1269 void StubCode::GenerateBreakpointDynamicStub(Assembler* assembler) { |
| 1247 __ Unimplemented("BreakpointDynamic stub"); | 1270 __ Unimplemented("BreakpointDynamic stub"); |
| 1248 } | 1271 } |
| 1249 | 1272 |
| 1250 } // namespace dart | 1273 } // namespace dart |
| 1251 | 1274 |
| 1252 #endif // defined TARGET_ARCH_X64 | 1275 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |