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

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: 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/assembler_arm.h ('k') | runtime/vm/assembler_arm64.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/assembler_arm.cc
diff --git a/runtime/vm/assembler_arm.cc b/runtime/vm/assembler_arm.cc
index 22202de22de6083e49241946c8e9752c21ea8a0d..0bbe790e20d14e06cb339ca9a5fe44d48a9bf362 100644
--- a/runtime/vm/assembler_arm.cc
+++ b/runtime/vm/assembler_arm.cc
@@ -1534,34 +1534,64 @@ 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
+ 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 +
+ Instructions::HeaderSize() - kHeapObjectTag;
+ mov(R0, Operand(PC));
+ AddImmediate(R0, R0, -offset);
+ ldr(IP, FieldAddress(CODE_REG, Code::saved_instructions_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);
}
@@ -1585,7 +1615,10 @@ bool Assembler::CanLoadFromObjectPool(const Object& object) const {
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)) {
// Load common VM constants from the thread. This works also in places where
// no constant pool is set up (e.g. intrinsic code).
@@ -1599,7 +1632,7 @@ 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);
} else {
ASSERT(FLAG_allow_absolute_addresses);
ASSERT(object.IsOld());
@@ -1611,14 +1644,14 @@ void Assembler::LoadObjectHelper(Register rd,
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);
}
@@ -1628,7 +1661,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);
}
@@ -1638,7 +1680,7 @@ void Assembler::LoadNativeEntry(Register rd,
Condition cond) {
const int32_t offset = ObjectPool::element_offset(
object_pool_wrapper_.FindNativeEntry(label, patchable));
- LoadWordFromPoolOffset(rd, offset - kHeapObjectTag, cond);
+ LoadWordFromPoolOffset(rd, offset - kHeapObjectTag, PP, cond);
}
@@ -1835,7 +1877,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.
}
@@ -1843,6 +1885,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);
@@ -2698,49 +2741,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, patchable));
+ 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, AL);
+ object_pool_wrapper_.FindObject(target, patchable));
+ LoadWordFromPoolOffset(CODE_REG, offset - kHeapObjectTag, PP, AL);
+ 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()));
}
@@ -2781,7 +2827,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, cond);
+ LoadWordFromPoolOffset(rd, offset - kHeapObjectTag, PP, cond);
} else {
LoadPatchableImmediate(rd, value, cond);
}
@@ -3317,19 +3363,9 @@ void Assembler::CallRuntime(const RuntimeEntry& entry,
void Assembler::EnterDartFrame(intptr_t frame_size) {
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();
@@ -3346,41 +3382,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.
- 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);
}
« no previous file with comments | « runtime/vm/assembler_arm.h ('k') | runtime/vm/assembler_arm64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698