Commit 1403fd7d authored by Clemens Backes's avatar Clemens Backes Committed by Commit Bot

[wasm] Avoid unnecessary jump tables

If multiple code spaces are created, each of them currently gets its own
jump table (on 64 bit platforms). Since we try to allocate new code
spaces right after existing ones, this is often not necessary. We could
instead reuse the existing jump table(s).
This saves code space for the unneeded jump tables and avoid the cost of
patching the redundant jump tables when we replace code objects.

This CL implements this by checking whether an existing jump table (or
pair of far jump table and (near) jump table) fully covers a new code
space, and reuses the existing jump table in that case.

R=ahaas@chromium.org

Change-Id: Id8751b9c4036cf8f85f9baa2b0be8b2cfb5716ff
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2043846Reviewed-by: 's avatarAndreas Haas <ahaas@chromium.org>
Commit-Queue: Clemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#66364}
parent 01fbaed0
...@@ -66,6 +66,16 @@ class AddressRegion { ...@@ -66,6 +66,16 @@ class AddressRegion {
}; };
ASSERT_TRIVIALLY_COPYABLE(AddressRegion); ASSERT_TRIVIALLY_COPYABLE(AddressRegion);
// Construct an AddressRegion from anything providing a {data()} and {size()}
// accessor.
template <typename Container,
typename = decltype(std::declval<Container>().data()),
typename = decltype(std::declval<Container>().size())>
inline constexpr AddressRegion AddressRegionOf(Container&& c) {
return AddressRegion{reinterpret_cast<AddressRegion::Address>(c.data()),
sizeof(*c.data()) * c.size()};
}
inline std::ostream& operator<<(std::ostream& out, AddressRegion region) { inline std::ostream& operator<<(std::ostream& out, AddressRegion region) {
return out << "[" << reinterpret_cast<void*>(region.begin()) << "+" return out << "[" << reinterpret_cast<void*>(region.begin()) << "+"
<< region.size() << "]"; << region.size() << "]";
......
...@@ -71,6 +71,9 @@ class Vector { ...@@ -71,6 +71,9 @@ class Vector {
// Returns a pointer to the start of the data in the vector. // Returns a pointer to the start of the data in the vector.
constexpr T* begin() const { return start_; } constexpr T* begin() const { return start_; }
// For consistency with other containers, do also provide a {data} accessor.
constexpr T* data() const { return start_; }
// Returns a pointer past the end of the data in the vector. // Returns a pointer past the end of the data in the vector.
constexpr T* end() const { return start_ + length_; } constexpr T* end() const { return start_ + length_; }
......
This diff is collapsed.
...@@ -462,23 +462,25 @@ class V8_EXPORT_PRIVATE NativeModule final { ...@@ -462,23 +462,25 @@ class V8_EXPORT_PRIVATE NativeModule final {
Address GetCallTargetForFunction(uint32_t func_index) const; Address GetCallTargetForFunction(uint32_t func_index) const;
struct JumpTablesRef { struct JumpTablesRef {
const Address jump_table_start; const Address jump_table_start = kNullAddress;
const Address far_jump_table_start; const Address far_jump_table_start = kNullAddress;
bool is_valid() const { return far_jump_table_start != kNullAddress; }
}; };
// Finds the jump tables that should be used for the code at {code_addr}. This // Finds the jump tables that should be used for given code region. This
// information is then passed to {GetNearCallTargetForFunction} and // information is then passed to {GetNearCallTargetForFunction} and
// {GetNearRuntimeStubEntry} to avoid the overhead of looking this information // {GetNearRuntimeStubEntry} to avoid the overhead of looking this information
// up there. // up there. Return an empty struct if no suitable jump tables exist.
JumpTablesRef FindJumpTablesForCode(Address code_addr) const; JumpTablesRef FindJumpTablesForRegion(base::AddressRegion) const;
// Similarly to {GetCallTargetForFunction}, but uses the jump table previously // Similarly to {GetCallTargetForFunction}, but uses the jump table previously
// looked up via {FindJumpTablesForCode}. // looked up via {FindJumpTablesForRegion}.
Address GetNearCallTargetForFunction(uint32_t func_index, Address GetNearCallTargetForFunction(uint32_t func_index,
const JumpTablesRef&) const; const JumpTablesRef&) const;
// Get a runtime stub entry (which is a far jump table slot) in the jump table // Get a runtime stub entry (which is a far jump table slot) in the jump table
// previously looked up via {FindJumpTablesForCode}. // previously looked up via {FindJumpTablesForRegion}.
Address GetNearRuntimeStubEntry(WasmCode::RuntimeStubId index, Address GetNearRuntimeStubEntry(WasmCode::RuntimeStubId index,
const JumpTablesRef&) const; const JumpTablesRef&) const;
......
...@@ -540,8 +540,8 @@ bool NativeModuleDeserializer::ReadCode(uint32_t fn_index, Reader* reader) { ...@@ -540,8 +540,8 @@ bool NativeModuleDeserializer::ReadCode(uint32_t fn_index, Reader* reader) {
RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) | RelocInfo::ModeMask(RelocInfo::EXTERNAL_REFERENCE) |
RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) | RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE) |
RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED); RelocInfo::ModeMask(RelocInfo::INTERNAL_REFERENCE_ENCODED);
auto jump_tables_ref = auto jump_tables_ref = native_module_->FindJumpTablesForRegion(
native_module_->FindJumpTablesForCode(code->instruction_start()); base::AddressRegionOf(code->instructions()));
for (RelocIterator iter(code->instructions(), code->reloc_info(), for (RelocIterator iter(code->instructions(), code->reloc_info(),
code->constant_pool(), mask); code->constant_pool(), mask);
!iter.done(); iter.next()) { !iter.done(); iter.next()) {
......
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