Skip to content

Commit fb512fb

Browse files
committed
[JSC] Store the ValueReps of FTL OSR exits in the exit stream
https://bugs.webkit.org/show_bug.cgi?id=325463 Reviewed by Yusuke Suzuki. 321991@main stored FTL OSR exits as an FTL::OSRExitStream, but where B3 placed the exit arguments of the exits stayed in another byte stream of the JITCode, and each exit in the stream had the offset of its ValueReps there. This patch stores the ValueReps of an exit right after the exit in the stream, so the offsets and the other byte stream are gone. One JetStream3 run, 167k exits: Before After Total 4.14 MB 3.96 MB Per exit 24.8 B 23.8 B * Source/JavaScriptCore/ftl/FTLJITCode.cpp: (JSC::FTL::JITCode::shrinkToFit): (JSC::FTL::JITCode::liveRegistersToPreserveAtExceptionHandlingCallSite): * Source/JavaScriptCore/ftl/FTLJITCode.h: * Source/JavaScriptCore/ftl/FTLLink.cpp: (JSC::FTL::link): * Source/JavaScriptCore/ftl/FTLOSRExit.cpp: (JSC::FTL::OSRExitDescriptor::prepareOSRExitHandle): (JSC::FTL::OSRExit::valueReps const): (JSC::FTL::OSRExitStream::OSRExitStream): (JSC::FTL::OSRExitStream::decode const): (JSC::FTL::OSRExitStream::valueReps const): (JSC::FTL::OSRExitValueReps::append): Deleted. (JSC::FTL::OSRExitValueReps::decode const): Deleted. * Source/JavaScriptCore/ftl/FTLOSRExit.h: (JSC::FTL::OSRExitValueReps::shrinkToFit): Deleted. * Source/JavaScriptCore/ftl/FTLState.h: Canonical link: https://commits.webkit.org/322138@main
1 parent 1e27366 commit fb512fb

6 files changed

Lines changed: 38 additions & 57 deletions

File tree

‎Source/JavaScriptCore/ftl/FTLJITCode.cpp‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,6 @@ void JITCode::shrinkToFit()
143143
common.shrinkToFit();
144144
osrExitDescriptors.shrinkToFit();
145145
osrExitConstants.shrinkToFit();
146-
osrExitValueReps.shrinkToFit();
147146
lazySlowPaths.shrinkToFit();
148147
}
149148

@@ -161,7 +160,7 @@ RegisterSet JITCode::liveRegistersToPreserveAtExceptionHandlingCallSite(CodeBloc
161160
{
162161
for (const OSRExitStream::ExceptionHandlerExit& handler : m_osrExits.exceptionHandlerExits()) {
163162
if (handler.callSiteIndex.bits() == callSiteIndex.bits())
164-
return ValueRep::usedRegisters(/* isSIMDContext = */ false, osrExitValueReps.decode(handler.valueRepsOffset));
163+
return ValueRep::usedRegisters(/* isSIMDContext = */ false, m_osrExits.valueReps(handler.valueRepsOffset));
165164
}
166165
return { };
167166
}

‎Source/JavaScriptCore/ftl/FTLJITCode.h‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,6 @@ class JITCode : public JSC::JITCode {
108108
RegisterAtOffsetList m_calleeSaveRegisters;
109109
SegmentedVector<OSRExitDescriptor, 8> osrExitDescriptors;
110110
Vector<EncodedJSValue> osrExitConstants;
111-
OSRExitValueReps osrExitValueReps;
112111
Vector<std::unique_ptr<LazySlowPath>> lazySlowPaths;
113112

114113
private:

‎Source/JavaScriptCore/ftl/FTLLink.cpp‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ void link(State& state)
6969

7070
state.jitCode->initializeB3Code(b3CodeRef);
7171
state.jitCode->common.m_jumpReplacements = WTF::move(state.jumpReplacements);
72-
state.jitCode->m_osrExits = OSRExitStream(state.osrExits);
72+
state.jitCode->m_osrExits = OSRExitStream(state.osrExits, state.osrExitValueReps.span());
7373
}
7474

7575
state.finalizer->m_codeSize = state.b3CodeLinkBuffer->size();

‎Source/JavaScriptCore/ftl/FTLOSRExit.cpp‎

Lines changed: 28 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -103,25 +103,6 @@ B3::ValueRep decodeValueRep(std::span<const uint8_t> bytes, size_t& offset)
103103

104104
} // anonymous namespace
105105

