[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: Michael Starzinger <mstarzinger@chromium.org> Cr-Commit-Position: refs/heads/master@{#53661}
This commit is contained in:
parent
964f11b6ac
commit
13fc4a1b3d
@ -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.
|
||||
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.
|
||||
|
||||
ExternalReferenceEncoder encoder(isolate());
|
||||
ExternalReferenceEncoder::Value v = encoder.Encode(reference.address());
|
||||
CHECK(!v.is_from_api());
|
||||
// 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());
|
||||
|
||||
// TODO(jgruber, v8:6666): Addresses within the isolate can be loaded through
|
||||
// an offset from the roots pointer, skipping one level of indirection.
|
||||
|
||||
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.
|
||||
|
Loading…
Reference in New Issue
Block a user