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

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: ia32 port, addressed 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
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 285 matching lines...) Expand 10 before | Expand all | Expand 10 after
296 continue; 296 continue;
297 } 297 }
298 298
299 // 6. Otherwise, the value can't be encoded. 299 // 6. Otherwise, the value can't be encoded.
300 return false; 300 return false;
301 } 301 }
302 } 302 }
303 303
304 304
305 void Assembler::LoadPoolPointer(Register pp) { 305 void Assembler::LoadPoolPointer(Register pp) {
306 const intptr_t object_pool_pc_dist = 306 CheckCodePointer();
307 Instructions::HeaderSize() - Instructions::object_pool_offset() + 307 ldr(pp, FieldAddress(CODE_REG, Code::object_pool_offset()));
308 CodeSize();
309 // PP <- Read(PC - object_pool_pc_dist).
310 ldr(pp, Address::PC(-object_pool_pc_dist));
311 308
312 // When in the PP register, the pool pointer is untagged. When we 309 // When in the PP register, the pool pointer is untagged. When we
313 // push it on the stack with TagAndPushPP it is tagged again. PopAndUntagPP 310 // push it on the stack with TagAndPushPP it is tagged again. PopAndUntagPP
314 // then untags when restoring from the stack. This will make loading from the 311 // then untags when restoring from the stack. This will make loading from the
315 // object pool only one instruction for the first 4096 entries. Otherwise, 312 // object pool only one instruction for the first 4096 entries. Otherwise,
316 // because the offset wouldn't be aligned, it would be only one instruction 313 // because the offset wouldn't be aligned, it would be only one instruction
317 // for the first 64 entries. 314 // for the first 64 entries.
318 sub(pp, pp, Operand(kHeapObjectTag)); 315 sub(pp, pp, Operand(kHeapObjectTag));
319 set_constant_pool_allowed(pp == PP); 316 set_constant_pool_allowed(pp == PP);
320 } 317 }
321 318
322 319
323 void Assembler::LoadWordFromPoolOffset(Register dst, uint32_t offset) { 320 void Assembler::LoadWordFromPoolOffset(Register dst,
324 ASSERT(constant_pool_allowed()); 321 uint32_t offset,
325 ASSERT(dst != PP); 322 Register pp) {
323 ASSERT((pp != PP) || constant_pool_allowed());
324 ASSERT(dst != pp);
326 Operand op; 325 Operand op;
327 const uint32_t upper20 = offset & 0xfffff000; 326 const uint32_t upper20 = offset & 0xfffff000;
328 if (Address::CanHoldOffset(offset)) { 327 if (Address::CanHoldOffset(offset)) {
329 ldr(dst, Address(PP, offset)); 328 ldr(dst, Address(pp, offset));
330 } else if (Operand::CanHold(upper20, kXRegSizeInBits, &op) == 329 } else if (Operand::CanHold(upper20, kXRegSizeInBits, &op) ==
331 Operand::Immediate) { 330 Operand::Immediate) {
332 const uint32_t lower12 = offset & 0x00000fff; 331 const uint32_t lower12 = offset & 0x00000fff;
333 ASSERT(Address::CanHoldOffset(lower12)); 332 ASSERT(Address::CanHoldOffset(lower12));
334 add(dst, PP, op); 333 add(dst, pp, op);
335 ldr(dst, Address(dst, lower12)); 334 ldr(dst, Address(dst, lower12));
336 } else { 335 } else {
337 const uint16_t offset_low = Utils::Low16Bits(offset); 336 const uint16_t offset_low = Utils::Low16Bits(offset);
338 const uint16_t offset_high = Utils::High16Bits(offset); 337 const uint16_t offset_high = Utils::High16Bits(offset);
339 movz(dst, Immediate(offset_low), 0); 338 movz(dst, Immediate(offset_low), 0);
340 if (offset_high != 0) { 339 if (offset_high != 0) {
341 movk(dst, Immediate(offset_high), 1); 340 movk(dst, Immediate(offset_high), 1);
342 } 341 }
343 ldr(dst, Address(PP, dst)); 342 ldr(dst, Address(pp, dst));
344 } 343 }
345 } 344 }
346 345
347 346
348 void Assembler::LoadWordFromPoolOffsetFixed(Register dst, uint32_t offset) { 347 void Assembler::LoadWordFromPoolOffsetFixed(Register dst, uint32_t offset) {
349 ASSERT(constant_pool_allowed()); 348 ASSERT(constant_pool_allowed());
350 ASSERT(dst != PP); 349 ASSERT(dst != PP);
351 Operand op; 350 Operand op;
352 const uint32_t upper20 = offset & 0xfffff000; 351 const uint32_t upper20 = offset & 0xfffff000;
353 const uint32_t lower12 = offset & 0x00000fff; 352 const uint32_t lower12 = offset & 0x00000fff;
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after
577 576
578 void Assembler::LoadDImmediate(VRegister vd, double immd) { 577 void Assembler::LoadDImmediate(VRegister vd, double immd) {
579 if (!fmovdi(vd, immd)) { 578 if (!fmovdi(vd, immd)) {
580 int64_t imm = bit_cast<int64_t, double>(immd); 579 int64_t imm = bit_cast<int64_t, double>(immd);
581 LoadImmediate(TMP, imm); 580 LoadImmediate(TMP, imm);
582 fmovdr(vd, TMP); 581 fmovdr(vd, TMP);
583 } 582 }
584 } 583 }
585 584
586 585
587 void Assembler::Branch(const ExternalLabel* label) { 586 void Assembler::Branch(const StubEntry& stub_entry,
588 LoadExternalLabel(TMP, label); 587 Register pp,
589 br(TMP); 588 Patchability patchable) {
590 } 589 const Code& target = Code::Handle(stub_entry.code());
591 590 const int32_t offset = ObjectPool::element_offset(
592 591 object_pool_wrapper_.FindObject(target, patchable));
593 void Assembler::Branch(const StubEntry& stub_entry) { 592 LoadWordFromPoolOffset(CODE_REG, offset, pp);
594 const ExternalLabel label(stub_entry.EntryPoint()); 593 ldr(TMP, FieldAddress(CODE_REG, Code::entry_point_offset()));
595 Branch(&label);
596 }
597
598
599 void Assembler::BranchPatchable(const ExternalLabel* label) {
600 // TODO(zra): Use LoadExternalLabelFixed if possible.
601 LoadImmediateFixed(TMP, label->address());
602 br(TMP); 594 br(TMP);
603 } 595 }
604 596
605 void Assembler::BranchPatchable(const StubEntry& stub_entry) { 597 void Assembler::BranchPatchable(const StubEntry& stub_entry) {
606 BranchPatchable(&stub_entry.label()); 598 Branch(stub_entry, PP, kPatchable);
607 } 599 }
608 600
609 601
610 void Assembler::BranchLink(const ExternalLabel* label) { 602 void Assembler::BranchLink(const StubEntry& stub_entry,
611 LoadExternalLabel(TMP, label); 603 Patchability patchable) {
612 blr(TMP); 604 const Code& target = Code::Handle(stub_entry.code());
613 } 605 const int32_t offset = ObjectPool::element_offset(
614 606 object_pool_wrapper_.FindObject(target, patchable));
615 607 LoadWordFromPoolOffset(CODE_REG, offset);
616 void Assembler::BranchLink(const StubEntry& stub_entry) { 608 ldr(TMP, FieldAddress(CODE_REG, Code::entry_point_offset()));
617 BranchLink(&stub_entry.label());
618 }
619
620
621 void Assembler::BranchLinkPatchable(const ExternalLabel* label) {
622 LoadExternalLabelFixed(TMP, label, kPatchable);
623 blr(TMP); 609 blr(TMP);
624 } 610 }
625 611
626 612
627 void Assembler::BranchLinkPatchable(const StubEntry& stub_entry) { 613 void Assembler::BranchLinkPatchable(const StubEntry& stub_entry) {
628 BranchLinkPatchable(&stub_entry.label()); 614 BranchLink(stub_entry, kPatchable);
629 } 615 }
630 616
631 617
632 void Assembler::AddImmediate(Register dest, Register rn, int64_t imm) { 618 void Assembler::AddImmediate(Register dest, Register rn, int64_t imm) {
633 Operand op; 619 Operand op;
634 if (imm == 0) { 620 if (imm == 0) {
635 if (dest != rn) { 621 if (dest != rn) {
636 mov(dest, rn); 622 mov(dest, rn);
637 } 623 }
638 return; 624 return;
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after
908 } 894 }
909 // A store buffer update is required. 895 // A store buffer update is required.
910 if (value != R0) { 896 if (value != R0) {
911 // Preserve R0. 897 // Preserve R0.
912 Push(R0); 898 Push(R0);
913 } 899 }
914 Push(LR); 900 Push(LR);
915 if (object != R0) { 901 if (object != R0) {
916 mov(R0, object); 902 mov(R0, object);
917 } 903 }
904 ldr(CODE_REG, Address(THR, Thread::update_store_buffer_code_offset()));
918 ldr(TMP, Address(THR, Thread::update_store_buffer_entry_point_offset())); 905 ldr(TMP, Address(THR, Thread::update_store_buffer_entry_point_offset()));
919 blr(TMP); 906 blr(TMP);
920 Pop(LR); 907 Pop(LR);
921 if (value != R0) { 908 if (value != R0) {
922 // Restore R0. 909 // Restore R0.
923 Pop(R0); 910 Pop(R0);
924 } 911 }
925 Bind(&done); 912 Bind(&done);
926 } 913 }
927 914
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
1084 // the C++ world. 1071 // the C++ world.
1085 if (frame_space != 0) { 1072 if (frame_space != 0) {
1086 AddImmediate(SP, SP, -frame_space); 1073 AddImmediate(SP, SP, -frame_space);
1087 } 1074 }
1088 if (OS::ActivationFrameAlignment() > 1) { 1075 if (OS::ActivationFrameAlignment() > 1) {
1089 andi(SP, SP, Immediate(~(OS::ActivationFrameAlignment() - 1))); 1076 andi(SP, SP, Immediate(~(OS::ActivationFrameAlignment() - 1)));
1090 } 1077 }
1091 } 1078 }
1092 1079
1093 1080
1081 void Assembler::RestoreCodePointer() {
1082 ldr(CODE_REG, Address(FP, kPcMarkerSlotFromFp * kWordSize));
1083 CheckCodePointer();
1084 }
1085
1086
1087 void Assembler::CheckCodePointer() {
1088 #ifdef DEBUG
1089 Label cid_ok, instructions_ok;
1090 Push(R0);
1091 CompareClassId(CODE_REG, kCodeCid);
1092 b(&cid_ok, EQ);
1093 brk(0);
1094 Bind(&cid_ok);
1095
1096 adr(R0, Immediate(-CodeSize()));
1097 ldr(TMP, FieldAddress(CODE_REG, Code::entry_point_offset()));
1098 cmp(R0, Operand(TMP));
1099 b(&instructions_ok, EQ);
1100 brk(1);
1101 Bind(&instructions_ok);
1102 Pop(R0);
1103 #endif
1104 }
1105
1106
1094 void Assembler::EnterFrame(intptr_t frame_size) { 1107 void Assembler::EnterFrame(intptr_t frame_size) {
1095 PushPair(LR, FP); 1108 PushPair(LR, FP);
1096 mov(FP, SP); 1109 mov(FP, SP);
1097 1110
1098 if (frame_size > 0) { 1111 if (frame_size > 0) {
1099 sub(SP, SP, Operand(frame_size)); 1112 sub(SP, SP, Operand(frame_size));
1100 } 1113 }
1101 } 1114 }
1102 1115
1103 1116
1104 void Assembler::LeaveFrame() { 1117 void Assembler::LeaveFrame() {
1105 mov(SP, FP); 1118 mov(SP, FP);
1106 PopPair(LR, FP); 1119 PopPair(LR, FP);
1107 } 1120 }
1108 1121
1109 1122
1110 void Assembler::EnterDartFrame(intptr_t frame_size, Register new_pp) { 1123 void Assembler::EnterDartFrame(intptr_t frame_size, Register new_pp) {
1124 CheckCodePointer();
1111 ASSERT(!constant_pool_allowed()); 1125 ASSERT(!constant_pool_allowed());
1112 // Setup the frame. 1126 // Setup the frame.
1113 adr(TMP, Immediate(-CodeSize())); // TMP gets PC marker.
1114 EnterFrame(0); 1127 EnterFrame(0);
1115 TagAndPushPPAndPcMarker(TMP); // Save PP and PC marker. 1128 TagAndPushPPAndPcMarker(); // Save PP and PC marker.
1116 1129
1117 // Load the pool pointer. 1130 // Load the pool pointer.
1118 if (new_pp == kNoRegister) { 1131 if (new_pp == kNoRegister) {
1119 LoadPoolPointer(); 1132 LoadPoolPointer();
1120 } else { 1133 } else {
1121 mov(PP, new_pp); 1134 mov(PP, new_pp);
1122 set_constant_pool_allowed(true); 1135 set_constant_pool_allowed(true);
1123 } 1136 }
1124 1137
1125 // Reserve space. 1138 // Reserve space.
1126 if (frame_size > 0) { 1139 if (frame_size > 0) {
1127 AddImmediate(SP, SP, -frame_size); 1140 AddImmediate(SP, SP, -frame_size);
1128 } 1141 }
1129 } 1142 }
1130 1143
1131 1144
1132 // On entry to a function compiled for OSR, the caller's frame pointer, the 1145 // On entry to a function compiled for OSR, the caller's frame pointer, the
1133 // stack locals, and any copied parameters are already in place. The frame 1146 // stack locals, and any copied parameters are already in place. The frame
1134 // pointer is already set up. The PC marker is not correct for the 1147 // pointer is already set up. The PC marker is not correct for the
1135 // optimized function and there may be extra space for spill slots to 1148 // optimized function and there may be extra space for spill slots to
1136 // allocate. We must also set up the pool pointer for the function. 1149 // allocate. We must also set up the pool pointer for the function.
1137 void Assembler::EnterOsrFrame(intptr_t extra_size, Register new_pp) { 1150 void Assembler::EnterOsrFrame(intptr_t extra_size, Register new_pp) {
1138 ASSERT(!constant_pool_allowed()); 1151 ASSERT(!constant_pool_allowed());
1139 Comment("EnterOsrFrame"); 1152 Comment("EnterOsrFrame");
1140 adr(TMP, Immediate(-CodeSize())); 1153 RestoreCodePointer();
1141 1154 LoadPoolPointer();
1142 StoreToOffset(TMP, FP, kPcMarkerSlotFromFp * kWordSize);
1143
1144 // Setup pool pointer for this dart function.
1145 if (new_pp == kNoRegister) {
1146 LoadPoolPointer();
1147 } else {
1148 mov(PP, new_pp);
1149 set_constant_pool_allowed(true);
1150 }
1151 1155
1152 if (extra_size > 0) { 1156 if (extra_size > 0) {
1153 AddImmediate(SP, SP, -extra_size); 1157 AddImmediate(SP, SP, -extra_size);
1154 } 1158 }
1155 } 1159 }
1156 1160
1157 1161
1158 void Assembler::LeaveDartFrame() { 1162 void Assembler::LeaveDartFrame(RestorePP restore_pp) {
1159 set_constant_pool_allowed(false); 1163 if (restore_pp == kRestoreCallerPP) {
1160 // Restore and untag PP. 1164 set_constant_pool_allowed(false);
1161 LoadFromOffset(PP, FP, kSavedCallerPpSlotFromFp * kWordSize); 1165 // Restore and untag PP.
1162 sub(PP, PP, Operand(kHeapObjectTag)); 1166 LoadFromOffset(PP, FP, kSavedCallerPpSlotFromFp * kWordSize);
1167 sub(PP, PP, Operand(kHeapObjectTag));
1168 }
1163 LeaveFrame(); 1169 LeaveFrame();
1164 } 1170 }
1165 1171
1166 1172
1167 void Assembler::EnterCallRuntimeFrame(intptr_t frame_size) { 1173 void Assembler::EnterCallRuntimeFrame(intptr_t frame_size) {
1168 EnterStubFrame(); 1174 EnterStubFrame();
1169 1175
1170 // Store fpu registers with the lowest register number at the lowest 1176 // Store fpu registers with the lowest register number at the lowest
1171 // address. 1177 // address.
1172 for (int i = kNumberOfVRegisters - 1; i >= 0; i--) { 1178 for (int i = kNumberOfVRegisters - 1; i >= 0; i--) {
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
1218 } 1224 }
1219 1225
1220 1226
1221 void Assembler::CallRuntime(const RuntimeEntry& entry, 1227 void Assembler::CallRuntime(const RuntimeEntry& entry,
1222 intptr_t argument_count) { 1228 intptr_t argument_count) {
1223 entry.Call(this, argument_count); 1229 entry.Call(this, argument_count);
1224 } 1230 }
1225 1231
1226 1232
1227 void Assembler::EnterStubFrame() { 1233 void Assembler::EnterStubFrame() {
1228 set_constant_pool_allowed(false); 1234 EnterDartFrame(0);
1229 EnterFrame(0);
1230 // Save caller's pool pointer. Push 0 in the saved PC area for stub frames.
1231 TagAndPushPPAndPcMarker(ZR);
1232 LoadPoolPointer();
1233 } 1235 }
1234 1236
1235 1237
1236 void Assembler::LeaveStubFrame() { 1238 void Assembler::LeaveStubFrame() {
1237 LeaveDartFrame(); 1239 LeaveDartFrame();
1238 } 1240 }
1239 1241
1240 1242
1241 void Assembler::UpdateAllocationStats(intptr_t cid, 1243 void Assembler::UpdateAllocationStats(intptr_t cid,
1242 Heap::Space space, 1244 Heap::Space space,
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after
1465 add(base, array, Operand(index, LSL, shift)); 1467 add(base, array, Operand(index, LSL, shift));
1466 } 1468 }
1467 const OperandSize size = Address::OperandSizeFor(cid); 1469 const OperandSize size = Address::OperandSizeFor(cid);
1468 ASSERT(Address::CanHoldOffset(offset, Address::Offset, size)); 1470 ASSERT(Address::CanHoldOffset(offset, Address::Offset, size));
1469 return Address(base, offset, Address::Offset, size); 1471 return Address(base, offset, Address::Offset, size);
1470 } 1472 }
1471 1473
1472 } // namespace dart 1474 } // namespace dart
1473 1475
1474 #endif // defined TARGET_ARCH_ARM64 1476 #endif // defined TARGET_ARCH_ARM64
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698