Commit 48490149 authored by Igor Sheludko's avatar Igor Sheludko Committed by V8 LUCI CQ

[ext-code-space] Fix external code range allocation logic

... by
1) using platform-specific kMaxPCRelativeCodeRangeInMB constant
   instead of fixed 2GB for computing a region around embedded builtins
   from which the builtins could be reachable by pc-relative call/jump
   instructions,
2) remapping builtins into the code range if the latter happened to be
   allocated too far from embedded builtins (so that the pc-relative
   calls/jumps can't reach the embedded builtins blob).

Bug: v8:11880
Change-Id: I3c8df6836a8f0156d5360edd9c4ae8c295ec7100
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3270543Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Reviewed-by: 's avatarMichael Lippautz <mlippautz@chromium.org>
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/main@{#77837}
parent a3277080
......@@ -104,8 +104,15 @@ STATIC_ASSERT(V8_DEFAULT_STACK_SIZE_KB* KB +
kStackLimitSlackForDeoptimizationInBytes <=
MB);
#if defined(V8_SHORT_BUILTIN_CALLS) && \
(!defined(V8_COMPRESS_POINTERS) || defined(V8_EXTERNAL_CODE_SPACE))
// The V8_ENABLE_NEAR_CODE_RANGE_BOOL enables logic that tries to allocate
// code range within a pc-relative call/jump proximity from embedded builtins.
// This machinery could help only when we have an opportunity to choose where
// to allocate code range and could benefit from it. This is the case for the
// following configurations:
// - external code space AND pointer compression are enabled,
// - short builtin calls feature is enabled while pointer compression is not.
#if (defined(V8_SHORT_BUILTIN_CALLS) && !defined(V8_COMPRESS_POINTERS)) || \
defined(V8_EXTERNAL_CODE_SPACE)
#define V8_ENABLE_NEAR_CODE_RANGE_BOOL true
#else
#define V8_ENABLE_NEAR_CODE_RANGE_BOOL false
......@@ -115,11 +122,6 @@ STATIC_ASSERT(V8_DEFAULT_STACK_SIZE_KB* KB +
// physical memory by checking the max old space size.
const size_t kShortBuiltinCallsOldSpaceSizeThreshold = size_t{2} * GB;
// This constant is used for detecting whether code range could be
// allocated within the +/- 2GB boundary to builtins' embedded blob
// to use short builtin calls.
const size_t kShortBuiltinCallsBoundary = size_t{2} * GB;
// Determine whether dict mode prototypes feature is enabled.
#ifdef V8_ENABLE_SWISS_NAME_DICTIONARY
#define V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL true
......
......@@ -7,6 +7,7 @@
#include <stdlib.h>
#include <atomic>
#include <cstdint>
#include <fstream>
#include <memory>
#include <sstream>
......@@ -367,8 +368,22 @@ uint32_t Isolate::CurrentEmbeddedBlobDataSize() {
std::memory_order::memory_order_relaxed);
}
// static
base::AddressRegion Isolate::GetShortBuiltinsCallRegion() {
DCHECK_LT(CurrentEmbeddedBlobCodeSize(), kShortBuiltinCallsBoundary);
// Update calculations below if the assert fails.
STATIC_ASSERT(kMaxPCRelativeCodeRangeInMB <= 4096);
if (kMaxPCRelativeCodeRangeInMB == 0) {
// Return empty region if pc-relative calls/jumps are not supported.
return base::AddressRegion(kNullAddress, 0);
}
constexpr size_t max_size = std::numeric_limits<size_t>::max();
if (uint64_t{kMaxPCRelativeCodeRangeInMB} * MB > max_size) {
// The whole addressable space is reachable with pc-relative calls/jumps.
return base::AddressRegion(kNullAddress, max_size);
}
constexpr size_t radius = kMaxPCRelativeCodeRangeInMB * MB;
DCHECK_LT(CurrentEmbeddedBlobCodeSize(), radius);
Address embedded_blob_code_start =
reinterpret_cast<Address>(CurrentEmbeddedBlobCode());
if (embedded_blob_code_start == kNullAddress) {
......@@ -378,10 +393,11 @@ base::AddressRegion Isolate::GetShortBuiltinsCallRegion() {
Address embedded_blob_code_end =
embedded_blob_code_start + CurrentEmbeddedBlobCodeSize();
Address region_start =
(embedded_blob_code_end > kShortBuiltinCallsBoundary)
? (embedded_blob_code_end - kShortBuiltinCallsBoundary)
: 0;
Address region_end = embedded_blob_code_start + kShortBuiltinCallsBoundary;
(embedded_blob_code_end > radius) ? (embedded_blob_code_end - radius) : 0;
Address region_end = embedded_blob_code_start + radius;
if (region_end < embedded_blob_code_start) {
region_end = static_cast<Address>(-1);
}
return base::AddressRegion(region_start, region_end - region_start);
}
......@@ -3518,8 +3534,13 @@ void Isolate::CreateAndSetEmbeddedBlob() {
}
void Isolate::MaybeRemapEmbeddedBuiltinsIntoCodeRange() {
if (!is_short_builtin_calls_enabled() || V8_ENABLE_NEAR_CODE_RANGE_BOOL ||
!RequiresCodeRange()) {
if (!is_short_builtin_calls_enabled() || !RequiresCodeRange()) {
return;
}
if (V8_ENABLE_NEAR_CODE_RANGE_BOOL &&
GetShortBuiltinsCallRegion().contains(heap_.code_region())) {
// The embedded builtins are within the pc-relative reach from the code
// range, so there's no need to remap embedded builtins.
return;
}
......@@ -3752,10 +3773,10 @@ bool Isolate::Init(SnapshotData* startup_snapshot_data,
}
}
if (V8_ENABLE_NEAR_CODE_RANGE_BOOL) {
// When enable short builtin calls by near code range, the
// code range should be close (<2GB) to the embedded blob to use
// pc-relative calls.
is_short_builtin_calls_enabled_ =
// The short builtin calls could still be enabled if allocated code range
// is close enough to embedded builtins so that the latter could be
// reached using pc-relative (short) calls/jumps.
is_short_builtin_calls_enabled_ |=
GetShortBuiltinsCallRegion().contains(heap_.code_region());
}
}
......
......@@ -1636,8 +1636,9 @@ class V8_EXPORT_PRIVATE Isolate final : private HiddenFactory {
return V8_SHORT_BUILTIN_CALLS_BOOL && is_short_builtin_calls_enabled_;
}
// Returns a region from which it's possible to make short calls/jumps to
// embedded builtins or empty region if there's no embedded blob.
// Returns a region from which it's possible to make pc-relative (short)
// calls/jumps to embedded builtins or empty region if there's no embedded
// blob or if pc-relative calls are not supported.
static base::AddressRegion GetShortBuiltinsCallRegion();
void set_array_buffer_allocator(v8::ArrayBuffer::Allocator* allocator) {
......
......@@ -21,7 +21,7 @@ namespace internal {
class CodeRangeAddressHint {
public:
// When near code range is enabled, an address within
// kShortBuiltinCallsBoundary to the embedded blob is returned if
// kMaxPCRelativeCodeRangeInMB to the embedded blob is returned if
// there is enough space. Otherwise a random address is returned.
// When near code range is disabled, returns the most recently freed code
// range start address for the given size. If there is no such entry, then a
......
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