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

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

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