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 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
361 __ pushq(RAX); // Array is in RAX and on top of stack. | 361 __ pushq(RAX); // Array is in RAX and on top of stack. |
362 __ leaq(R12, Address(RBP, R10, TIMES_8, kParamEndSlotFromFp * kWordSize)); | 362 __ leaq(R12, Address(RBP, R10, TIMES_8, kParamEndSlotFromFp * kWordSize)); |
363 __ leaq(RBX, FieldAddress(RAX, Array::data_offset())); | 363 __ leaq(RBX, FieldAddress(RAX, Array::data_offset())); |
364 // R12: address of first argument on stack. | 364 // R12: address of first argument on stack. |
365 // RBX: address of first argument in array. | 365 // RBX: address of first argument in array. |
366 Label loop, loop_condition; | 366 Label loop, loop_condition; |
367 __ jmp(&loop_condition, Assembler::kNearJump); | 367 __ jmp(&loop_condition, Assembler::kNearJump); |
368 __ Bind(&loop); | 368 __ Bind(&loop); |
369 __ movq(RDI, Address(R12, 0)); | 369 __ movq(RDI, Address(R12, 0)); |
370 // No generational barrier needed, since array is in new space. | 370 // No generational barrier needed, since array is in new space. |
371 __ StoreIntoObjectNoBarrier(RAX, Address(RBX, 0), RDI); | 371 __ InitializeFieldNoBarrier(RAX, Address(RBX, 0), RDI); |
372 __ addq(RBX, Immediate(kWordSize)); | 372 __ addq(RBX, Immediate(kWordSize)); |
373 __ subq(R12, Immediate(kWordSize)); | 373 __ subq(R12, Immediate(kWordSize)); |
374 __ Bind(&loop_condition); | 374 __ Bind(&loop_condition); |
375 __ decq(R10); | 375 __ decq(R10); |
376 __ j(POSITIVE, &loop, Assembler::kNearJump); | 376 __ j(POSITIVE, &loop, Assembler::kNearJump); |
377 } | 377 } |
378 | 378 |
379 | 379 |
380 DECLARE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame, | 380 DECLARE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame, |
381 intptr_t deopt_reason, | 381 intptr_t deopt_reason, |
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
625 __ movq(RDI, Immediate(0)); | 625 __ movq(RDI, Immediate(0)); |
626 __ Bind(&done); | 626 __ Bind(&done); |
627 | 627 |
628 // Get the class index and insert it into the tags. | 628 // Get the class index and insert it into the tags. |
629 __ orq(RDI, Immediate(RawObject::ClassIdTag::encode(cid))); | 629 __ orq(RDI, Immediate(RawObject::ClassIdTag::encode(cid))); |
630 __ movq(FieldAddress(RAX, Array::tags_offset()), RDI); // Tags. | 630 __ movq(FieldAddress(RAX, Array::tags_offset()), RDI); // Tags. |
631 } | 631 } |
632 | 632 |
633 // RAX: new object start as a tagged pointer. | 633 // RAX: new object start as a tagged pointer. |
634 // Store the type argument field. | 634 // Store the type argument field. |
635 __ StoreIntoObjectNoBarrier(RAX, | 635 __ InitializeFieldNoBarrier(RAX, |
636 FieldAddress(RAX, Array::type_arguments_offset()), | 636 FieldAddress(RAX, Array::type_arguments_offset()), |
637 RBX); | 637 RBX); |
638 | 638 |
639 // Set the length field. | 639 // Set the length field. |
640 __ StoreIntoObjectNoBarrier(RAX, | 640 __ InitializeFieldNoBarrier(RAX, |
641 FieldAddress(RAX, Array::length_offset()), | 641 FieldAddress(RAX, Array::length_offset()), |
642 R10); | 642 R10); |
643 | 643 |
644 // Initialize all array elements to raw_null. | 644 // Initialize all array elements to raw_null. |
645 // RAX: new object start as a tagged pointer. | 645 // RAX: new object start as a tagged pointer. |
646 // RCX: new object end address. | 646 // RCX: new object end address. |
647 // RDI: iterator which initially points to the start of the variable | 647 // RDI: iterator which initially points to the start of the variable |
648 // data area to be initialized. | 648 // data area to be initialized. |
649 __ LoadObject(R12, Object::null_object(), PP); | 649 __ LoadObject(R12, Object::null_object(), PP); |
650 __ leaq(RDI, FieldAddress(RAX, sizeof(RawArray))); | 650 __ leaq(RDI, FieldAddress(RAX, sizeof(RawArray))); |
651 Label done; | 651 Label done; |
652 Label init_loop; | 652 Label init_loop; |
653 __ Bind(&init_loop); | 653 __ Bind(&init_loop); |
654 __ cmpq(RDI, RCX); | 654 __ cmpq(RDI, RCX); |
655 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump); | 655 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump); |
656 // No generational barrier needed, since we are storing null. | 656 // No generational barrier needed, since we are storing null. |
657 __ StoreIntoObjectNoBarrier(RAX, Address(RDI, 0), R12); | 657 __ InitializeFieldNoBarrier(RAX, Address(RDI, 0), R12); |
658 __ addq(RDI, Immediate(kWordSize)); | 658 __ addq(RDI, Immediate(kWordSize)); |
659 __ jmp(&init_loop, Assembler::kNearJump); | 659 __ jmp(&init_loop, Assembler::kNearJump); |
660 __ Bind(&done); | 660 __ Bind(&done); |
661 __ ret(); // returns the newly allocated object in RAX. | 661 __ ret(); // returns the newly allocated object in RAX. |
662 | 662 |
663 // Unable to allocate the array using the fast inline code, just call | 663 // Unable to allocate the array using the fast inline code, just call |
664 // into the runtime. | 664 // into the runtime. |
665 __ Bind(&slow_case); | 665 __ Bind(&slow_case); |
666 // Create a stub frame as we are pushing some objects on the stack before | 666 // Create a stub frame as we are pushing some objects on the stack before |
667 // calling into the runtime. | 667 // calling into the runtime. |
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
881 | 881 |
882 // Setup up number of context variables field. | 882 // Setup up number of context variables field. |
883 // RAX: new object. | 883 // RAX: new object. |
884 // R10: number of context variables as integer value (not object). | 884 // R10: number of context variables as integer value (not object). |
885 __ movq(FieldAddress(RAX, Context::num_variables_offset()), R10); | 885 __ movq(FieldAddress(RAX, Context::num_variables_offset()), R10); |
886 | 886 |
887 // Setup the parent field. | 887 // Setup the parent field. |
888 // RAX: new object. | 888 // RAX: new object. |
889 // R10: number of context variables. | 889 // R10: number of context variables. |
890 // No generational barrier needed, since we are storing null. | 890 // No generational barrier needed, since we are storing null. |
891 __ StoreIntoObjectNoBarrier(RAX, | 891 __ InitializeFieldNoBarrier(RAX, |
892 FieldAddress(RAX, Context::parent_offset()), | 892 FieldAddress(RAX, Context::parent_offset()), |
893 R12); | 893 R12); |
894 | 894 |
895 // Initialize the context variables. | 895 // Initialize the context variables. |
896 // RAX: new object. | 896 // RAX: new object. |
897 // R10: number of context variables. | 897 // R10: number of context variables. |
898 { | 898 { |
899 Label loop, entry; | 899 Label loop, entry; |
900 __ leaq(R13, FieldAddress(RAX, Context::variable_offset(0))); | 900 __ leaq(R13, FieldAddress(RAX, Context::variable_offset(0))); |
901 | 901 #if defined(DEBUG) |
902 __ jmp(&entry, Assembler::kNearJump); | 902 static const bool kJumpLength = Assembler::kFarJump; |
| 903 #else |
| 904 static const bool kJumpLength = Assembler::kNearJump; |
| 905 #endif // DEBUG |
| 906 __ jmp(&entry, kJumpLength); |
903 __ Bind(&loop); | 907 __ Bind(&loop); |
904 __ decq(R10); | 908 __ decq(R10); |
905 // No generational barrier needed, since we are storing null. | 909 // No generational barrier needed, since we are storing null. |
906 __ StoreIntoObjectNoBarrier(RAX, | 910 __ InitializeFieldNoBarrier(RAX, |
907 Address(R13, R10, TIMES_8, 0), | 911 Address(R13, R10, TIMES_8, 0), |
908 R12); | 912 R12); |
909 __ Bind(&entry); | 913 __ Bind(&entry); |
910 __ cmpq(R10, Immediate(0)); | 914 __ cmpq(R10, Immediate(0)); |
911 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); | 915 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); |
912 } | 916 } |
913 | 917 |
914 // Done allocating and initializing the context. | 918 // Done allocating and initializing the context. |
915 // RAX: new object. | 919 // RAX: new object. |
916 __ ret(); | 920 __ ret(); |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1070 // RBX: next object start. | 1074 // RBX: next object start. |
1071 // RDX: new object type arguments (if is_cls_parameterized). | 1075 // RDX: new object type arguments (if is_cls_parameterized). |
1072 // R12: raw null. | 1076 // R12: raw null. |
1073 // First try inlining the initialization without a loop. | 1077 // First try inlining the initialization without a loop. |
1074 if (instance_size < (kInlineInstanceSize * kWordSize)) { | 1078 if (instance_size < (kInlineInstanceSize * kWordSize)) { |
1075 // Check if the object contains any non-header fields. | 1079 // Check if the object contains any non-header fields. |
1076 // Small objects are initialized using a consecutive set of writes. | 1080 // Small objects are initialized using a consecutive set of writes. |
1077 for (intptr_t current_offset = Instance::NextFieldOffset(); | 1081 for (intptr_t current_offset = Instance::NextFieldOffset(); |
1078 current_offset < instance_size; | 1082 current_offset < instance_size; |
1079 current_offset += kWordSize) { | 1083 current_offset += kWordSize) { |
1080 __ StoreIntoObjectNoBarrier(RAX, | 1084 __ InitializeFieldNoBarrier(RAX, |
1081 FieldAddress(RAX, current_offset), | 1085 FieldAddress(RAX, current_offset), |
1082 R12); | 1086 R12); |
1083 } | 1087 } |
1084 } else { | 1088 } else { |
1085 __ leaq(RCX, FieldAddress(RAX, Instance::NextFieldOffset())); | 1089 __ leaq(RCX, FieldAddress(RAX, Instance::NextFieldOffset())); |
1086 // Loop until the whole object is initialized. | 1090 // Loop until the whole object is initialized. |
1087 // RAX: new object (tagged). | 1091 // RAX: new object (tagged). |
1088 // RBX: next object start. | 1092 // RBX: next object start. |
1089 // RCX: next word to be initialized. | 1093 // RCX: next word to be initialized. |
1090 // RDX: new object type arguments (if is_cls_parameterized). | 1094 // RDX: new object type arguments (if is_cls_parameterized). |
1091 Label init_loop; | 1095 Label init_loop; |
1092 Label done; | 1096 Label done; |
1093 __ Bind(&init_loop); | 1097 __ Bind(&init_loop); |
1094 __ cmpq(RCX, RBX); | 1098 __ cmpq(RCX, RBX); |
1095 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump); | 1099 __ j(ABOVE_EQUAL, &done, Assembler::kNearJump); |
1096 __ StoreIntoObjectNoBarrier(RAX, Address(RCX, 0), R12); | 1100 __ InitializeFieldNoBarrier(RAX, Address(RCX, 0), R12); |
1097 __ addq(RCX, Immediate(kWordSize)); | 1101 __ addq(RCX, Immediate(kWordSize)); |
1098 __ jmp(&init_loop, Assembler::kNearJump); | 1102 __ jmp(&init_loop, Assembler::kNearJump); |
1099 __ Bind(&done); | 1103 __ Bind(&done); |
1100 } | 1104 } |
1101 if (is_cls_parameterized) { | 1105 if (is_cls_parameterized) { |
1102 // RDX: new object type arguments. | 1106 // RDX: new object type arguments. |
1103 // Set the type arguments in the new object. | 1107 // Set the type arguments in the new object. |
1104 intptr_t offset = cls.type_arguments_field_offset(); | 1108 intptr_t offset = cls.type_arguments_field_offset(); |
1105 __ StoreIntoObjectNoBarrier(RAX, FieldAddress(RAX, offset), RDX); | 1109 __ InitializeFieldNoBarrier(RAX, FieldAddress(RAX, offset), RDX); |
1106 } | 1110 } |
1107 // Done allocating and initializing the instance. | 1111 // Done allocating and initializing the instance. |
1108 // RAX: new object (tagged). | 1112 // RAX: new object (tagged). |
1109 __ ret(); | 1113 __ ret(); |
1110 | 1114 |
1111 __ Bind(&slow_case); | 1115 __ Bind(&slow_case); |
1112 } | 1116 } |
1113 // If is_cls_parameterized: | 1117 // If is_cls_parameterized: |
1114 // RDX: new object type arguments. | 1118 // RDX: new object type arguments. |
1115 // Create a stub frame. | 1119 // Create a stub frame. |
(...skipping 507 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1623 __ Stop("Incorrect IC data for unoptimized static call"); | 1627 __ Stop("Incorrect IC data for unoptimized static call"); |
1624 __ Bind(&ok); | 1628 __ Bind(&ok); |
1625 } | 1629 } |
1626 #endif // DEBUG | 1630 #endif // DEBUG |
1627 | 1631 |
1628 // Check single stepping. | 1632 // Check single stepping. |
1629 Label stepping, done_stepping; | 1633 Label stepping, done_stepping; |
1630 __ LoadIsolate(RAX); | 1634 __ LoadIsolate(RAX); |
1631 __ movzxb(RAX, Address(RAX, Isolate::single_step_offset())); | 1635 __ movzxb(RAX, Address(RAX, Isolate::single_step_offset())); |
1632 __ cmpq(RAX, Immediate(0)); | 1636 __ cmpq(RAX, Immediate(0)); |
1633 __ j(NOT_EQUAL, &stepping, Assembler::kNearJump); | 1637 #if defined(DEBUG) |
| 1638 static const bool kJumpLength = Assembler::kFarJump; |
| 1639 #else |
| 1640 static const bool kJumpLength = Assembler::kNearJump; |
| 1641 #endif // DEBUG |
| 1642 __ j(NOT_EQUAL, &stepping, kJumpLength); |
1634 __ Bind(&done_stepping); | 1643 __ Bind(&done_stepping); |
1635 | 1644 |
1636 // RBX: IC data object (preserved). | 1645 // RBX: IC data object (preserved). |
1637 __ movq(R12, FieldAddress(RBX, ICData::ic_data_offset())); | 1646 __ movq(R12, FieldAddress(RBX, ICData::ic_data_offset())); |
1638 // R12: ic_data_array with entries: target functions and count. | 1647 // R12: ic_data_array with entries: target functions and count. |
1639 __ leaq(R12, FieldAddress(R12, Array::data_offset())); | 1648 __ leaq(R12, FieldAddress(R12, Array::data_offset())); |
1640 // R12: points directly to the first ic data array element. | 1649 // R12: points directly to the first ic data array element. |
1641 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize; | 1650 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize; |
1642 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; | 1651 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; |
1643 | 1652 |
(...skipping 425 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2069 | 2078 |
2070 __ movq(left, Address(RSP, 2 * kWordSize)); | 2079 __ movq(left, Address(RSP, 2 * kWordSize)); |
2071 __ movq(right, Address(RSP, 1 * kWordSize)); | 2080 __ movq(right, Address(RSP, 1 * kWordSize)); |
2072 GenerateIdenticalWithNumberCheckStub(assembler, left, right); | 2081 GenerateIdenticalWithNumberCheckStub(assembler, left, right); |
2073 __ ret(); | 2082 __ ret(); |
2074 } | 2083 } |
2075 | 2084 |
2076 } // namespace dart | 2085 } // namespace dart |
2077 | 2086 |
2078 #endif // defined TARGET_ARCH_X64 | 2087 #endif // defined TARGET_ARCH_X64 |
OLD | NEW |