Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(131)

Side by Side Diff: runtime/vm/assembler_arm64.cc

Issue 1192103004: VM: New calling convention for generated code. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: fixed comments Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/assembler_arm64.h ('k') | runtime/vm/assembler_arm64_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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" // NOLINT 5 #include "vm/globals.h" // NOLINT
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/cpu.h" 9 #include "vm/cpu.h"
10 #include "vm/longjump.h" 10 #include "vm/longjump.h"
(...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after
297 continue; 297 continue;
298 } 298 }
299 299
300 // 6. Otherwise, the value can't be encoded. 300 // 6. Otherwise, the value can't be encoded.
301 return false; 301 return false;
302 } 302 }
303 } 303 }
304 304
305 305
306 void Assembler::LoadPoolPointer(Register pp) { 306 void Assembler::LoadPoolPointer(Register pp) {
307 const intptr_t object_pool_pc_dist = 307 CheckCodePointer();
308 Instructions::HeaderSize() - Instructions::object_pool_offset() + 308 ldr(pp, FieldAddress(CODE_REG, Code::object_pool_offset()));
309 CodeSize();
310 // PP <- Read(PC - object_pool_pc_dist).
311 ldr(pp, Address::PC(-object_pool_pc_dist));
312 309
313 // When in the PP register, the pool pointer is untagged. When we 310 // When in the PP register, the pool pointer is untagged. When we
314 // push it on the stack with TagAndPushPP it is tagged again. PopAndUntagPP 311 // push it on the stack with TagAndPushPP it is tagged again. PopAndUntagPP
315 // then untags when restoring from the stack. This will make loading from the 312 // then untags when restoring from the stack. This will make loading from the
316 // object pool only one instruction for the first 4096 entries. Otherwise, 313 // object pool only one instruction for the first 4096 entries. Otherwise,
317 // because the offset wouldn't be aligned, it would be only one instruction 314 // because the offset wouldn't be aligned, it would be only one instruction
318 // for the first 64 entries. 315 // for the first 64 entries.
319 sub(pp, pp, Operand(kHeapObjectTag)); 316 sub(pp, pp, Operand(kHeapObjectTag));
320 set_constant_pool_allowed(pp == PP); 317 set_constant_pool_allowed(pp == PP);
321 } 318 }
322 319
323 320
324 void Assembler::LoadWordFromPoolOffset(Register dst, uint32_t offset) { 321 void Assembler::LoadWordFromPoolOffset(Register dst,
325 ASSERT(constant_pool_allowed()); 322 uint32_t offset,
326 ASSERT(dst != PP); 323 Register pp) {
324 ASSERT((pp != PP) || constant_pool_allowed());
325 ASSERT(dst != pp);
327 Operand op; 326 Operand op;
328 const uint32_t upper20 = offset & 0xfffff000; 327 const uint32_t upper20 = offset & 0xfffff000;
329 if (Address::CanHoldOffset(offset)) { 328 if (Address::CanHoldOffset(offset)) {
330 ldr(dst, Address(PP, offset)); 329 ldr(dst, Address(pp, offset));
331 } else if (Operand::CanHold(upper20, kXRegSizeInBits, &op) == 330 } else if (Operand::CanHold(upper20, kXRegSizeInBits, &op) ==
332 Operand::Immediate) { 331 Operand::Immediate) {
333 const uint32_t lower12 = offset & 0x00000fff; 332 const uint32_t lower12 = offset & 0x00000fff;
334 ASSERT(Address::CanHoldOffset(lower12)); 333 ASSERT(Address::CanHoldOffset(lower12));
335 add(dst, PP, op); 334 add(dst, pp, op);
336 ldr(dst, Address(dst, lower12)); 335 ldr(dst, Address(dst, lower12));
337 } else { 336 } else {
338 const uint16_t offset_low = Utils::Low16Bits(offset); 337 const uint16_t offset_low = Utils::Low16Bits(offset);
339 const uint16_t offset_high = Utils::High16Bits(offset); 338 const uint16_t offset_high = Utils::High16Bits(offset);
340 movz(dst, Immediate(offset_low), 0); 339 movz(dst, Immediate(offset_low), 0);
341 if (offset_high != 0) { 340 if (offset_high != 0) {
342 movk(dst, Immediate(offset_high), 1); 341 movk(dst, Immediate(offset_high), 1);
343 } 342 }
344 ldr(dst, Address(PP, dst)); 343 ldr(dst, Address(pp, dst));
345 } 344 }
346 } 345 }
347 346
348 347
349 void Assembler::LoadWordFromPoolOffsetFixed(Register dst, uint32_t offset) { 348 void Assembler::LoadWordFromPoolOffsetFixed(Register dst, uint32_t offset) {
350 ASSERT(constant_pool_allowed()); 349 ASSERT(constant_pool_allowed());
351 ASSERT(dst != PP); 350 ASSERT(dst != PP);
352 Operand op; 351 Operand op;
353 const uint32_t upper20 = offset & 0xfffff000; 352 const uint32_t upper20 = offset & 0xfffff000;
354 const uint32_t lower12 = offset & 0x00000fff; 353 const uint32_t lower12 = offset & 0x00000fff;
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after
588 587
589 void Assembler::LoadDImmediate(VRegister vd, double immd) { 588 void Assembler::LoadDImmediate(VRegister vd, double immd) {
590 if (!fmovdi(vd, immd)) { 589 if (!fmovdi(vd, immd)) {
591 int64_t imm = bit_cast<int64_t, double>(immd); 590 int64_t imm = bit_cast<int64_t, double>(immd);
592 LoadImmediate(TMP, imm); 591 LoadImmediate(TMP, imm);
593 fmovdr(vd, TMP); 592 fmovdr(vd, TMP);
594 } 593 }
595 } 594 }
596 595
597 596
598 void Assembler::Branch(const ExternalLabel* label) { 597 void Assembler::Branch(const StubEntry& stub_entry,
599 LoadExternalLabel(TMP, label); 598 Register pp,
600 br(TMP); 599 Patchability patchable) {
601 } 600 const Code& target = Code::Handle(stub_entry.code());
602 601 const int32_t offset = ObjectPool::element_offset(
603 602 object_pool_wrapper_.FindObject(target, patchable));
604 void Assembler::Branch(const StubEntry& stub_entry) { 603 LoadWordFromPoolOffset(CODE_REG, offset, pp);
605 const ExternalLabel label(stub_entry.EntryPoint()); 604 ldr(TMP, FieldAddress(CODE_REG, Code::entry_point_offset()));
606 Branch(&label);
607 }
608
609
610 void Assembler::BranchPatchable(const ExternalLabel* label) {
611 // TODO(zra): Use LoadExternalLabelFixed if possible.
612 LoadImmediateFixed(TMP, label->address());
613 br(TMP); 605 br(TMP);
614 } 606 }
615 607
616 void Assembler::BranchPatchable(const StubEntry& stub_entry) { 608 void Assembler::BranchPatchable(const StubEntry& stub_entry) {
617 BranchPatchable(&stub_entry.label()); 609 Branch(stub_entry, PP, kPatchable);
618 } 610 }
619 611
620 612
621 void Assembler::BranchLink(const ExternalLabel* label) { 613 void Assembler::BranchLink(const StubEntry& stub_entry,
622 LoadExternalLabel(TMP, label); 614 Patchability patchable) {
623 blr(TMP); 615 const Code& target = Code::Handle(stub_entry.code());
624 } 616 const int32_t offset = ObjectPool::element_offset(
625 617 object_pool_wrapper_.FindObject(target, patchable));
626 618 LoadWordFromPoolOffset(CODE_REG, offset);
627 void Assembler::BranchLink(const StubEntry& stub_entry) { 619 ldr(TMP, FieldAddress(CODE_REG, Code::entry_point_offset()));
628 BranchLink(&stub_entry.label());
629 }
630
631
632 void Assembler::BranchLinkPatchable(const ExternalLabel* label) {
633 LoadExternalLabelFixed(TMP, label, kPatchable);
634 blr(TMP); 620 blr(TMP);
635 } 621 }
636 622
637 623
638 void Assembler::BranchLinkPatchable(const StubEntry& stub_entry) { 624 void Assembler::BranchLinkPatchable(const StubEntry& stub_entry) {
639 BranchLinkPatchable(&stub_entry.label()); 625 BranchLink(stub_entry, kPatchable);
640 } 626 }
641 627
642 628
643 void Assembler::AddImmediate(Register dest, Register rn, int64_t imm) { 629 void Assembler::AddImmediate(Register dest, Register rn, int64_t imm) {
644 Operand op; 630 Operand op;
645 if (imm == 0) { 631 if (imm == 0) {
646 if (dest != rn) { 632 if (dest != rn) {
647 mov(dest, rn); 633 mov(dest, rn);
648 } 634 }
649 return; 635 return;
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after
919 } 905 }
920 // A store buffer update is required. 906 // A store buffer update is required.
921 if (value != R0) { 907 if (value != R0) {
922 // Preserve R0. 908 // Preserve R0.
923 Push(R0); 909 Push(R0);
924 } 910 }
925 Push(LR); 911 Push(LR);
926 if (object != R0) { 912 if (object != R0) {
927 mov(R0, object); 913 mov(R0, object);
928 } 914 }
915 ldr(CODE_REG, Address(THR, Thread::update_store_buffer_code_offset()));
929 ldr(TMP, Address(THR, Thread::update_store_buffer_entry_point_offset())); 916 ldr(TMP, Address(THR, Thread::update_store_buffer_entry_point_offset()));
930 blr(TMP); 917 blr(TMP);
931 Pop(LR); 918 Pop(LR);
932 if (value != R0) { 919 if (value != R0) {
933 // Restore R0. 920 // Restore R0.
934 Pop(R0); 921 Pop(R0);
935 } 922 }
936 Bind(&done); 923 Bind(&done);
937 } 924 }
938 925
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
1095 // the C++ world. 1082 // the C++ world.
1096 if (frame_space != 0) { 1083 if (frame_space != 0) {
1097 AddImmediate(SP, SP, -frame_space); 1084 AddImmediate(SP, SP, -frame_space);
1098 } 1085 }
1099 if (OS::ActivationFrameAlignment() > 1) { 1086 if (OS::ActivationFrameAlignment() > 1) {
1100 andi(SP, SP, Immediate(~(OS::ActivationFrameAlignment() - 1))); 1087 andi(SP, SP, Immediate(~(OS::ActivationFrameAlignment() - 1)));
1101 } 1088 }
1102 } 1089 }
1103 1090
1104 1091
1092 void Assembler::RestoreCodePointer() {
1093 ldr(CODE_REG, Address(FP, kPcMarkerSlotFromFp * kWordSize));
1094 CheckCodePointer();
1095 }
1096
1097
1098 void Assembler::CheckCodePointer() {
1099 #ifdef DEBUG
1100 Label cid_ok, instructions_ok;
1101 Push(R0);
1102 CompareClassId(CODE_REG, kCodeCid);
1103 b(&cid_ok, EQ);
1104 brk(0);
1105 Bind(&cid_ok);
1106
1107 const intptr_t entry_offset =
1108 CodeSize() + Instructions::HeaderSize() - kHeapObjectTag;
1109 adr(R0, Immediate(-entry_offset));
1110 ldr(TMP, FieldAddress(CODE_REG, Code::saved_instructions_offset()));
1111 cmp(R0, Operand(TMP));
1112 b(&instructions_ok, EQ);
1113 brk(1);
1114 Bind(&instructions_ok);
1115 Pop(R0);
1116 #endif
1117 }
1118
1119
1105 void Assembler::EnterFrame(intptr_t frame_size) { 1120 void Assembler::EnterFrame(intptr_t frame_size) {
1106 PushPair(LR, FP); 1121 PushPair(LR, FP);
1107 mov(FP, SP); 1122 mov(FP, SP);
1108 1123
1109 if (frame_size > 0) { 1124 if (frame_size > 0) {
1110 sub(SP, SP, Operand(frame_size)); 1125 sub(SP, SP, Operand(frame_size));
1111 } 1126 }
1112 } 1127 }
1113 1128
1114 1129
1115 void Assembler::LeaveFrame() { 1130 void Assembler::LeaveFrame() {
1116 mov(SP, FP); 1131 mov(SP, FP);
1117 PopPair(LR, FP); 1132 PopPair(LR, FP);
1118 } 1133 }
1119 1134
1120 1135
1121 void Assembler::EnterDartFrame(intptr_t frame_size, Register new_pp) { 1136 void Assembler::EnterDartFrame(intptr_t frame_size, Register new_pp) {
1122 ASSERT(!constant_pool_allowed()); 1137 ASSERT(!constant_pool_allowed());
1123 // Setup the frame. 1138 // Setup the frame.
1124 adr(TMP, Immediate(-CodeSize())); // TMP gets PC marker.
1125 EnterFrame(0); 1139 EnterFrame(0);
1126 TagAndPushPPAndPcMarker(TMP); // Save PP and PC marker. 1140 TagAndPushPPAndPcMarker(); // Save PP and PC marker.
1127 1141
1128 // Load the pool pointer. 1142 // Load the pool pointer.
1129 if (new_pp == kNoRegister) { 1143 if (new_pp == kNoRegister) {
1130 LoadPoolPointer(); 1144 LoadPoolPointer();
1131 } else { 1145 } else {
1132 mov(PP, new_pp); 1146 mov(PP, new_pp);
1133 set_constant_pool_allowed(true); 1147 set_constant_pool_allowed(true);
1134 } 1148 }
1135 1149
1136 // Reserve space. 1150 // Reserve space.
1137 if (frame_size > 0) { 1151 if (frame_size > 0) {
1138 AddImmediate(SP, SP, -frame_size); 1152 AddImmediate(SP, SP, -frame_size);
1139 } 1153 }
1140 } 1154 }
1141 1155
1142 1156
1143 // On entry to a function compiled for OSR, the caller's frame pointer, the 1157 // On entry to a function compiled for OSR, the caller's frame pointer, the
1144 // stack locals, and any copied parameters are already in place. The frame 1158 // stack locals, and any copied parameters are already in place. The frame
1145 // pointer is already set up. The PC marker is not correct for the 1159 // pointer is already set up. The PC marker is not correct for the
1146 // optimized function and there may be extra space for spill slots to 1160 // optimized function and there may be extra space for spill slots to
1147 // allocate. We must also set up the pool pointer for the function. 1161 // allocate. We must also set up the pool pointer for the function.
1148 void Assembler::EnterOsrFrame(intptr_t extra_size, Register new_pp) { 1162 void Assembler::EnterOsrFrame(intptr_t extra_size, Register new_pp) {
1149 ASSERT(!constant_pool_allowed()); 1163 ASSERT(!constant_pool_allowed());
1150 Comment("EnterOsrFrame"); 1164 Comment("EnterOsrFrame");
1151 adr(TMP, Immediate(-CodeSize())); 1165 RestoreCodePointer();
1152 1166 LoadPoolPointer();
1153 StoreToOffset(TMP, FP, kPcMarkerSlotFromFp * kWordSize);
1154
1155 // Setup pool pointer for this dart function.
1156 if (new_pp == kNoRegister) {
1157 LoadPoolPointer();
1158 } else {
1159 mov(PP, new_pp);
1160 set_constant_pool_allowed(true);
1161 }
1162 1167
1163 if (extra_size > 0) { 1168 if (extra_size > 0) {
1164 AddImmediate(SP, SP, -extra_size); 1169 AddImmediate(SP, SP, -extra_size);
1165 } 1170 }
1166 } 1171 }
1167 1172
1168 1173
1169 void Assembler::LeaveDartFrame() { 1174 void Assembler::LeaveDartFrame(RestorePP restore_pp) {
1170 set_constant_pool_allowed(false); 1175 if (restore_pp == kRestoreCallerPP) {
1171 // Restore and untag PP. 1176 set_constant_pool_allowed(false);
1172 LoadFromOffset(PP, FP, kSavedCallerPpSlotFromFp * kWordSize); 1177 // Restore and untag PP.
1173 sub(PP, PP, Operand(kHeapObjectTag)); 1178 LoadFromOffset(PP, FP, kSavedCallerPpSlotFromFp * kWordSize);
1179 sub(PP, PP, Operand(kHeapObjectTag));
1180 }
1174 LeaveFrame(); 1181 LeaveFrame();
1175 } 1182 }
1176 1183
1177 1184
1178 void Assembler::EnterCallRuntimeFrame(intptr_t frame_size) { 1185 void Assembler::EnterCallRuntimeFrame(intptr_t frame_size) {
1179 EnterStubFrame(); 1186 EnterStubFrame();
1180 1187
1181 // Store fpu registers with the lowest register number at the lowest 1188 // Store fpu registers with the lowest register number at the lowest
1182 // address. 1189 // address.
1183 for (int i = kNumberOfVRegisters - 1; i >= 0; i--) { 1190 for (int i = kNumberOfVRegisters - 1; i >= 0; i--) {
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
1229 } 1236 }
1230 1237
1231 1238
1232 void Assembler::CallRuntime(const RuntimeEntry& entry, 1239 void Assembler::CallRuntime(const RuntimeEntry& entry,
1233 intptr_t argument_count) { 1240 intptr_t argument_count) {
1234 entry.Call(this, argument_count); 1241 entry.Call(this, argument_count);
1235 } 1242 }
1236 1243
1237 1244
1238 void Assembler::EnterStubFrame() { 1245 void Assembler::EnterStubFrame() {
1239 set_constant_pool_allowed(false); 1246 EnterDartFrame(0);
1240 EnterFrame(0);
1241 // Save caller's pool pointer. Push 0 in the saved PC area for stub frames.
1242 TagAndPushPPAndPcMarker(ZR);
1243 LoadPoolPointer();
1244 } 1247 }
1245 1248
1246 1249
1247 void Assembler::LeaveStubFrame() { 1250 void Assembler::LeaveStubFrame() {
1248 LeaveDartFrame(); 1251 LeaveDartFrame();
1249 } 1252 }
1250 1253
1251 1254
1252 void Assembler::UpdateAllocationStats(intptr_t cid, 1255 void Assembler::UpdateAllocationStats(intptr_t cid,
1253 Heap::Space space, 1256 Heap::Space space,
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after
1478 add(base, array, Operand(index, LSL, shift)); 1481 add(base, array, Operand(index, LSL, shift));
1479 } 1482 }
1480 const OperandSize size = Address::OperandSizeFor(cid); 1483 const OperandSize size = Address::OperandSizeFor(cid);
1481 ASSERT(Address::CanHoldOffset(offset, Address::Offset, size)); 1484 ASSERT(Address::CanHoldOffset(offset, Address::Offset, size));
1482 return Address(base, offset, Address::Offset, size); 1485 return Address(base, offset, Address::Offset, size);
1483 } 1486 }
1484 1487
1485 } // namespace dart 1488 } // namespace dart
1486 1489
1487 #endif // defined TARGET_ARCH_ARM64 1490 #endif // defined TARGET_ARCH_ARM64
OLDNEW
« no previous file with comments | « runtime/vm/assembler_arm64.h ('k') | runtime/vm/assembler_arm64_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698