Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions Source/JavaScriptCore/bytecode/CodeBlock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1282,15 +1282,15 @@ static Seconds NODELETE timeToLive(JITType jitType)

switch (jitType) {
case JITType::InterpreterThunk:
return 5_s;
return Seconds(Options::interpreterThunkTimeToLiveSeconds());
case JITType::BaselineJIT:
// Effectively 10 additional seconds, since BaselineJIT and
// InterpreterThunk share a CodeBlock.
return 15_s;
return Seconds(Options::baselineJITTimeToLiveSeconds());
case JITType::DFGJIT:
return 20_s;
return Seconds(Options::dfgJITTimeToLiveSeconds());
case JITType::FTLJIT:
return 60_s;
return Seconds(Options::ftlJITTimeToLiveSeconds());
Comment on lines +1285 to +1293
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Sanitize configurable TTL values before constructing Seconds.

These values are externally configurable; negative/invalid inputs can force immediate old-age jettison and create unnecessary recompile churn. Clamp at the call site.

Suggested fix
 static Seconds NODELETE timeToLive(JITType jitType)
 {
+    auto sanitizeTTL = [] (double seconds) -> Seconds {
+        return Seconds(seconds >= 0 ? seconds : 0);
+    };
+
     if (Options::useEagerCodeBlockJettisonTiming()) [[unlikely]] {
         switch (jitType) {
         case JITType::InterpreterThunk:
             return 10_ms;
@@
     switch (jitType) {
     case JITType::InterpreterThunk:
-        return Seconds(Options::interpreterThunkTimeToLiveSeconds());
+        return sanitizeTTL(Options::interpreterThunkTimeToLiveSeconds());
     case JITType::BaselineJIT:
         // Effectively 10 additional seconds, since BaselineJIT and
         // InterpreterThunk share a CodeBlock.
-        return Seconds(Options::baselineJITTimeToLiveSeconds());
+        return sanitizeTTL(Options::baselineJITTimeToLiveSeconds());
     case JITType::DFGJIT:
-        return Seconds(Options::dfgJITTimeToLiveSeconds());
+        return sanitizeTTL(Options::dfgJITTimeToLiveSeconds());
     case JITType::FTLJIT:
-        return Seconds(Options::ftlJITTimeToLiveSeconds());
+        return sanitizeTTL(Options::ftlJITTimeToLiveSeconds());
     default:
         return Seconds::infinity();
     }
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
return Seconds(Options::interpreterThunkTimeToLiveSeconds());
case JITType::BaselineJIT:
// Effectively 10 additional seconds, since BaselineJIT and
// InterpreterThunk share a CodeBlock.
return 15_s;
return Seconds(Options::baselineJITTimeToLiveSeconds());
case JITType::DFGJIT:
return 20_s;
return Seconds(Options::dfgJITTimeToLiveSeconds());
case JITType::FTLJIT:
return 60_s;
return Seconds(Options::ftlJITTimeToLiveSeconds());
static Seconds NODELETE timeToLive(JITType jitType)
{
auto sanitizeTTL = [] (double seconds) -> Seconds {
return Seconds(seconds >= 0 ? seconds : 0);
};
if (Options::useEagerCodeBlockJettisonTiming()) [[unlikely]] {
switch (jitType) {
case JITType::InterpreterThunk:
return 10_ms;
case JITType::BaselineJIT:
return 100_ms;
case JITType::DFGJIT:
return 1_s;
case JITType::FTLJIT:
return 10_s;
default:
ASSERT_NOT_REACHED();
}
}
switch (jitType) {
case JITType::InterpreterThunk:
return sanitizeTTL(Options::interpreterThunkTimeToLiveSeconds());
case JITType::BaselineJIT:
// Effectively 10 additional seconds, since BaselineJIT and
// InterpreterThunk share a CodeBlock.
return sanitizeTTL(Options::baselineJITTimeToLiveSeconds());
case JITType::DFGJIT:
return sanitizeTTL(Options::dfgJITTimeToLiveSeconds());
case JITType::FTLJIT:
return sanitizeTTL(Options::ftlJITTimeToLiveSeconds());
default:
return Seconds::infinity();
}
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Source/JavaScriptCore/bytecode/CodeBlock.cpp` around lines 1285 - 1293, The
TTL values returned from Options (used in the switch over JITType in
CodeBlock.cpp) must be sanitized before constructing Seconds to avoid
negative/invalid inputs causing immediate eviction; for each case
(InterpreterThunk, BaselineJIT, DFGJIT, FTLJIT) read the raw config value from
Options::*, clamp it to a safe non-negative range (e.g. using std::max(0, value)
or std::clamp(value, 0, someUpperBound)) and then construct and return
Seconds(clampedValue) instead of passing the raw value directly to Seconds.
Ensure you adjust the InterpreterThunk, BaselineJIT, DFGJIT and FTLJIT return
sites accordingly.

default:
return Seconds::infinity();
}
Expand Down
4 changes: 4 additions & 0 deletions Source/JavaScriptCore/runtime/OptionsList.h
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,10 @@ bool hasCapacityToUseLargeGigacage();
v(Bool, dumpHeapOnLowMemory, false, Normal, "Dump a heap dump when the memory handler is triggered. Use alongside $vm.triggerMemoryPressure() and enableStrongRefTracker."_s) \
v(Bool, forceCodeBlockToJettisonDueToOldAge, false, Normal, "If true, this means that anytime we can jettison a CodeBlock due to old age, we do."_s) \
v(Bool, useEagerCodeBlockJettisonTiming, false, Normal, "If true, the time slices for jettisoning a CodeBlock due to old age are shrunk significantly."_s) \
v(Double, interpreterThunkTimeToLiveSeconds, 5.0, Normal, "Seconds before an InterpreterThunk CodeBlock is eligible for old-age jettison."_s) \
v(Double, baselineJITTimeToLiveSeconds, 15.0, Normal, "Seconds before a BaselineJIT CodeBlock is eligible for old-age jettison."_s) \
v(Double, dfgJITTimeToLiveSeconds, 20.0, Normal, "Seconds before a DFGJIT CodeBlock is eligible for old-age jettison."_s) \
v(Double, ftlJITTimeToLiveSeconds, 60.0, Normal, "Seconds before an FTLJIT CodeBlock is eligible for old-age jettison."_s) \
\
v(Bool, useTypeProfiler, false, Normal, nullptr) \
v(Bool, useControlFlowProfiler, false, Normal, nullptr) \
Expand Down
Loading