commit c08c3ea0df5664f6e1dae83b7b3d31c8f0176bf4
parent 73e0899365ed7e2fdb05860e1f60fb9c877f020d
Author: Jan de Mooij <jdemooij@mozilla.com>
Date: Fri, 7 Nov 2025 06:54:20 +0000
Bug 1982378 part 1 - Improve entry point code in BytecodeRangeWithPosition. r=arai
This refactors the entry point code in `BytecodeRangeWithPosition`:
* Use an enum instead of two booleans.
* Move code into `updatePosition` instead of separate functions.
* Add some assertions for prologue bytecode ops.
This simplifies the next patch.
Differential Revision: https://phabricator.services.mozilla.com/D271578
Diffstat:
1 file changed, 40 insertions(+), 28 deletions(-)
diff --git a/js/src/vm/BytecodeUtil-inl.h b/js/src/vm/BytecodeUtil-inl.h
@@ -123,45 +123,26 @@ class BytecodeRangeWithPosition : private BytecodeRange {
sn(script->notes()),
snEnd(script->notesEnd()),
snpc(script->code()),
- isEntryPoint(false),
+ mainPC(script->main()),
isBreakpoint(false),
- seenStepSeparator(false),
- wasArtifactEntryPoint(false) {
+ seenStepSeparator(false) {
if (sn < snEnd) {
snpc += sn->delta();
}
updatePosition();
- while (frontPC() != script->main()) {
+ while (frontPC() != mainPC) {
popFront();
}
-
- if (frontOpcode() != JSOp::JumpTarget) {
- isEntryPoint = true;
- } else {
- wasArtifactEntryPoint = true;
- }
+ MOZ_ASSERT(entryPointState != EntryPointState::NotEntryPoint);
}
void popFront() {
BytecodeRange::popFront();
if (empty()) {
- isEntryPoint = false;
+ entryPointState = EntryPointState::NotEntryPoint;
} else {
updatePosition();
}
-
- // The following conditions are handling artifacts introduced by the
- // bytecode emitter, such that we do not add breakpoints on empty
- // statements of the source code of the user.
- if (wasArtifactEntryPoint) {
- wasArtifactEntryPoint = false;
- isEntryPoint = true;
- }
-
- if (isEntryPoint && frontOpcode() == JSOp::JumpTarget) {
- wasArtifactEntryPoint = isEntryPoint;
- isEntryPoint = false;
- }
}
uint32_t frontLineNumber() const { return lineno; }
@@ -174,7 +155,9 @@ class BytecodeRangeWithPosition : private BytecodeRange {
// implement the idea that the bytecode emitter should tell the
// debugger exactly which offsets represent "interesting" (to the
// user) places to stop.
- bool frontIsEntryPoint() const { return isEntryPoint; }
+ bool frontIsEntryPoint() const {
+ return entryPointState == EntryPointState::EntryPoint;
+ }
// Breakable points are explicitly marked by the emitter as locations where
// the debugger may want to allow users to pause.
@@ -229,7 +212,30 @@ class BytecodeRangeWithPosition : private BytecodeRange {
}
sn = *iter;
- isEntryPoint = lastLinePC == frontPC();
+
+ // The current bytecode op is an entry point if it's the first op of the
+ // 'main' bytecode section or if it matches lastLinePC.
+ //
+ // If we're at a JSOp::JumpTarget op, we use ArtifactEntryPoint to mark the
+ // next op as entry point instead. This prevents adding breakpoints for
+ // empty statements in the JS code.
+ if (frontPC() == mainPC || frontPC() == lastLinePC ||
+ entryPointState == EntryPointState::ArtifactEntryPoint) {
+ if (frontOpcode() == JSOp::JumpTarget) {
+ entryPointState = EntryPointState::ArtifactEntryPoint;
+ } else {
+ entryPointState = EntryPointState::EntryPoint;
+ }
+ } else {
+ entryPointState = EntryPointState::NotEntryPoint;
+ }
+
+ // Ops in the prologue are never entry points or breakable locations.
+ if (frontPC() < mainPC) {
+ MOZ_ASSERT(!frontIsEntryPoint());
+ MOZ_ASSERT(!frontIsBreakablePoint());
+ MOZ_ASSERT(!frontIsBreakableStepPoint());
+ }
}
uint32_t initialLine;
@@ -243,10 +249,16 @@ class BytecodeRangeWithPosition : private BytecodeRange {
const SrcNote* sn;
const SrcNote* snEnd;
jsbytecode* snpc;
- bool isEntryPoint;
+ jsbytecode* mainPC;
bool isBreakpoint;
bool seenStepSeparator;
- bool wasArtifactEntryPoint;
+
+ enum class EntryPointState : uint8_t {
+ NotEntryPoint,
+ EntryPoint,
+ ArtifactEntryPoint
+ };
+ EntryPointState entryPointState = EntryPointState::NotEntryPoint;
};
} // namespace js