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

Unified Diff: runtime/vm/assembler_arm.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 side-by-side diff with in-line comments
Download patch
Index: runtime/vm/assembler_arm.cc
diff --git a/runtime/vm/assembler_arm.cc b/runtime/vm/assembler_arm.cc
index 71a960831e0aff959f3d0d7829966d4a7599e2c9..a40f235bcf8433d6becfb6b5e504e817e2bb5751 100644
--- a/runtime/vm/assembler_arm.cc
+++ b/runtime/vm/assembler_arm.cc
@@ -1533,34 +1533,63 @@ intptr_t Assembler::FindImmediate(int32_t imm) {
// Uses a code sequence that can easily be decoded.
void Assembler::LoadWordFromPoolOffset(Register rd,
int32_t offset,
+ Register pp,
Condition cond) {
- ASSERT(constant_pool_allowed());
- ASSERT(rd != PP);
+ ASSERT((pp != PP) || constant_pool_allowed());
+ ASSERT(rd != pp);
int32_t offset_mask = 0;
if (Address::CanHoldLoadOffset(kWord, offset, &offset_mask)) {
- ldr(rd, Address(PP, offset), cond);
+ ldr(rd, Address(pp, offset), cond);
} else {
int32_t offset_hi = offset & ~offset_mask; // signed
uint32_t offset_lo = offset & offset_mask; // unsigned
- // Inline a simplified version of AddImmediate(rd, PP, offset_hi).
+ // Inline a simplified version of AddImmediate(rd, pp, offset_hi).
Operand o;
if (Operand::CanHold(offset_hi, &o)) {
- add(rd, PP, o, cond);
+ add(rd, pp, o, cond);
} else {
LoadImmediate(rd, offset_hi, cond);
- add(rd, PP, Operand(rd), cond);
+ add(rd, pp, Operand(rd), cond);
}
ldr(rd, Address(rd, offset_lo), cond);
}
}
+void Assembler::CheckCodePointer() {
+#ifdef DEBUG
rmacnak 2015/09/12 23:12:43 This seems a bit heavy even for debug mode. When f
Florian Schneider 2015/09/14 11:15:15 Yes, it is, but my guess is that in DEBUG mode, ge
+ Label cid_ok, instructions_ok;
+ Push(R0);
+ Push(IP);
+ CompareClassId(CODE_REG, kCodeCid, R0);
+ b(&cid_ok, EQ);
+ bkpt(0);
+ Bind(&cid_ok);
+
+ const intptr_t offset = CodeSize() + Instr::kPCReadOffset;
+ mov(R0, Operand(PC));
+ AddImmediate(R0, R0, -offset);
+ ldr(IP, FieldAddress(CODE_REG, Code::entry_point_offset()));
+ cmp(R0, Operand(IP));
+ b(&instructions_ok, EQ);
+ bkpt(1);
+ Bind(&instructions_ok);
+ Pop(IP);
+ Pop(R0);
+#endif
+}
+
+
+void Assembler::RestoreCodePointer() {
+ ldr(CODE_REG, Address(FP, kPcMarkerSlotFromFp * kWordSize));
+ CheckCodePointer();
+}
+
-void Assembler::LoadPoolPointer() {
- const intptr_t object_pool_pc_dist =
- Instructions::HeaderSize() - Instructions::object_pool_offset() +
- CodeSize() + Instr::kPCReadOffset;
- LoadFromOffset(kWord, PP, PC, -object_pool_pc_dist);
- set_constant_pool_allowed(true);
+void Assembler::LoadPoolPointer(Register reg) {
+ // Load new pool pointer.
+ CheckCodePointer();
+ ldr(reg, FieldAddress(CODE_REG, Code::object_pool_offset()));
+ set_constant_pool_allowed(reg == PP);
}
@@ -1572,7 +1601,8 @@ void Assembler::LoadIsolate(Register rd) {
void Assembler::LoadObjectHelper(Register rd,
const Object& object,
Condition cond,
- bool is_unique) {
+ bool is_unique,
+ Register pp) {
// Load common VM constants from the thread. This works also in places where
// no constant pool is set up (e.g. intrinsic code).
if (Thread::CanLoadFromThread(object)) {
@@ -1592,20 +1622,20 @@ void Assembler::LoadObjectHelper(Register rd,
const int32_t offset = ObjectPool::element_offset(
is_unique ? object_pool_wrapper_.AddObject(object)
: object_pool_wrapper_.FindObject(object));
- LoadWordFromPoolOffset(rd, offset - kHeapObjectTag, cond);
+ LoadWordFromPoolOffset(rd, offset - kHeapObjectTag, PP, cond);
}
}
void Assembler::LoadObject(Register rd, const Object& object, Condition cond) {
- LoadObjectHelper(rd, object, cond, false);
+ LoadObjectHelper(rd, object, cond, /* is_unique = */ false, PP);
}
void Assembler::LoadUniqueObject(Register rd,
const Object& object,
Condition cond) {
- LoadObjectHelper(rd, object, cond, true);
+ LoadObjectHelper(rd, object, cond, /* is_unique = */ true, PP);
}
@@ -1615,7 +1645,16 @@ void Assembler::LoadExternalLabel(Register rd,
Condition cond) {
const int32_t offset = ObjectPool::element_offset(
object_pool_wrapper_.FindExternalLabel(label, patchable));
- LoadWordFromPoolOffset(rd, offset - kHeapObjectTag, cond);
+ LoadWordFromPoolOffset(rd, offset - kHeapObjectTag, PP, cond);
+}
+
+
+void Assembler::LoadFunctionFromCalleePool(Register dst,
+ const Function& function,
+ Register new_pp) {
+ const int32_t offset =
+ ObjectPool::element_offset(object_pool_wrapper_.FindObject(function));
+ LoadWordFromPoolOffset(dst, offset - kHeapObjectTag, new_pp, AL);
}
@@ -1812,7 +1851,7 @@ void Assembler::StoreIntoObject(Register object,
StoreIntoObjectFilterNoSmi(object, value, &done);
}
// A store buffer update is required.
- RegList regs = (1 << LR);
+ RegList regs = (1 << CODE_REG) | (1 << LR);
if (value != R0) {
regs |= (1 << R0); // Preserve R0.
}
@@ -1820,6 +1859,7 @@ void Assembler::StoreIntoObject(Register object,
if (object != R0) {
mov(R0, Operand(object));
}
+ ldr(CODE_REG, Address(THR, Thread::update_store_buffer_code_offset()));
ldr(LR, Address(THR, Thread::update_store_buffer_entry_point_offset()));
blx(LR);
PopList(regs);
@@ -2678,49 +2718,52 @@ void Assembler::Vdivqs(QRegister qd, QRegister qn, QRegister qm) {
}
-void Assembler::Branch(const StubEntry& stub_entry, Condition cond) {
- // Address is never patched.
- LoadImmediate(IP, stub_entry.label().address(), cond);
+void Assembler::Branch(const StubEntry& stub_entry,
+ Patchability patchable,
+ Register pp,
+ Condition cond) {
+ const Code& target_code = Code::Handle(stub_entry.code());
+ const int32_t offset = ObjectPool::element_offset(
+ object_pool_wrapper_.FindObject(target_code, kPatchable));
rmacnak 2015/09/12 23:12:44 patchable
Florian Schneider 2015/09/14 11:15:15 Done.
+ LoadWordFromPoolOffset(CODE_REG, offset - kHeapObjectTag, pp, cond);
+ ldr(IP, FieldAddress(CODE_REG, Code::entry_point_offset()), cond);
bx(IP, cond);
}
-void Assembler::BranchPatchable(const StubEntry& stub_entry) {
- // Use a fixed size code sequence, since a function prologue may be patched
- // with this branch sequence.
- // Contrarily to BranchLinkPatchable, BranchPatchable requires an instruction
- // cache flush upon patching.
- LoadPatchableImmediate(IP, stub_entry.label().address());
- bx(IP);
-}
-
-
-void Assembler::BranchLink(const ExternalLabel* label) {
- LoadImmediate(LR, label->address()); // Target address is never patched.
- blx(LR); // Use blx instruction so that the return branch prediction works.
-}
-
-
-void Assembler::BranchLink(const ExternalLabel* label, Patchability patchable) {
+void Assembler::BranchLink(const Code& target, Patchability patchable) {
// Make sure that class CallPattern is able to patch the label referred
// to by this code sequence.
// For added code robustness, use 'blx lr' in a patchable sequence and
// use 'blx ip' in a non-patchable sequence (see other BranchLink flavors).
const int32_t offset = ObjectPool::element_offset(
- object_pool_wrapper_.FindExternalLabel(label, patchable));
- LoadWordFromPoolOffset(LR, offset - kHeapObjectTag);
+ object_pool_wrapper_.FindObject(target, patchable));
+ LoadWordFromPoolOffset(CODE_REG, offset - kHeapObjectTag, PP);
+ ldr(LR, FieldAddress(CODE_REG, Code::entry_point_offset()));
blx(LR); // Use blx instruction so that the return branch prediction works.
}
void Assembler::BranchLink(const StubEntry& stub_entry,
Patchability patchable) {
- BranchLink(&stub_entry.label(), patchable);
+ const Code& code = Code::Handle(stub_entry.code());
+ BranchLink(code, patchable);
+}
+
+
+void Assembler::BranchLinkPatchable(const Code& target) {
+ BranchLink(target, kPatchable);
+}
+
+
+void Assembler::BranchLink(const ExternalLabel* label) {
+ LoadImmediate(LR, label->address()); // Target address is never patched.
+ blx(LR); // Use blx instruction so that the return branch prediction works.
}
void Assembler::BranchLinkPatchable(const StubEntry& stub_entry) {
- BranchLink(&stub_entry.label(), kPatchable);
+ BranchLinkPatchable(Code::Handle(stub_entry.code()));
}
@@ -2761,7 +2804,7 @@ void Assembler::LoadDecodableImmediate(
if ((version == ARMv5TE) || (version == ARMv6)) {
if (constant_pool_allowed()) {
const int32_t offset = Array::element_offset(FindImmediate(value));
- LoadWordFromPoolOffset(rd, offset - kHeapObjectTag);
+ LoadWordFromPoolOffset(rd, offset - kHeapObjectTag, PP);
} else {
LoadPatchableImmediate(rd, value, cond);
}
@@ -3296,20 +3339,11 @@ void Assembler::CallRuntime(const RuntimeEntry& entry,
void Assembler::EnterDartFrame(intptr_t frame_size) {
+ CheckCodePointer();
ASSERT(!constant_pool_allowed());
- const intptr_t offset = CodeSize();
- // Save PC in frame for fast identification of corresponding code.
- // Note that callee-saved registers can be added to the register list.
- EnterFrame((1 << PP) | (1 << FP) | (1 << LR) | (1 << PC), 0);
-
- if (offset != 0) {
- // Adjust saved PC for any intrinsic code that could have been generated
- // before a frame is created. Use PP as temp register.
- ldr(PP, Address(FP, 2 * kWordSize));
- AddImmediate(PP, PP, -offset);
- str(PP, Address(FP, 2 * kWordSize));
- }
+ // Registers are pushed in descending order: R9 | R10 | R11 | R14.
+ EnterFrame((1 << PP) | (1 << CODE_REG) | (1 << FP) | (1 << LR), 0);
// Setup pool pointer for this dart function.
LoadPoolPointer();
@@ -3326,41 +3360,26 @@ void Assembler::EnterDartFrame(intptr_t frame_size) {
// allocate. We must also set up the pool pointer for the function.
void Assembler::EnterOsrFrame(intptr_t extra_size) {
ASSERT(!constant_pool_allowed());
- // mov(IP, Operand(PC)) loads PC + Instr::kPCReadOffset (8). This may be
- // different from EntryPointToPcMarkerOffset().
- const intptr_t offset =
- CodeSize() + Instr::kPCReadOffset - EntryPointToPcMarkerOffset();
-
Comment("EnterOsrFrame");
- mov(IP, Operand(PC));
-
- AddImmediate(IP, -offset);
- str(IP, Address(FP, kPcMarkerSlotFromFp * kWordSize));
-
- // Setup pool pointer for this dart function.
+ RestoreCodePointer();
LoadPoolPointer();
AddImmediate(SP, -extra_size);
}
-void Assembler::LeaveDartFrame() {
- set_constant_pool_allowed(false);
- LeaveFrame((1 << PP) | (1 << FP) | (1 << LR));
- // Adjust SP for PC pushed in EnterDartFrame.
- AddImmediate(SP, kWordSize);
+void Assembler::LeaveDartFrame(RestorePP restore_pp) {
+ if (restore_pp == kRestoreCallerPP) {
+ ldr(PP, Address(FP, kSavedCallerPpSlotFromFp * kWordSize));
+ set_constant_pool_allowed(false);
+ }
+ Drop(2); // Drop saved PP, PC marker.
+ LeaveFrame((1 << FP) | (1 << LR));
}
void Assembler::EnterStubFrame() {
- set_constant_pool_allowed(false);
- // Push 0 as saved PC for stub frames.
rmacnak 2015/09/12 23:12:44 GC stack walker should be able to assert the pc-ma
Florian Schneider 2015/09/14 11:15:15 Done. Added assertion to StackFrame::GetCodeObject
- mov(IP, Operand(LR));
- mov(LR, Operand(0));
- RegList regs = (1 << PP) | (1 << FP) | (1 << IP) | (1 << LR);
- EnterFrame(regs, 0);
- // Setup pool pointer for this stub.
- LoadPoolPointer();
+ EnterDartFrame(0);
}

Powered by Google App Engine
This is Rietveld 408576698