106-
unsigned OSRExitValueReps::append(std::span<const B3::ValueRep> reps)
107-
{
108-
unsigned offset = m_bytes.size();
109-
WTF::LEBEncoder::encodeUInt32(m_bytes, reps.size());
110-
for (const B3::ValueRep& rep : reps)
111-
encodeValueRep(m_bytes, rep);
112-
return offset;
113-
}
114-
115-
FixedVector<B3::ValueRep> OSRExitValueReps::decode(unsigned offset) const
116-
{
117-
std::span<const uint8_t> bytes = m_bytes.span();
118-
size_t position = offset;
119-
unsigned count = WTF::LEBDecoder::decodeUInt32OrCrash(bytes, position);
120-
return FixedVector<B3::ValueRep>::createWithSizeFromGenerator(count, [&](size_t) {
121-
return decodeValueRep(bytes, position);
122-
});
123-
}
124-
125106
void OSRExitValues::encode(const Operands<ExitValue>& values, const Bag<ExitTimeObjectMaterialization>& materializationBag, JITCode& jitCode)
126107
{
127108
m_numberOfArguments = values.numberOfArguments();
@@ -271,7 +252,11 @@ Ref<OSRExitHandle> OSRExitDescriptor::prepareOSRExitHandle(
271252
State& state, ExitKind exitKind, const NodeOrigin& nodeOrigin,
272253
const StackmapGenerationParams& params, uint32_t dfgNodeIndex, unsigned offset)
273254
{
274-
unsigned valueRepsOffset = state.jitCode->osrExitValueReps.append(params.reps().subspan(offset));
255+
unsigned valueRepsOffset = state.osrExitValueReps.size();
256+
std::span<const B3::ValueRep> reps = params.reps().subspan(offset);
257+
WTF::LEBEncoder::encodeUInt32(state.osrExitValueReps, reps.size());
258+
for (const B3::ValueRep& rep : reps)
259+
encodeValueRep(state.osrExitValueReps, rep);
275260
OSRExit exit(this, exitKind, nodeOrigin.forExit, nodeOrigin.semantic, nodeOrigin.wasHoisted, dfgNodeIndex, valueRepsOffset);
276261
if (exitKind == WillThrowOutOfMemoryError)
277262
exit.m_exitCallSiteIndex = callSiteIndexForCodeOrigin(state, nodeOrigin.semantic);
@@ -290,14 +275,14 @@ OSRExit::OSRExit(const OSRExitDescriptor* descriptor, ExitKind exitKind, CodeOri
290275

291276
FixedVector<B3::ValueRep> OSRExit::valueReps(const JITCode& jitCode) const
292277
{
293-
return jitCode.osrExitValueReps.decode(m_valueRepsOffset);
278+
return jitCode.m_osrExits.valueReps(m_valueRepsOffset);
294279
}
295280

296281
static constexpr unsigned codeOriginTagShift = 0;
297282
static constexpr unsigned profileOriginTagShift = 2;
298283
static constexpr unsigned wasHoistedBit = 1 << 4;
299284

300-
OSRExitStream::OSRExitStream(const Vector<OSRExit>& exits)
285+
OSRExitStream::OSRExitStream(const Vector<OSRExit>& exits, std::span<const uint8_t> valueReps)
301286
: m_chunkOffsets(divideRoundedUp(exits.size(), static_cast<size_t>(exitsPerChunk)))
302287
, m_size(exits.size())
303288
{
@@ -327,15 +312,15 @@ OSRExitStream::OSRExitStream(const Vector<OSRExit>& exits)
327312
previous.dfgNodeIndex = exit.m_dfgNodeIndex;
328313
WTF::LEBEncoder::encodeInt32(bytes, static_cast<int32_t>(exit.m_descriptor->m_index - previous.descriptorIndex));
329314
previous.descriptorIndex = exit.m_descriptor->m_index;
330-
// FIXME: Store the ValueReps after the exit in this stream instead of their offset.
331-
WTF::LEBEncoder::encodeInt32(bytes, static_cast<int32_t>(exit.m_valueRepsOffset - previous.valueRepsOffset));
332-
previous.valueRepsOffset = exit.m_valueRepsOffset;
333315
WTF::LEBEncoder::encodeInt32(bytes, static_cast<int32_t>(exit.m_entranceOffset - previous.entranceOffset));
334316
previous.entranceOffset = exit.m_entranceOffset;
335317
if (exit.m_kind == WillThrowOutOfMemoryError)
336318
WTF::LEBEncoder::encodeUInt32(bytes, exit.m_exitCallSiteIndex.bits());
337319
if (exit.isGenericUnwindHandler())
338-
exceptionHandlerExits.append({ exit.m_exceptionHandlerCallSiteIndex, exit.m_valueRepsOffset });
320+
exceptionHandlerExits.append({ exit.m_exceptionHandlerCallSiteIndex, static_cast<uint32_t>(bytes.size()) });
321+
size_t valueRepsEnd = index + 1 < exits.size() ? exits[index + 1].m_valueRepsOffset : valueReps.size();
322+
RELEASE_ASSERT(exit.m_valueRepsOffset < valueRepsEnd);
323+
bytes.append(valueReps.subspan(exit.m_valueRepsOffset, valueRepsEnd - exit.m_valueRepsOffset));
339324
}
340325
m_bytes = WTF::move(bytes);
341326
m_exceptionHandlerExits = WTF::move(exceptionHandlerExits);
@@ -350,16 +335,29 @@ OSRExit OSRExitStream::decode(size_t& offset, PreviousExit& previous, const JITC
350335
CodeOrigin codeOriginForExitProfile = decodeCodeOrigin(bytes, offset, codeOriginTagFromFlags(flags, profileOriginTagShift), previous.codeOrigin);
351336
previous.dfgNodeIndex += WTF::LEBDecoder::decodeInt32OrCrash(bytes, offset);
352337
previous.descriptorIndex += WTF::LEBDecoder::decodeInt32OrCrash(bytes, offset);
353-
previous.valueRepsOffset += WTF::LEBDecoder::decodeInt32OrCrash(bytes, offset);
354338
previous.entranceOffset += WTF::LEBDecoder::decodeInt32OrCrash(bytes, offset);
339+
CallSiteIndex exitCallSiteIndex;
340+
if (kind == WillThrowOutOfMemoryError)
341+
exitCallSiteIndex = CallSiteIndex(WTF::LEBDecoder::decodeUInt32OrCrash(bytes, offset));
355342

356-
OSRExit exit(&jitCode.osrExitDescriptors[previous.descriptorIndex], kind, previous.codeOrigin, WTF::move(codeOriginForExitProfile), !!(flags & wasHoistedBit), previous.dfgNodeIndex, previous.valueRepsOffset);
343+
OSRExit exit(&jitCode.osrExitDescriptors[previous.descriptorIndex], kind, previous.codeOrigin, WTF::move(codeOriginForExitProfile), !!(flags & wasHoistedBit), previous.dfgNodeIndex, static_cast<unsigned>(offset));
357344
exit.m_entranceOffset = previous.entranceOffset;
358-
if (kind == WillThrowOutOfMemoryError)
359-
exit.m_exitCallSiteIndex = CallSiteIndex(WTF::LEBDecoder::decodeUInt32OrCrash(bytes, offset));
345+
exit.m_exitCallSiteIndex = exitCallSiteIndex;
346+
for (unsigned count = WTF::LEBDecoder::decodeUInt32OrCrash(bytes, offset); count--;)
347+
decodeValueRep(bytes, offset);
360348
return exit;
361349
}
362350

351+
FixedVector<B3::ValueRep> OSRExitStream::valueReps(unsigned offset) const
352+
{
353+
std::span<const uint8_t> bytes = m_bytes.span();
354+
size_t position = offset;
355+
unsigned count = WTF::LEBDecoder::decodeUInt32OrCrash(bytes, position);
356+
return FixedVector<B3::ValueRep>::createWithSizeFromGenerator(count, [&](size_t) {
357+
return decodeValueRep(bytes, position);
358+
});
359+
}
360+
363361
OSRExit OSRExitStream::at(unsigned index, const JITCode& jitCode) const
364362
{
365363
RELEASE_ASSERT(index < m_size);

‎Source/JavaScriptCore/ftl/FTLOSRExit.h‎

Lines changed: 7 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -96,26 +96,6 @@ class OSRExitValues {
9696
unsigned m_numberOfTmps { 0 };
9797
};
9898

99-
// Stores where B3 placed the exit arguments of every exit of a JITCode as one byte stream. An
100-
// exit's entry is a LEB128 argument count followed by one B3::ValueRep per argument, which is a
101-
// B3::ValueRep::Kind byte and then:
102-
//
103-
// Register the Reg index byte
104-
// Stack the SLEB128 offset from the frame pointer
105-
// Constant the SLEB128 value
106-
class OSRExitValueReps {
107-
WTF_MAKE_NONCOPYABLE(OSRExitValueReps);
108-
public:
109-
OSRExitValueReps() = default;
110-
111-
unsigned append(std::span<const B3::ValueRep>);
112-
FixedVector<B3::ValueRep> decode(unsigned offset) const;
113-
void shrinkToFit() { m_bytes.shrinkToFit(); }
114-
115-
private:
116-
Vector<uint8_t> m_bytes;
117-
};
118-
11999
struct OSRExitDescriptor {
120100
private:
121101
WTF_MAKE_NONCOPYABLE(OSRExitDescriptor);
@@ -196,9 +176,13 @@ struct OSRExit : public DFG::OSRExitBase {
196176
// the payload of each origin tag, in the order of the flags
197177
// LEB128 signed delta of m_dfgNodeIndex
198178
// LEB128 signed delta of the index of m_descriptor in JITCode::osrExitDescriptors
199-
// LEB128 signed delta of m_valueRepsOffset
200179
// LEB128 signed delta of m_entranceOffset
201180
// [LEB128] WillThrowOutOfMemoryError: m_exitCallSiteIndex
181+
// LEB128 number of exit arguments
182+
// where B3 placed each exit argument, which is a B3::ValueRep::Kind byte and then:
183+
// Register the Reg index byte
184+
// Stack the SLEB128 offset from the frame pointer
185+
// Constant the SLEB128 value
202186
class OSRExitStream {
203187
public:
204188
struct ExceptionHandlerExit {
@@ -207,10 +191,11 @@ class OSRExitStream {
207191
};
208192

209193
OSRExitStream() = default;
210-
explicit OSRExitStream(const Vector<OSRExit>&);
194+
OSRExitStream(const Vector<OSRExit>&, std::span<const uint8_t> valueReps);
211195

212196
OSRExit at(unsigned index, const JITCode&) const;
213197
unsigned indexForEntranceOffset(uintptr_t, const JITCode&) const;
198+
FixedVector<B3::ValueRep> valueReps(unsigned offset) const;
214199
std::span<const ExceptionHandlerExit> exceptionHandlerExits() const LIFETIME_BOUND { return m_exceptionHandlerExits.span(); }
215200

216201
private:
@@ -220,7 +205,6 @@ class OSRExitStream {
220205
CodeOrigin codeOrigin { BytecodeIndex(0) };
221206
uint32_t dfgNodeIndex { 0 };
222207
unsigned descriptorIndex { 0 };
223-
unsigned valueRepsOffset { 0 };
224208
uint32_t entranceOffset { 0 };
225209
};
226210

‎Source/JavaScriptCore/ftl/FTLState.h‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ class State {
8989
B3::Air::StackSlot* capturedValue { nullptr };
9090
Vector<DFG::JumpReplacement> jumpReplacements;
9191
Vector<OSRExit> osrExits;
92+
Vector<uint8_t> osrExitValueReps;
9293
};
9394

9495
} } // namespace JSC::FTL

0 commit comments

Comments
 (0)