Commit 13fc4a1b authored by jgruber's avatar jgruber Committed by Commit Bot

[masm] Shortcut some indirect external reference loads

External references located within the isolate can be loaded as a
fixed offset from the root register. This avoids one load from memory
over the default indirect method (which reads from the external
reference table).

Bug: v8:6666
Change-Id: I569308c03f1a8c3feb1be7ceb072178b5be17b25
Reviewed-on: https://chromium-review.googlesource.com/1092739
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#53661}
parent 964f11b6
......@@ -173,6 +173,15 @@ void TurboAssembler::LoadBuiltin(Register destination, int builtin_index) {
ldr(destination, MemOperand(kRootRegister, roots_to_builtins_offset));
}
void TurboAssembler::LoadRootRegisterOffset(Register destination,
intptr_t offset) {
if (offset == 0) {
Move(destination, kRootRegister);
} else {
add(destination, kRootRegister, Operand(offset));
}
}
#endif // V8_EMBEDDED_BUILTINS
void TurboAssembler::Jump(Register target, Condition cond) { bx(target, cond); }
......
......@@ -322,6 +322,7 @@ class TurboAssembler : public TurboAssemblerBase {
void LoadExternalReference(Register destination,
int reference_index) override;
void LoadBuiltin(Register destination, int builtin_index) override;
void LoadRootRegisterOffset(Register destination, intptr_t offset) override;
#endif // V8_EMBEDDED_BUILTINS
// Returns the size of a call in instructions. Note, the value returned is
......
......@@ -1891,6 +1891,15 @@ void TurboAssembler::LoadBuiltin(Register destination, int builtin_index) {
Heap::roots_to_builtins_offset() + builtin_index * kPointerSize;
Ldr(destination, MemOperand(kRootRegister, roots_to_builtins_offset));
}
void TurboAssembler::LoadRootRegisterOffset(Register destination,
intptr_t offset) {
if (offset == 0) {
Move(destination, kRootRegister);
} else {
Add(destination, kRootRegister, Operand(offset));
}
}
#endif // V8_EMBEDDED_BUILTINS
void TurboAssembler::Jump(Register target, Condition cond) {
......
......@@ -880,6 +880,7 @@ class TurboAssembler : public TurboAssemblerBase {
void LoadExternalReference(Register destination,
int reference_index) override;
void LoadBuiltin(Register destination, int builtin_index) override;
void LoadRootRegisterOffset(Register destination, intptr_t offset) override;
#endif // V8_EMBEDDED_BUILTINS
void Jump(Register target, Condition cond = al);
......
......@@ -834,6 +834,24 @@ ExternalReference ExternalReference::ForDeoptEntry(Address entry) {
return ExternalReference(entry);
}
bool ExternalReference::IsAddressableThroughRootRegister(
Isolate* isolate) const {
Address start = reinterpret_cast<Address>(isolate);
Address end = isolate->heap()->root_register_addressable_end();
return start <= address_ && address_ < end;
}
intptr_t ExternalReference::OffsetFromRootRegister(Isolate* isolate) const {
DCHECK(IsAddressableThroughRootRegister(isolate));
#ifdef V8_TARGET_ARCH_X64
return static_cast<intptr_t>(address_) - kRootRegisterBias -
reinterpret_cast<intptr_t>(isolate->heap()->roots_array_start());
#else
return static_cast<intptr_t>(address_) -
reinterpret_cast<intptr_t>(isolate->heap()->roots_array_start());
#endif
}
ExternalReference ExternalReference::cpu_features() {
DCHECK(CpuFeatures::initialized_);
return ExternalReference(&CpuFeatures::supported_);
......
......@@ -285,6 +285,11 @@ class ExternalReference BASE_EMBEDDED {
Address address() const { return address_; }
// An address is addressable through kRootRegister if it is located within
// [isolate, roots_ + root_register_addressable_end_offset[.
bool IsAddressableThroughRootRegister(Isolate* isolate) const;
intptr_t OffsetFromRootRegister(Isolate* isolate) const;
private:
explicit ExternalReference(Address address) : address_(address) {}
......
......@@ -1099,6 +1099,11 @@ class Heap {
return kRootsBuiltinsOffset;
}
Address root_register_addressable_end() {
return reinterpret_cast<Address>(roots_array_start()) +
kRootRegisterAddressableEndOffset;
}
// Sets the stub_cache_ (only used when expanding the dictionary).
void SetRootCodeStubs(SimpleNumberDictionary* value);
......@@ -2216,6 +2221,12 @@ class Heap {
ExternalReferenceTable::SizeInBytes();
Object* builtins_[Builtins::builtin_count];
// kRootRegister may be used to address any location that starts at the
// Isolate and ends at this point. Fields past this point are not guaranteed
// to live at a static offset from kRootRegister.
static constexpr int kRootRegisterAddressableEndOffset =
kRootsBuiltinsOffset + Builtins::builtin_count * kPointerSize;
size_t code_range_size_;
size_t max_semi_space_size_;
size_t initial_semispace_size_;
......
......@@ -3623,6 +3623,15 @@ void TurboAssembler::LoadBuiltin(Register destination, int builtin_index) {
Heap::roots_to_builtins_offset() + builtin_index * kPointerSize;
lw(destination, MemOperand(kRootRegister, roots_to_builtins_offset));
}
void TurboAssembler::LoadRootRegisterOffset(Register destination,
intptr_t offset) {
if (offset == 0) {
Move(destination, kRootRegister);
} else {
Addu(destination, kRootRegister, offset);
}
}
#endif // V8_EMBEDDED_BUILTINS
void TurboAssembler::Jump(Register target, int16_t offset, Condition cond,
......
......@@ -251,6 +251,7 @@ class TurboAssembler : public TurboAssemblerBase {
void LoadExternalReference(Register destination,
int reference_index) override;
void LoadBuiltin(Register destination, int builtin_index) override;
void LoadRootRegisterOffset(Register destination, intptr_t offset) override;
#endif // V8_EMBEDDED_BUILTINS
// Jump, Call, and Ret pseudo instructions implementing inter-working.
......
......@@ -4132,6 +4132,15 @@ void TurboAssembler::LoadBuiltin(Register destination, int builtin_index) {
Heap::roots_to_builtins_offset() + builtin_index * kPointerSize;
Ld(destination, MemOperand(kRootRegister, roots_to_builtins_offset));
}
void TurboAssembler::LoadRootRegisterOffset(Register destination,
intptr_t offset) {
if (offset == 0) {
Move(destination, kRootRegister);
} else {
Daddu(destination, kRootRegister, Operand(offset));
}
}
#endif // V8_EMBEDDED_BUILTINS
void TurboAssembler::Jump(Register target, Condition cond, Register rs,
......
......@@ -271,6 +271,7 @@ class TurboAssembler : public TurboAssemblerBase {
void LoadExternalReference(Register destination,
int reference_index) override;
void LoadBuiltin(Register destination, int builtin_index) override;
void LoadRootRegisterOffset(Register destination, intptr_t offset) override;
#endif // V8_EMBEDDED_BUILTINS
// Jump, Call, and Ret pseudo instructions implementing inter-working.
......
......@@ -67,16 +67,22 @@ void TurboAssemblerBase::IndirectLoadExternalReference(
CHECK(isolate()->ShouldLoadConstantsFromRootList());
CHECK(root_array_available_);
// Encode as an index into the external reference table stored on the isolate.
ExternalReferenceEncoder encoder(isolate());
ExternalReferenceEncoder::Value v = encoder.Encode(reference.address());
CHECK(!v.is_from_api());
if (reference.IsAddressableThroughRootRegister(isolate())) {
// Some external references can be efficiently loaded as an offset from
// kRootRegister.
intptr_t offset = reference.OffsetFromRootRegister(isolate());
LoadRootRegisterOffset(destination, offset);
} else {
// Otherwise, do a memory load from the external reference table.
// TODO(jgruber, v8:6666): Addresses within the isolate can be loaded through
// an offset from the roots pointer, skipping one level of indirection.
// Encode as an index into the external reference table stored on the
// isolate.
ExternalReferenceEncoder encoder(isolate());
ExternalReferenceEncoder::Value v = encoder.Encode(reference.address());
CHECK(!v.is_from_api());
LoadExternalReference(destination, v.index());
LoadExternalReference(destination, v.index());
}
}
#endif // V8_EMBEDDED_BUILTINS
......
......@@ -45,6 +45,8 @@ class TurboAssemblerBase : public Assembler {
virtual void LoadExternalReference(Register destination,
int reference_index) = 0;
virtual void LoadBuiltin(Register destination, int builtin_index) = 0;
virtual void LoadRootRegisterOffset(Register destination,
intptr_t offset) = 0;
#endif // V8_EMBEDDED_BUILTINS
virtual void LoadRoot(Register destination, Heap::RootListIndex index) = 0;
......
......@@ -172,6 +172,16 @@ void TurboAssembler::LoadBuiltin(Register destination, int builtin_index) {
movp(destination, Operand(kRootRegister, roots_to_builtins_offset));
}
void TurboAssembler::LoadRootRegisterOffset(Register destination,
intptr_t offset) {
DCHECK(is_int32(offset));
if (offset == 0) {
Move(destination, kRootRegister);
} else {
leap(destination, Operand(kRootRegister, static_cast<int32_t>(offset)));
}
}
#endif // V8_EMBEDDED_BUILTINS
void TurboAssembler::LoadAddress(Register destination,
......
......@@ -366,6 +366,7 @@ class TurboAssembler : public TurboAssemblerBase {
void LoadBuiltin(Register destination, int builtin_index) override;
void LoadExternalReference(Register destination,
int reference_index) override;
void LoadRootRegisterOffset(Register destination, intptr_t offset) override;
#endif // V8_EMBEDDED_BUILTINS
// Operand pointing to an external reference.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment