| 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 |