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

Unified Diff: src/arm64/assembler-arm64.cc

Issue 1016073002: [arm64] Assembler support for internal references. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 9 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 | « src/arm64/assembler-arm64.h ('k') | src/arm64/assembler-arm64-inl.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/arm64/assembler-arm64.cc
diff --git a/src/arm64/assembler-arm64.cc b/src/arm64/assembler-arm64.cc
index 93d1d25a6c7747628d51c0c4466432ad9e749fd8..d0724336333d87476e610c65a9bc2796ffabb4f3 100644
--- a/src/arm64/assembler-arm64.cc
+++ b/src/arm64/assembler-arm64.cc
@@ -171,7 +171,7 @@ CPURegList CPURegList::GetSafepointSavedRegisters() {
// -----------------------------------------------------------------------------
// Implementation of RelocInfo
-const int RelocInfo::kApplyMask = 0;
+const int RelocInfo::kApplyMask = 1 << RelocInfo::INTERNAL_REFERENCE;
bool RelocInfo::IsCodedSpecially() {
@@ -732,7 +732,15 @@ void Assembler::bind(Label* label) {
DCHECK(prevlinkoffset >= 0);
// Update the link to point to the label.
- link->SetImmPCOffsetTarget(reinterpret_cast<Instruction*>(pc_));
+ if (link->IsUnresolvedInternalReference()) {
+ // Internal references do not get patched to an instruction but directly
+ // to an address.
+ internal_reference_positions_.push_back(linkoffset);
+ PatchingAssembler patcher(link, 2);
+ patcher.dc64(reinterpret_cast<uintptr_t>(pc_));
+ } else {
+ link->SetImmPCOffsetTarget(reinterpret_cast<Instruction*>(pc_));
+ }
// Link the label to the previous link in the chain.
if (linkoffset - prevlinkoffset == kStartOfLabelLinkChain) {
@@ -2060,6 +2068,50 @@ void Assembler::ucvtf(const FPRegister& fd,
}
+void Assembler::dcptr(Label* label) {
+ RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE);
+ if (label->is_bound()) {
+ // The label is bound, so it does not need to be updated and the internal
+ // reference should be emitted.
+ //
+ // In this case, label->pos() returns the offset of the label from the
+ // start of the buffer.
+ internal_reference_positions_.push_back(pc_offset());
+ dc64(reinterpret_cast<uintptr_t>(buffer_ + label->pos()));
+ } else {
+ int32_t offset;
+ if (label->is_linked()) {
+ // The label is linked, so the internal reference should be added
+ // onto the end of the label's link chain.
+ //
+ // In this case, label->pos() returns the offset of the last linked
+ // instruction from the start of the buffer.
+ offset = label->pos() - pc_offset();
+ DCHECK(offset != kStartOfLabelLinkChain);
+ } else {
+ // The label is unused, so it now becomes linked and the internal
+ // reference is at the start of the new link chain.
+ offset = kStartOfLabelLinkChain;
+ }
+ // The instruction at pc is now the last link in the label's chain.
+ label->link_to(pc_offset());
+
+ // Traditionally the offset to the previous instruction in the chain is
+ // encoded in the instruction payload (e.g. branch range) but internal
+ // references are not instructions so while unbound they are encoded as
+ // two consecutive brk instructions. The two 16-bit immediates are used
+ // to encode the offset.
+ offset >>= kInstructionSizeLog2;
+ DCHECK(is_int32(offset));
+ uint32_t high16 = unsigned_bitextract_32(31, 16, offset);
+ uint32_t low16 = unsigned_bitextract_32(15, 0, offset);
+
+ brk(high16);
+ brk(low16);
+ }
+}
+
+
// Note:
// Below, a difference in case for the same letter indicates a
// negated bit.
@@ -2819,6 +2871,12 @@ void Assembler::GrowBuffer() {
// buffer nor pc absolute pointing inside the code buffer, so there is no need
// to relocate any emitted relocation entries.
+ // Relocate internal references.
+ for (auto pos : internal_reference_positions_) {
+ intptr_t* p = reinterpret_cast<intptr_t*>(buffer_ + pos);
+ *p += pc_delta;
+ }
+
// Pending relocation entries are also relative, no need to relocate.
}
@@ -2828,6 +2886,7 @@ void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
RelocInfo rinfo(reinterpret_cast<byte*>(pc_), rmode, data, NULL);
if (((rmode >= RelocInfo::JS_RETURN) &&
(rmode <= RelocInfo::DEBUG_BREAK_SLOT)) ||
+ (rmode == RelocInfo::INTERNAL_REFERENCE) ||
(rmode == RelocInfo::CONST_POOL) ||
(rmode == RelocInfo::VENEER_POOL) ||
(rmode == RelocInfo::DEOPT_REASON)) {
@@ -2837,6 +2896,7 @@ void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) {
|| RelocInfo::IsComment(rmode)
|| RelocInfo::IsDeoptReason(rmode)
|| RelocInfo::IsPosition(rmode)
+ || RelocInfo::IsInternalReference(rmode)
|| RelocInfo::IsConstPool(rmode)
|| RelocInfo::IsVeneerPool(rmode));
// These modes do not need an entry in the constant pool.
« no previous file with comments | « src/arm64/assembler-arm64.h ('k') | src/arm64/assembler-arm64-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698