Skip to content

Commit decb43f

Browse files
abmusseV8 LUCI CQ
authored andcommitted
[aix/ibmi] fix leaptiering crash
After enabling leaptiering by default I discovered a crash with mksnapshot. I rebuilt with DCHECKs enabled by setting: v8_enable_debugging_features = true This revealed a DCHECK error while running mksnapshot at: ```sh ./mksnapshot \ --turbo_instruction_scheduling \ --stress-turbo-late-spilling \ --target_os=aix \ --target_arch=ppc64 \ --embedded_src gen/embedded.S \ --predictable \ --no-use-ic \ --embedded_variant Default \ --random-seed 314159265 \ --startup_blob snapshot_blob.bin \ --native-code-counters \ --concurrent-builtin-generation \ --concurrent-turbofan-max-threads=0 \ --verify-heap ``` https://source.chromium.org/chromium/chromium/src/+/main:v8/src/sandbox/js-dispatch-table-inl.h;l=24 In the DCHECK above looks like kObjectPointerShift is set to 16 and purpose of the check is to ensure the top 16 bits (2 bytes) are empty. From what I understand mmap will give you back an address in 0x0A.... segment on AIX 0x0A00000000000000 - 0x0AFFFFFFFFFFFFFFF More details: https://www.ibm.com/docs/en/aix/7.2?topic=memory-1-tb-segment-aliasing So there will be something set in the upper bits there leading to garbage results once the bits get shuffled around. I did some additional investigation and its looks like golang ran into a similar problem on AIX and uses offsets https://github.com/golang/go/blob/28d7eec3a23c04fb74863d032d499b76c3c3d4c3/src/runtime/malloc.go#L300-L304 My solution here is to introduce similar offset solution by adding kObjectPointerOffset to the JSDispatchEntry struct. Change-Id: I67ad82f78d763bd35ad90d6c45c8f123d28022fe Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/6320599 Reviewed-by: Olivier Flückiger <[email protected]> Reviewed-by: Samuel Groß <[email protected]> Commit-Queue: Samuel Groß <[email protected]> Cr-Commit-Position: refs/heads/main@{#100011}
1 parent 4f1eda2 commit decb43f

3 files changed

Lines changed: 40 additions & 9 deletions

File tree

src/codegen/code-stub-assembler.cc

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1984,9 +1984,19 @@ TNode<Code> CodeStubAssembler::LoadCodeObjectFromJSDispatchTable(
19841984
TNode<UintPtrT> value = Load<UintPtrT>(table, offset);
19851985
// The LSB is used as marking bit by the js dispatch table, so here we have
19861986
// to set it using a bitwise OR as it may or may not be set.
1987-
value = UncheckedCast<UintPtrT>(WordOr(
1988-
WordShr(value, UintPtrConstant(JSDispatchEntry::kObjectPointerShift)),
1989-
UintPtrConstant(kHeapObjectTag)));
1987+
1988+
TNode<UintPtrT> shifted_value;
1989+
if (JSDispatchEntry::kObjectPointerOffset == 0) {
1990+
shifted_value =
1991+
WordShr(value, UintPtrConstant(JSDispatchEntry::kObjectPointerShift));
1992+
} else {
1993+
shifted_value = UintPtrAdd(
1994+
WordShr(value, UintPtrConstant(JSDispatchEntry::kObjectPointerShift)),
1995+
UintPtrConstant(JSDispatchEntry::kObjectPointerOffset));
1996+
}
1997+
1998+
value = UncheckedCast<UintPtrT>(
1999+
WordOr(shifted_value, UintPtrConstant(kHeapObjectTag)));
19902000
return CAST(BitcastWordToTagged(value));
19912001
}
19922002

src/sandbox/js-dispatch-table-inl.h

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,16 @@ void JSDispatchEntry::MakeJSDispatchEntry(Address object, Address entrypoint,
2323
uint16_t parameter_count,
2424
bool mark_as_alive) {
2525
DCHECK_EQ(object & kHeapObjectTag, 0);
26-
DCHECK_EQ((object << kObjectPointerShift) >> kObjectPointerShift, object);
27-
28-
Address payload =
29-
(object << kObjectPointerShift) | (parameter_count & kParameterCountMask);
26+
DCHECK_EQ((((object - kObjectPointerOffset) << kObjectPointerShift) >>
27+
kObjectPointerShift) +
28+
kObjectPointerOffset,
29+
object);
30+
DCHECK_EQ((object - kObjectPointerOffset) + kObjectPointerOffset, object);
31+
DCHECK_LT((object - kObjectPointerOffset),
32+
1ULL << ((sizeof(encoded_word_) * 8) - kObjectPointerShift));
33+
34+
Address payload = ((object - kObjectPointerOffset) << kObjectPointerShift) |
35+
(parameter_count & kParameterCountMask);
3036
DCHECK(!(payload & kMarkingBit));
3137
if (mark_as_alive) payload |= kMarkingBit;
3238
#ifdef V8_TARGET_ARCH_32_BIT
@@ -49,7 +55,8 @@ Address JSDispatchEntry::GetCodePointer() const {
4955
// and so may be 0 or 1 here. As the return value is a tagged pointer, the
5056
// bit must be 1 when returned, so we need to set it here.
5157
Address payload = encoded_word_.load(std::memory_order_relaxed);
52-
return (payload >> kObjectPointerShift) | kHeapObjectTag;
58+
return ((payload >> kObjectPointerShift) + kObjectPointerOffset) |
59+
kHeapObjectTag;
5360
}
5461

5562
Tagged<Code> JSDispatchEntry::GetCode() const {
@@ -178,7 +185,9 @@ void JSDispatchEntry::SetCodeAndEntrypointPointer(Address new_object,
178185
Address parameter_count = old_payload & kParameterCountMask;
179186
// We want to preserve the marking bit of the entry. Since that happens to
180187
// be the tag bit of the pointer, we need to explicitly clear it here.
181-
Address object = (new_object << kObjectPointerShift) & ~kMarkingBit;
188+
Address object =
189+
((new_object - kObjectPointerOffset) << kObjectPointerShift) &
190+
~kMarkingBit;
182191
Address new_payload = object | marking_bit | parameter_count;
183192
encoded_word_.store(new_payload, std::memory_order_relaxed);
184193
entrypoint_.store(new_entrypoint, std::memory_order_relaxed);

src/sandbox/js-dispatch-table.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,18 @@ struct JSDispatchEntry {
7575
static constexpr uintptr_t kCodeObjectOffset = kSystemPointerSize;
7676
static constexpr size_t kParameterCountSize = 2;
7777

78+
// On AIX and IBM i, mmap will give you back an address with the top bits set
79+
// unlike other platforms where the top bits are unset.
80+
// Therefore kObjectPointerOffset was introduced to ensure we account for
81+
// the top bits being set when performing pointer operations.
82+
#if defined(__PASE__)
83+
static constexpr uintptr_t kObjectPointerOffset = 0x0700000000000000;
84+
#elif defined(_AIX)
85+
static constexpr uintptr_t kObjectPointerOffset = 0x0a00000000000000;
86+
#else
87+
static constexpr uintptr_t kObjectPointerOffset = 0;
88+
#endif
89+
7890
#if defined(V8_TARGET_ARCH_64_BIT)
7991
// Freelist entries contain the index of the next free entry in their lower 32
8092
// bits and are tagged with this tag.

0 commit comments

Comments
 (0)