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) { ...@@ -173,6 +173,15 @@ void TurboAssembler::LoadBuiltin(Register destination, int builtin_index) {
ldr(destination, MemOperand(kRootRegister, roots_to_builtins_offset)); 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 #endif // V8_EMBEDDED_BUILTINS
void TurboAssembler::Jump(Register target, Condition cond) { bx(target, cond); } void TurboAssembler::Jump(Register target, Condition cond) { bx(target, cond); }
......
...@@ -322,6 +322,7 @@ class TurboAssembler : public TurboAssemblerBase { ...@@ -322,6 +322,7 @@ class TurboAssembler : public TurboAssemblerBase {
void LoadExternalReference(Register destination, void LoadExternalReference(Register destination,
int reference_index) override; int reference_index) override;
void LoadBuiltin(Register destination, int builtin_index) override; void LoadBuiltin(Register destination, int builtin_index) override;
void LoadRootRegisterOffset(Register destination, intptr_t offset) override;
#endif // V8_EMBEDDED_BUILTINS #endif // V8_EMBEDDED_BUILTINS
// Returns the size of a call in instructions. Note, the value returned is // 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) { ...@@ -1891,6 +1891,15 @@ void TurboAssembler::LoadBuiltin(Register destination, int builtin_index) {
Heap::roots_to_builtins_offset() + builtin_index * kPointerSize; Heap::roots_to_builtins_offset() + builtin_index * kPointerSize;
Ldr(destination, MemOperand(kRootRegister, roots_to_builtins_offset)); 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 #endif // V8_EMBEDDED_BUILTINS
void TurboAssembler::Jump(Register target, Condition cond) { void TurboAssembler::Jump(Register target, Condition cond) {
......
...@@ -880,6 +880,7 @@ class TurboAssembler : public TurboAssemblerBase { ...@@ -880,6 +880,7 @@ class TurboAssembler : public TurboAssemblerBase {
void LoadExternalReference(Register destination, void LoadExternalReference(Register destination,
int reference_index) override; int reference_index) override;
void LoadBuiltin(Register destination, int builtin_index) override; void LoadBuiltin(Register destination, int builtin_index) override;
void LoadRootRegisterOffset(Register destination, intptr_t offset) override;
#endif // V8_EMBEDDED_BUILTINS #endif // V8_EMBEDDED_BUILTINS
void Jump(Register target, Condition cond = al); void Jump(Register target, Condition cond = al);
......
...@@ -834,6 +834,24 @@ ExternalReference ExternalReference::ForDeoptEntry(Address entry) { ...@@ -834,6 +834,24 @@ ExternalReference ExternalReference::ForDeoptEntry(Address entry) {
return ExternalReference(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() { ExternalReference ExternalReference::cpu_features() {
DCHECK(CpuFeatures::initialized_); DCHECK(CpuFeatures::initialized_);
return ExternalReference(&CpuFeatures::supported_); return ExternalReference(&CpuFeatures::supported_);
......
...@@ -285,6 +285,11 @@ class ExternalReference BASE_EMBEDDED { ...@@ -285,6 +285,11 @@ class ExternalReference BASE_EMBEDDED {
Address address() const { return address_; } 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: private:
explicit ExternalReference(Address address) : address_(address) {} explicit ExternalReference(Address address) : address_(address) {}
......
...@@ -1099,6 +1099,11 @@ class Heap { ...@@ -1099,6 +1099,11 @@ class Heap {
return kRootsBuiltinsOffset; 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). // Sets the stub_cache_ (only used when expanding the dictionary).
void SetRootCodeStubs(SimpleNumberDictionary* value); void SetRootCodeStubs(SimpleNumberDictionary* value);
...@@ -2216,6 +2221,12 @@ class Heap { ...@@ -2216,6 +2221,12 @@ class Heap {
ExternalReferenceTable::SizeInBytes(); ExternalReferenceTable::SizeInBytes();
Object* builtins_[Builtins::builtin_count]; 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 code_range_size_;
size_t max_semi_space_size_; size_t max_semi_space_size_;
size_t initial_semispace_size_; size_t initial_semispace_size_;
......
...@@ -3623,6 +3623,15 @@ void TurboAssembler::LoadBuiltin(Register destination, int builtin_index) { ...@@ -3623,6 +3623,15 @@ void TurboAssembler::LoadBuiltin(Register destination, int builtin_index) {
Heap::roots_to_builtins_offset() + builtin_index * kPointerSize; Heap::roots_to_builtins_offset() + builtin_index * kPointerSize;
lw(destination, MemOperand(kRootRegister, roots_to_builtins_offset)); 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 #endif // V8_EMBEDDED_BUILTINS
void TurboAssembler::Jump(Register target, int16_t offset, Condition cond, void TurboAssembler::Jump(Register target, int16_t offset, Condition cond,
......
...@@ -251,6 +251,7 @@ class TurboAssembler : public TurboAssemblerBase { ...@@ -251,6 +251,7 @@ class TurboAssembler : public TurboAssemblerBase {
void LoadExternalReference(Register destination, void LoadExternalReference(Register destination,
int reference_index) override; int reference_index) override;
void LoadBuiltin(Register destination, int builtin_index) override; void LoadBuiltin(Register destination, int builtin_index) override;
void LoadRootRegisterOffset(Register destination, intptr_t offset) override;
#endif // V8_EMBEDDED_BUILTINS #endif // V8_EMBEDDED_BUILTINS
// Jump, Call, and Ret pseudo instructions implementing inter-working. // Jump, Call, and Ret pseudo instructions implementing inter-working.
......
...@@ -4132,6 +4132,15 @@ void TurboAssembler::LoadBuiltin(Register destination, int builtin_index) { ...@@ -4132,6 +4132,15 @@ void TurboAssembler::LoadBuiltin(Register destination, int builtin_index) {
Heap::roots_to_builtins_offset() + builtin_index * kPointerSize; Heap::roots_to_builtins_offset() + builtin_index * kPointerSize;
Ld(destination, MemOperand(kRootRegister, roots_to_builtins_offset)); 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 #endif // V8_EMBEDDED_BUILTINS
void TurboAssembler::Jump(Register target, Condition cond, Register rs, void TurboAssembler::Jump(Register target, Condition cond, Register rs,
......
...@@ -271,6 +271,7 @@ class TurboAssembler : public TurboAssemblerBase { ...@@ -271,6 +271,7 @@ class TurboAssembler : public TurboAssemblerBase {
void LoadExternalReference(Register destination, void LoadExternalReference(Register destination,
int reference_index) override; int reference_index) override;
void LoadBuiltin(Register destination, int builtin_index) override; void LoadBuiltin(Register destination, int builtin_index) override;
void LoadRootRegisterOffset(Register destination, intptr_t offset) override;
#endif // V8_EMBEDDED_BUILTINS #endif // V8_EMBEDDED_BUILTINS
// Jump, Call, and Ret pseudo instructions implementing inter-working. // Jump, Call, and Ret pseudo instructions implementing inter-working.
......
...@@ -67,16 +67,22 @@ void TurboAssemblerBase::IndirectLoadExternalReference( ...@@ -67,16 +67,22 @@ void TurboAssemblerBase::IndirectLoadExternalReference(
CHECK(isolate()->ShouldLoadConstantsFromRootList()); CHECK(isolate()->ShouldLoadConstantsFromRootList());
CHECK(root_array_available_); 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
ExternalReferenceEncoder encoder(isolate()); // kRootRegister.
ExternalReferenceEncoder::Value v = encoder.Encode(reference.address()); intptr_t offset = reference.OffsetFromRootRegister(isolate());
CHECK(!v.is_from_api()); 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 // Encode as an index into the external reference table stored on the
// an offset from the roots pointer, skipping one level of indirection. // 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 #endif // V8_EMBEDDED_BUILTINS
......
...@@ -45,6 +45,8 @@ class TurboAssemblerBase : public Assembler { ...@@ -45,6 +45,8 @@ class TurboAssemblerBase : public Assembler {
virtual void LoadExternalReference(Register destination, virtual void LoadExternalReference(Register destination,
int reference_index) = 0; int reference_index) = 0;
virtual void LoadBuiltin(Register destination, int builtin_index) = 0; virtual void LoadBuiltin(Register destination, int builtin_index) = 0;
virtual void LoadRootRegisterOffset(Register destination,
intptr_t offset) = 0;
#endif // V8_EMBEDDED_BUILTINS #endif // V8_EMBEDDED_BUILTINS
virtual void LoadRoot(Register destination, Heap::RootListIndex index) = 0; virtual void LoadRoot(Register destination, Heap::RootListIndex index) = 0;
......
...@@ -172,6 +172,16 @@ void TurboAssembler::LoadBuiltin(Register destination, int builtin_index) { ...@@ -172,6 +172,16 @@ void TurboAssembler::LoadBuiltin(Register destination, int builtin_index) {
movp(destination, Operand(kRootRegister, roots_to_builtins_offset)); 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 #endif // V8_EMBEDDED_BUILTINS
void TurboAssembler::LoadAddress(Register destination, void TurboAssembler::LoadAddress(Register destination,
......
...@@ -366,6 +366,7 @@ class TurboAssembler : public TurboAssemblerBase { ...@@ -366,6 +366,7 @@ class TurboAssembler : public TurboAssemblerBase {
void LoadBuiltin(Register destination, int builtin_index) override; void LoadBuiltin(Register destination, int builtin_index) override;
void LoadExternalReference(Register destination, void LoadExternalReference(Register destination,
int reference_index) override; int reference_index) override;
void LoadRootRegisterOffset(Register destination, intptr_t offset) override;
#endif // V8_EMBEDDED_BUILTINS #endif // V8_EMBEDDED_BUILTINS
// Operand pointing to an external reference. // 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