From 46f72577a427e24f2d7d4fedf7c02c665dde2b9a Mon Sep 17 00:00:00 2001 From: Dan McDonald Date: Wed, 16 Apr 2025 10:03:49 -0400 Subject: [PATCH] deps: patch V8 for illumos illumos pointers are VA48, can allocate from the top of the 64-bit range as well. PR-URL: https://github.com/nodejs/node/pull/59805 Reviewed-By: Filip Skokan Reviewed-By: Richard Lau Reviewed-By: Ruben Bridgewater Reviewed-By: Colin Ihrig Reviewed-By: Joyee Cheung Reviewed-By: Yagiz Nizipli --- common.gypi | 2 +- deps/v8/src/codegen/code-stub-assembler.cc | 9 +++++++++ deps/v8/src/sandbox/js-dispatch-table-inl.h | 15 +++++++++++++++ deps/v8/src/sandbox/js-dispatch-table.h | 15 +++++++++++++++ 4 files changed, 40 insertions(+), 1 deletion(-) diff --git a/common.gypi b/common.gypi index ae5b995559..891f498138 100644 --- a/common.gypi +++ b/common.gypi @@ -38,7 +38,7 @@ # Reset this number to 0 on major V8 upgrades. # Increment by one for each non-official patch applied to deps/v8. - 'v8_embedder_string': '-node.4', + 'v8_embedder_string': '-node.5', ##### V8 defaults for Node.js ##### diff --git a/deps/v8/src/codegen/code-stub-assembler.cc b/deps/v8/src/codegen/code-stub-assembler.cc index 9269f9623e..fceedaa540 100644 --- a/deps/v8/src/codegen/code-stub-assembler.cc +++ b/deps/v8/src/codegen/code-stub-assembler.cc @@ -2043,7 +2043,16 @@ TNode CodeStubAssembler::LoadCodeObjectFromJSDispatchTable( TNode shifted_value; if (JSDispatchEntry::kObjectPointerOffset == 0) { shifted_value = +#if defined(__illumos__) && defined(V8_HOST_ARCH_64_BIT) + // Pointers in illumos span both the low 2^47 range and the high 2^47 range + // as well. Checking the high bit being set in illumos means all higher bits + // need to be set to 1 after shifting right. + // Use WordSar() so any high-bit check wouldn't be necessary. + UncheckedCast(WordSar(UncheckedCast(value), + IntPtrConstant(JSDispatchEntry::kObjectPointerShift))); +#else WordShr(value, UintPtrConstant(JSDispatchEntry::kObjectPointerShift)); +#endif /* __illumos__ and 64-bit */ } else { shifted_value = UintPtrAdd( WordShr(value, UintPtrConstant(JSDispatchEntry::kObjectPointerShift)), diff --git a/deps/v8/src/sandbox/js-dispatch-table-inl.h b/deps/v8/src/sandbox/js-dispatch-table-inl.h index 94ee761a15..072ff2387e 100644 --- a/deps/v8/src/sandbox/js-dispatch-table-inl.h +++ b/deps/v8/src/sandbox/js-dispatch-table-inl.h @@ -25,6 +25,7 @@ void JSDispatchEntry::MakeJSDispatchEntry(Address object, Address entrypoint, uint16_t parameter_count, bool mark_as_alive) { DCHECK_EQ(object & kHeapObjectTag, 0); +#if !defined(__illumos__) || !defined(V8_TARGET_ARCH_64_BIT) DCHECK_EQ((((object - kObjectPointerOffset) << kObjectPointerShift) >> kObjectPointerShift) + kObjectPointerOffset, @@ -32,6 +33,7 @@ void JSDispatchEntry::MakeJSDispatchEntry(Address object, Address entrypoint, DCHECK_EQ((object - kObjectPointerOffset) + kObjectPointerOffset, object); DCHECK_LT((object - kObjectPointerOffset), 1ULL << ((sizeof(encoded_word_) * 8) - kObjectPointerShift)); +#endif /* __illumos__ & 64-bit */ Address payload = ((object - kObjectPointerOffset) << kObjectPointerShift) | (parameter_count & kParameterCountMask); @@ -57,8 +59,16 @@ Address JSDispatchEntry::GetCodePointer() const { // and so may be 0 or 1 here. As the return value is a tagged pointer, the // bit must be 1 when returned, so we need to set it here. Address payload = encoded_word_.load(std::memory_order_acquire); +#if defined(__illumos__) && defined(V8_TARGET_ARCH_64_BIT) + // Unsigned types won't sign-extend on shift-right, but we need to do + // this with illumos VA48 addressing. + DCHECK_EQ(kObjectPointerOffset, 0); + return (Address)((intptr_t)payload >> (int)kObjectPointerShift) | + kHeapObjectTag; +#else return ((payload >> kObjectPointerShift) + kObjectPointerOffset) | kHeapObjectTag; +#endif /* __illumos__ & 64-bit */ } Tagged JSDispatchEntry::GetCode() const { @@ -216,7 +226,12 @@ void JSDispatchEntry::MakeFreelistEntry(uint32_t next_entry_index) { bool JSDispatchEntry::IsFreelistEntry() const { #ifdef V8_TARGET_ARCH_64_BIT auto entrypoint = entrypoint_.load(std::memory_order_relaxed); +#ifdef __illumos__ + // See the illumos definition of kFreeEntryTag for why we have to do this. + return (entrypoint & 0xffff000000000000ull) == kFreeEntryTag; +#else return (entrypoint & kFreeEntryTag) == kFreeEntryTag; +#endif /* __illumos__ */ #else return next_free_entry_.load(std::memory_order_relaxed) != 0; #endif diff --git a/deps/v8/src/sandbox/js-dispatch-table.h b/deps/v8/src/sandbox/js-dispatch-table.h index f786118980..140c311e62 100644 --- a/deps/v8/src/sandbox/js-dispatch-table.h +++ b/deps/v8/src/sandbox/js-dispatch-table.h @@ -90,7 +90,22 @@ struct JSDispatchEntry { #if defined(V8_TARGET_ARCH_64_BIT) // Freelist entries contain the index of the next free entry in their lower 32 // bits and are tagged with this tag. +#ifdef __illumos__ + // In illumos 64-bit apps, pointers are allocated both the bottom 2^47 range + // AND the top 2^47 range in the 64-bit space. Instead of 47 bits of VA space + // we have 48 bits. This means, however, the top 16-bits may be 0xffff. We + // therefore pick a different value for the kFreeEntryTag. If/when we go to + // VA57, aka 5-level paging, we'll need to revisit this again, as will node + // by default, since the fixed-bits on the high end will shrink from top + // 16-bits to top 8-bits. + // + // Unless illumos ships an Oracle-Solaris-like VA47 link-time options to + // restrict pointers from allocating from above the Virtual Address hole, + // we need to be mindful of this. + static constexpr Address kFreeEntryTag = 0xfeed000000000000ull; +#else static constexpr Address kFreeEntryTag = 0xffff000000000000ull; +#endif /* __illumos__ */ #ifdef V8_TARGET_BIG_ENDIAN // 2-byte parameter count is on the least significant side of encoded_word_. static constexpr int kBigEndianParamCountOffset =