| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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_ARM64) | 6 #if defined(TARGET_ARCH_ARM64) |
| 7 | 7 |
| 8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
| 9 #include "vm/code_generator.h" | 9 #include "vm/code_generator.h" |
| 10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
| (...skipping 639 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 650 // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)). | 650 // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)). |
| 651 // Assert that length is a Smi. | 651 // Assert that length is a Smi. |
| 652 __ tsti(R2, kSmiTagMask); | 652 __ tsti(R2, kSmiTagMask); |
| 653 if (FLAG_use_slow_path) { | 653 if (FLAG_use_slow_path) { |
| 654 __ b(&slow_case); | 654 __ b(&slow_case); |
| 655 } else { | 655 } else { |
| 656 __ b(&slow_case, NE); | 656 __ b(&slow_case, NE); |
| 657 } | 657 } |
| 658 __ cmp(R2, Operand(0)); | 658 __ cmp(R2, Operand(0)); |
| 659 __ b(&slow_case, LT); | 659 __ b(&slow_case, LT); |
| 660 __ LoadFieldFromOffset(R8, CTX, Context::isolate_offset(), kNoPP); | 660 __ LoadImmediate(R8, Isolate::CurrentAddress(), kNoPP); |
| 661 __ LoadFromOffset(R8, R8, Isolate::heap_offset(), kNoPP); | 661 __ LoadFromOffset(R8, R8, Isolate::heap_offset(), kNoPP); |
| 662 __ LoadFromOffset(R8, R8, Heap::new_space_offset(), kNoPP); | 662 __ LoadFromOffset(R8, R8, Heap::new_space_offset(), kNoPP); |
| 663 | 663 |
| 664 // Calculate and align allocation size. | 664 // Calculate and align allocation size. |
| 665 // Load new object start and calculate next object start. | 665 // Load new object start and calculate next object start. |
| 666 // R1: array element type. | 666 // R1: array element type. |
| 667 // R2: array length as Smi. | 667 // R2: array length as Smi. |
| 668 // R8: points to new space object. | 668 // R8: points to new space object. |
| 669 __ LoadFromOffset(R0, R8, Scavenger::top_offset(), kNoPP); | 669 __ LoadFromOffset(R0, R8, Scavenger::top_offset(), kNoPP); |
| 670 intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1; | 670 intptr_t fixed_size = sizeof(RawArray) + kObjectAlignment - 1; |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 817 | 817 |
| 818 // The new Context structure contains a pointer to the current Isolate | 818 // The new Context structure contains a pointer to the current Isolate |
| 819 // structure. Cache the Context pointer in the CTX register so that it is | 819 // structure. Cache the Context pointer in the CTX register so that it is |
| 820 // available in generated code and calls to Isolate::Current() need not be | 820 // available in generated code and calls to Isolate::Current() need not be |
| 821 // done. The assumption is that this register will never be clobbered by | 821 // done. The assumption is that this register will never be clobbered by |
| 822 // compiled or runtime stub code. | 822 // compiled or runtime stub code. |
| 823 | 823 |
| 824 // Cache the new Context pointer into CTX while executing Dart code. | 824 // Cache the new Context pointer into CTX while executing Dart code. |
| 825 __ LoadFromOffset(CTX, R3, VMHandles::kOffsetOfRawPtrInHandle, PP); | 825 __ LoadFromOffset(CTX, R3, VMHandles::kOffsetOfRawPtrInHandle, PP); |
| 826 | 826 |
| 827 // Load Isolate pointer from Context structure into temporary register R5. | 827 // Load Isolate pointer into temporary register R5. |
| 828 __ LoadFieldFromOffset(R5, CTX, Context::isolate_offset(), PP); | 828 __ LoadImmediate(R5, Isolate::CurrentAddress(), PP); |
| 829 | 829 |
| 830 // Load the stack limit address into the C stack pointer register. | 830 // Load the stack limit address into the C stack pointer register. |
| 831 __ LoadFromOffset(CSP, R5, Isolate::stack_limit_offset(), PP); | 831 __ LoadFromOffset(CSP, R5, Isolate::stack_limit_offset(), PP); |
| 832 | 832 |
| 833 // Cache the new Context pointer into CTX while executing Dart code. | 833 // Cache the new Context pointer into CTX while executing Dart code. |
| 834 __ LoadFromOffset(CTX, R3, VMHandles::kOffsetOfRawPtrInHandle, PP); | 834 __ LoadFromOffset(CTX, R3, VMHandles::kOffsetOfRawPtrInHandle, PP); |
| 835 | 835 |
| 836 // Save the current VMTag on the stack. | 836 // Save the current VMTag on the stack. |
| 837 ASSERT(kSavedVMTagSlotFromEntryFp == -20); | 837 ASSERT(kSavedVMTagSlotFromEntryFp == -20); |
| 838 __ LoadFromOffset(R4, R5, Isolate::vm_tag_offset(), PP); | 838 __ LoadFromOffset(R4, R5, Isolate::vm_tag_offset(), PP); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 884 __ add(R1, R1, Operand(1)); | 884 __ add(R1, R1, Operand(1)); |
| 885 __ add(R2, R2, Operand(kWordSize)); | 885 __ add(R2, R2, Operand(kWordSize)); |
| 886 __ cmp(R1, Operand(R5)); | 886 __ cmp(R1, Operand(R5)); |
| 887 __ b(&push_arguments, LT); | 887 __ b(&push_arguments, LT); |
| 888 __ Bind(&done_push_arguments); | 888 __ Bind(&done_push_arguments); |
| 889 | 889 |
| 890 // Call the Dart code entrypoint. | 890 // Call the Dart code entrypoint. |
| 891 __ blr(R0); // R4 is the arguments descriptor array. | 891 __ blr(R0); // R4 is the arguments descriptor array. |
| 892 __ Comment("InvokeDartCodeStub return"); | 892 __ Comment("InvokeDartCodeStub return"); |
| 893 | 893 |
| 894 // Restore constant pool pointer after return. |
| 895 __ LoadPoolPointer(PP); |
| 896 |
| 894 // Read the saved new Context pointer. | 897 // Read the saved new Context pointer. |
| 895 __ LoadFromOffset(CTX, FP, kNewContextOffsetFromFp, PP); | 898 __ LoadFromOffset(CTX, FP, kNewContextOffsetFromFp, PP); |
| 896 __ LoadFromOffset(CTX, CTX, VMHandles::kOffsetOfRawPtrInHandle, PP); | 899 __ LoadFromOffset(CTX, CTX, VMHandles::kOffsetOfRawPtrInHandle, PP); |
| 897 | 900 |
| 898 // Get rid of arguments pushed on the stack. | 901 // Get rid of arguments pushed on the stack. |
| 899 __ AddImmediate(SP, FP, kSavedContextSlotFromEntryFp * kWordSize, PP); | 902 __ AddImmediate(SP, FP, kSavedContextSlotFromEntryFp * kWordSize, PP); |
| 900 | 903 |
| 901 // Load Isolate pointer from Context structure into CTX. Drop Context. | 904 // Load Isolate pointer into CTX. Drop Context. |
| 902 __ LoadFieldFromOffset(CTX, CTX, Context::isolate_offset(), PP); | 905 __ LoadImmediate(CTX, Isolate::CurrentAddress(), PP); |
| 903 | 906 |
| 904 // Restore the current VMTag from the stack. | 907 // Restore the current VMTag from the stack. |
| 905 __ ldr(R4, Address(SP, 2 * kWordSize)); | 908 __ ldr(R4, Address(SP, 2 * kWordSize)); |
| 906 __ StoreToOffset(R4, CTX, Isolate::vm_tag_offset(), PP); | 909 __ StoreToOffset(R4, CTX, Isolate::vm_tag_offset(), PP); |
| 907 | 910 |
| 908 // Restore the saved Context pointer into the Isolate structure. | 911 // Restore the saved Context pointer into the Isolate structure. |
| 909 // Uses R4 as a temporary register for this. | 912 // Uses R4 as a temporary register for this. |
| 910 // Restore the saved top exit frame info back into the Isolate structure. | 913 // Restore the saved top exit frame info back into the Isolate structure. |
| 911 // Uses R6 as a temporary register for this. | 914 // Uses R6 as a temporary register for this. |
| 912 __ Pop(R4); | 915 __ Pop(R4); |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1005 TMP, RawObject::ClassIdTag::encode(context_class.id()), kNoPP); | 1008 TMP, RawObject::ClassIdTag::encode(context_class.id()), kNoPP); |
| 1006 __ orr(R2, R2, Operand(TMP)); | 1009 __ orr(R2, R2, Operand(TMP)); |
| 1007 __ StoreFieldToOffset(R2, R0, Context::tags_offset(), kNoPP); | 1010 __ StoreFieldToOffset(R2, R0, Context::tags_offset(), kNoPP); |
| 1008 | 1011 |
| 1009 // Setup up number of context variables field. | 1012 // Setup up number of context variables field. |
| 1010 // R0: new object. | 1013 // R0: new object. |
| 1011 // R1: number of context variables as integer value (not object). | 1014 // R1: number of context variables as integer value (not object). |
| 1012 __ StoreFieldToOffset(R1, R0, Context::num_variables_offset(), kNoPP); | 1015 __ StoreFieldToOffset(R1, R0, Context::num_variables_offset(), kNoPP); |
| 1013 | 1016 |
| 1014 // Setup isolate field. | 1017 // Setup isolate field. |
| 1015 // Load Isolate pointer from Context structure into R2. | 1018 // Load Isolate pointer into R2. |
| 1016 // R0: new object. | 1019 // R0: new object. |
| 1017 // R1: number of context variables. | 1020 // R1: number of context variables. |
| 1018 __ LoadFieldFromOffset(R2, CTX, Context::isolate_offset(), kNoPP); | 1021 __ LoadImmediate(R2, Isolate::CurrentAddress(), kNoPP); |
| 1019 // R2: isolate, not an object. | 1022 // R2: isolate, not an object. |
| 1020 __ StoreFieldToOffset(R2, R0, Context::isolate_offset(), kNoPP); | 1023 __ StoreFieldToOffset(R2, R0, Context::isolate_offset(), kNoPP); |
| 1021 | 1024 |
| 1022 // Setup the parent field. | 1025 // Setup the parent field. |
| 1023 // R0: new object. | 1026 // R0: new object. |
| 1024 // R1: number of context variables. | 1027 // R1: number of context variables. |
| 1025 __ LoadObject(R2, Object::null_object(), PP); | 1028 __ LoadObject(R2, Object::null_object(), PP); |
| 1026 __ StoreFieldToOffset(R2, R0, Context::parent_offset(), kNoPP); | 1029 __ StoreFieldToOffset(R2, R0, Context::parent_offset(), kNoPP); |
| 1027 | 1030 |
| 1028 // Initialize the context variables. | 1031 // Initialize the context variables. |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1078 | 1081 |
| 1079 __ Bind(&add_to_buffer); | 1082 __ Bind(&add_to_buffer); |
| 1080 // Save values being destroyed. | 1083 // Save values being destroyed. |
| 1081 __ Push(R1); | 1084 __ Push(R1); |
| 1082 __ Push(R2); | 1085 __ Push(R2); |
| 1083 __ Push(R3); | 1086 __ Push(R3); |
| 1084 | 1087 |
| 1085 __ orri(R2, TMP, 1 << RawObject::kRememberedBit); | 1088 __ orri(R2, TMP, 1 << RawObject::kRememberedBit); |
| 1086 __ StoreFieldToOffset(R2, R0, Object::tags_offset(), kNoPP); | 1089 __ StoreFieldToOffset(R2, R0, Object::tags_offset(), kNoPP); |
| 1087 | 1090 |
| 1088 // Load the isolate out of the context. | 1091 // Load the isolate. |
| 1089 // Spilled: R1, R2, R3. | 1092 // Spilled: R1, R2, R3. |
| 1090 // R0: address being stored. | 1093 // R0: address being stored. |
| 1091 __ LoadFieldFromOffset(R1, CTX, Context::isolate_offset(), kNoPP); | 1094 __ LoadImmediate(R1, Isolate::CurrentAddress(), kNoPP); |
| 1092 | 1095 |
| 1093 // Load the StoreBuffer block out of the isolate. Then load top_ out of the | 1096 // Load the StoreBuffer block out of the isolate. Then load top_ out of the |
| 1094 // StoreBufferBlock and add the address to the pointers_. | 1097 // StoreBufferBlock and add the address to the pointers_. |
| 1095 // R1: isolate. | 1098 // R1: isolate. |
| 1096 __ LoadFromOffset(R1, R1, Isolate::store_buffer_offset(), kNoPP); | 1099 __ LoadFromOffset(R1, R1, Isolate::store_buffer_offset(), kNoPP); |
| 1097 __ LoadFromOffset(R2, R1, StoreBufferBlock::top_offset(), | 1100 __ LoadFromOffset(R2, R1, StoreBufferBlock::top_offset(), |
| 1098 kNoPP, kUnsignedWord); | 1101 kNoPP, kUnsignedWord); |
| 1099 __ add(R3, R1, Operand(R2, LSL, 3)); | 1102 __ add(R3, R1, Operand(R2, LSL, 3)); |
| 1100 __ StoreToOffset(R0, R3, StoreBufferBlock::pointers_offset(), kNoPP); | 1103 __ StoreToOffset(R0, R3, StoreBufferBlock::pointers_offset(), kNoPP); |
| 1101 | 1104 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1112 __ Pop(R2); | 1115 __ Pop(R2); |
| 1113 __ Pop(R1); | 1116 __ Pop(R1); |
| 1114 __ b(&L, EQ); | 1117 __ b(&L, EQ); |
| 1115 __ ret(); | 1118 __ ret(); |
| 1116 | 1119 |
| 1117 // Handle overflow: Call the runtime leaf function. | 1120 // Handle overflow: Call the runtime leaf function. |
| 1118 __ Bind(&L); | 1121 __ Bind(&L); |
| 1119 // Setup frame, push callee-saved registers. | 1122 // Setup frame, push callee-saved registers. |
| 1120 | 1123 |
| 1121 __ EnterCallRuntimeFrame(0 * kWordSize); | 1124 __ EnterCallRuntimeFrame(0 * kWordSize); |
| 1122 __ LoadFieldFromOffset(R0, CTX, Context::isolate_offset(), kNoPP); | 1125 __ LoadImmediate(R0, Isolate::CurrentAddress(), kNoPP); |
| 1123 __ CallRuntime(kStoreBufferBlockProcessRuntimeEntry, 1); | 1126 __ CallRuntime(kStoreBufferBlockProcessRuntimeEntry, 1); |
| 1124 // Restore callee-saved registers, tear down frame. | 1127 // Restore callee-saved registers, tear down frame. |
| 1125 __ LeaveCallRuntimeFrame(); | 1128 __ LeaveCallRuntimeFrame(); |
| 1126 __ ret(); | 1129 __ ret(); |
| 1127 } | 1130 } |
| 1128 | 1131 |
| 1129 | 1132 |
| 1130 // Called for inline allocation of objects. | 1133 // Called for inline allocation of objects. |
| 1131 // Input parameters: | 1134 // Input parameters: |
| 1132 // LR : return address. | 1135 // LR : return address. |
| (...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1425 kNoPP, kUnsignedWord); | 1428 kNoPP, kUnsignedWord); |
| 1426 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. | 1429 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. |
| 1427 __ andi(R6, R6, ICData::NumArgsTestedMask()); | 1430 __ andi(R6, R6, ICData::NumArgsTestedMask()); |
| 1428 __ CompareImmediate(R6, num_args, kNoPP); | 1431 __ CompareImmediate(R6, num_args, kNoPP); |
| 1429 __ b(&ok, EQ); | 1432 __ b(&ok, EQ); |
| 1430 __ Stop("Incorrect stub for IC data"); | 1433 __ Stop("Incorrect stub for IC data"); |
| 1431 __ Bind(&ok); | 1434 __ Bind(&ok); |
| 1432 } | 1435 } |
| 1433 #endif // DEBUG | 1436 #endif // DEBUG |
| 1434 | 1437 |
| 1438 // Check single stepping. |
| 1435 Label stepping, done_stepping; | 1439 Label stepping, done_stepping; |
| 1436 // Check single stepping. | 1440 __ LoadImmediate(R6, Isolate::CurrentAddress(), kNoPP); |
| 1437 __ LoadFieldFromOffset(R6, CTX, Context::isolate_offset(), kNoPP); | |
| 1438 __ LoadFromOffset( | 1441 __ LoadFromOffset( |
| 1439 R6, R6, Isolate::single_step_offset(), kNoPP, kUnsignedByte); | 1442 R6, R6, Isolate::single_step_offset(), kNoPP, kUnsignedByte); |
| 1440 __ CompareRegisters(R6, ZR); | 1443 __ CompareRegisters(R6, ZR); |
| 1441 __ b(&stepping, NE); | 1444 __ b(&stepping, NE); |
| 1442 __ Bind(&done_stepping); | 1445 __ Bind(&done_stepping); |
| 1443 | 1446 |
| 1444 if (kind != Token::kILLEGAL) { | 1447 if (kind != Token::kILLEGAL) { |
| 1445 Label not_smi_or_overflow; | 1448 Label not_smi_or_overflow; |
| 1446 EmitFastSmiOp(assembler, kind, num_args, ¬_smi_or_overflow); | 1449 EmitFastSmiOp(assembler, kind, num_args, ¬_smi_or_overflow); |
| 1447 __ Bind(¬_smi_or_overflow); | 1450 __ Bind(¬_smi_or_overflow); |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1659 __ andi(R6, R6, ICData::NumArgsTestedMask()); | 1662 __ andi(R6, R6, ICData::NumArgsTestedMask()); |
| 1660 __ CompareImmediate(R6, 0, kNoPP); | 1663 __ CompareImmediate(R6, 0, kNoPP); |
| 1661 __ b(&ok, EQ); | 1664 __ b(&ok, EQ); |
| 1662 __ Stop("Incorrect IC data for unoptimized static call"); | 1665 __ Stop("Incorrect IC data for unoptimized static call"); |
| 1663 __ Bind(&ok); | 1666 __ Bind(&ok); |
| 1664 } | 1667 } |
| 1665 #endif // DEBUG | 1668 #endif // DEBUG |
| 1666 | 1669 |
| 1667 // Check single stepping. | 1670 // Check single stepping. |
| 1668 Label stepping, done_stepping; | 1671 Label stepping, done_stepping; |
| 1669 __ LoadFieldFromOffset(R6, CTX, Context::isolate_offset(), kNoPP); | 1672 __ LoadImmediate(R6, Isolate::CurrentAddress(), kNoPP); |
| 1670 __ LoadFromOffset( | 1673 __ LoadFromOffset( |
| 1671 R6, R6, Isolate::single_step_offset(), kNoPP, kUnsignedByte); | 1674 R6, R6, Isolate::single_step_offset(), kNoPP, kUnsignedByte); |
| 1672 __ CompareImmediate(R6, 0, kNoPP); | 1675 __ CompareImmediate(R6, 0, kNoPP); |
| 1673 __ b(&stepping, NE); | 1676 __ b(&stepping, NE); |
| 1674 __ Bind(&done_stepping); | 1677 __ Bind(&done_stepping); |
| 1675 | 1678 |
| 1676 // R5: IC data object (preserved). | 1679 // R5: IC data object (preserved). |
| 1677 __ LoadFieldFromOffset(R6, R5, ICData::ic_data_offset(), kNoPP); | 1680 __ LoadFieldFromOffset(R6, R5, ICData::ic_data_offset(), kNoPP); |
| 1678 // R6: ic_data_array with entries: target functions and count. | 1681 // R6: ic_data_array with entries: target functions and count. |
| 1679 __ AddImmediate(R6, R6, Array::data_offset() - kHeapObjectTag, kNoPP); | 1682 __ AddImmediate(R6, R6, Array::data_offset() - kHeapObjectTag, kNoPP); |
| (...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2035 } | 2038 } |
| 2036 | 2039 |
| 2037 | 2040 |
| 2038 // Called only from unoptimized code. All relevant registers have been saved. | 2041 // Called only from unoptimized code. All relevant registers have been saved. |
| 2039 // LR: return address. | 2042 // LR: return address. |
| 2040 // SP + 4: left operand. | 2043 // SP + 4: left operand. |
| 2041 // SP + 0: right operand. | 2044 // SP + 0: right operand. |
| 2042 // Return Zero condition flag set if equal. | 2045 // Return Zero condition flag set if equal. |
| 2043 void StubCode::GenerateUnoptimizedIdenticalWithNumberCheckStub( | 2046 void StubCode::GenerateUnoptimizedIdenticalWithNumberCheckStub( |
| 2044 Assembler* assembler) { | 2047 Assembler* assembler) { |
| 2045 // Check single stepping. | 2048 // Check single stepping. |
| 2046 Label stepping, done_stepping; | 2049 Label stepping, done_stepping; |
| 2047 __ LoadFieldFromOffset(R1, CTX, Context::isolate_offset(), kNoPP); | 2050 __ LoadFieldFromOffset(R1, CTX, Context::isolate_offset(), kNoPP); |
| 2048 __ LoadFromOffset( | 2051 __ LoadFromOffset( |
| 2049 R1, R1, Isolate::single_step_offset(), kNoPP, kUnsignedByte); | 2052 R1, R1, Isolate::single_step_offset(), kNoPP, kUnsignedByte); |
| 2050 __ CompareImmediate(R1, 0, kNoPP); | 2053 __ CompareImmediate(R1, 0, kNoPP); |
| 2051 __ b(&stepping, NE); | 2054 __ b(&stepping, NE); |
| 2052 __ Bind(&done_stepping); | 2055 __ Bind(&done_stepping); |
| 2053 | 2056 |
| 2054 const Register left = R1; | 2057 const Register left = R1; |
| 2055 const Register right = R0; | 2058 const Register right = R0; |
| (...skipping 22 matching lines...) Expand all Loading... |
| 2078 const Register right = R0; | 2081 const Register right = R0; |
| 2079 __ LoadFromOffset(left, SP, 1 * kWordSize, kNoPP); | 2082 __ LoadFromOffset(left, SP, 1 * kWordSize, kNoPP); |
| 2080 __ LoadFromOffset(right, SP, 0 * kWordSize, kNoPP); | 2083 __ LoadFromOffset(right, SP, 0 * kWordSize, kNoPP); |
| 2081 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); | 2084 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); |
| 2082 __ ret(); | 2085 __ ret(); |
| 2083 } | 2086 } |
| 2084 | 2087 |
| 2085 } // namespace dart | 2088 } // namespace dart |
| 2086 | 2089 |
| 2087 #endif // defined TARGET_ARCH_ARM64 | 2090 #endif // defined TARGET_ARCH_ARM64 |
| OLD | NEW |