Issue #2142 - Improve TokenPos handling in BCE

* Don't print bogus error locations on BCE internal errors
* Do not use TokenPos in BytecodeEmitter::{setFunctionBodyEndPos,setScriptStartOffsetIfUnset}

Based-on: m-c 1451826/1, 1530034, 1473796/2
This commit is contained in:
Martok 2023-04-07 19:32:22 +02:00 • committed by roytam1
commit ab7721e4df
2 changed files with 26 additions and 18 deletions

View file

@ -190,8 +190,7 @@ BytecodeEmitter::BytecodeEmitter(BytecodeEmitter* parent,
hasSingletons(false), hasSingletons(false),
hasTryFinally(false), hasTryFinally(false),
emittingRunOnceLambda(false), emittingRunOnceLambda(false),
emitterMode(emitterMode), emitterMode(emitterMode)
functionBodyEndPosSet(false)
{ {
MOZ_ASSERT_IF(emitterMode == LazyFunction, lazyScript); MOZ_ASSERT_IF(emitterMode == LazyFunction, lazyScript);
} }
@ -204,7 +203,8 @@ BytecodeEmitter::BytecodeEmitter(BytecodeEmitter* parent,
parser->tokenStream.srcCoords.lineNum(bodyPosition.begin), parser->tokenStream.srcCoords.lineNum(bodyPosition.begin),
emitterMode) emitterMode)
{ {
setFunctionBodyEndPos(bodyPosition); setScriptStartOffsetIfUnset(bodyPosition.begin);
setFunctionBodyEndPos(bodyPosition.end);
} }
bool bool
@ -1645,11 +1645,11 @@ BytecodeEmitter::tokenStream()
bool bool
BytecodeEmitter::reportError(ParseNode* pn, unsigned errorNumber, ...) BytecodeEmitter::reportError(ParseNode* pn, unsigned errorNumber, ...)
{ {
TokenPos pos = pn ? pn->pn_pos : tokenStream().currentToken().pos; uint32_t offset = pn ? pn->pn_pos.begin : *scriptStartOffset;
va_list args; va_list args;
va_start(args, errorNumber); va_start(args, errorNumber);
bool result = tokenStream().reportCompileErrorNumberVA(nullptr, pos.begin, JSREPORT_ERROR, bool result = tokenStream().reportCompileErrorNumberVA(nullptr, offset, JSREPORT_ERROR,
errorNumber, args); errorNumber, args);
va_end(args); va_end(args);
return result; return result;
@ -1658,7 +1658,7 @@ BytecodeEmitter::reportError(ParseNode* pn, unsigned errorNumber, ...)
bool bool
BytecodeEmitter::reportError(const mozilla::Maybe<uint32_t>& maybeOffset, unsigned errorNumber, ...) BytecodeEmitter::reportError(const mozilla::Maybe<uint32_t>& maybeOffset, unsigned errorNumber, ...)
{ {
uint32_t offset = maybeOffset ? *maybeOffset : tokenStream().currentToken().pos.begin; uint32_t offset = maybeOffset ? *maybeOffset : *scriptStartOffset;
va_list args; va_list args;
va_start(args, errorNumber); va_start(args, errorNumber);
@ -1671,11 +1671,11 @@ BytecodeEmitter::reportError(const mozilla::Maybe<uint32_t>& maybeOffset, unsign
bool bool
BytecodeEmitter::reportExtraWarning(ParseNode* pn, unsigned errorNumber, ...) BytecodeEmitter::reportExtraWarning(ParseNode* pn, unsigned errorNumber, ...)
{ {
TokenPos pos = pn ? pn->pn_pos : tokenStream().currentToken().pos; uint32_t offset = pn ? pn->pn_pos.begin : *scriptStartOffset;
va_list args; va_list args;
va_start(args, errorNumber); va_start(args, errorNumber);
bool result = tokenStream().reportExtraWarningErrorNumberVA(nullptr, pos.begin, bool result = tokenStream().reportExtraWarningErrorNumberVA(nullptr, offset,
errorNumber, args); errorNumber, args);
va_end(args); va_end(args);
return result; return result;
@ -2323,6 +2323,8 @@ BytecodeEmitter::emitSetThis(BinaryNode* setThisNode)
bool bool
BytecodeEmitter::emitScript(ParseNode* body) BytecodeEmitter::emitScript(ParseNode* body)
{ {
setScriptStartOffsetIfUnset(body->pn_pos.begin);
TDZCheckCache tdzCache(this); TDZCheckCache tdzCache(this);
EmitterScope emitterScope(this); EmitterScope emitterScope(this);
if (sc->isGlobalContext()) { if (sc->isGlobalContext()) {
@ -2341,7 +2343,7 @@ BytecodeEmitter::emitScript(ParseNode* body)
return false; return false;
} }
setFunctionBodyEndPos(body->pn_pos); setFunctionBodyEndPos(body->pn_pos.end);
if (sc->isEvalContext() && !sc->strict() && if (sc->isEvalContext() && !sc->strict() &&
body->is<LexicalScopeNode>() && !body->as<LexicalScopeNode>().isEmptyScope()) body->is<LexicalScopeNode>() && !body->as<LexicalScopeNode>().isEmptyScope())
@ -2451,6 +2453,8 @@ BytecodeEmitter::emitFunctionScript(FunctionNode* funNode)
ParseNode* body = funNode->body(); ParseNode* body = funNode->body();
FunctionBox* funbox = sc->asFunctionBox(); FunctionBox* funbox = sc->asFunctionBox();
setScriptStartOffsetIfUnset(body->pn_pos.begin);
// The ordering of these EmitterScopes is important. The named lambda // The ordering of these EmitterScopes is important. The named lambda
// scope needs to enclose the function scope needs to enclose the extra // scope needs to enclose the function scope needs to enclose the extra
// var scope. // var scope.
@ -2480,7 +2484,7 @@ BytecodeEmitter::emitFunctionScript(FunctionNode* funNode)
switchToMain(); switchToMain();
} }
setFunctionBodyEndPos(body->pn_pos); setFunctionBodyEndPos(body->pn_pos.end);
if (!emitTree(body)) if (!emitTree(body))
return false; return false;
@ -6235,8 +6239,7 @@ BytecodeEmitter::emitReturn(UnaryNode* returnNode)
// We know functionBodyEndPos is set because "return" is only // We know functionBodyEndPos is set because "return" is only
// valid in a function, and so we've passed through // valid in a function, and so we've passed through
// emitFunctionScript. // emitFunctionScript.
MOZ_ASSERT(functionBodyEndPosSet); if (!updateSourceCoordNotes(*functionBodyEndPos))
if (!updateSourceCoordNotes(functionBodyEndPos))
return false; return false;
/* /*

View file

@ -236,10 +236,10 @@ struct MOZ_STACK_CLASS BytecodeEmitter
const EmitterMode emitterMode; const EmitterMode emitterMode;
mozilla::Maybe<uint32_t> scriptStartOffset;
// The end location of a function body that is being emitted. // The end location of a function body that is being emitted.
uint32_t functionBodyEndPos; mozilla::Maybe<uint32_t> functionBodyEndPos;
// Whether functionBodyEndPos was set.
bool functionBodyEndPosSet;
/* /*
* Note that BytecodeEmitters are magic: they own the arena "top-of-stack" * Note that BytecodeEmitters are magic: they own the arena "top-of-stack"
@ -350,9 +350,14 @@ struct MOZ_STACK_CLASS BytecodeEmitter
return lastOpcodeIsJumpTarget() ? current->lastTarget.offset : offset(); return lastOpcodeIsJumpTarget() ? current->lastTarget.offset : offset();
} }
void setFunctionBodyEndPos(TokenPos pos) { void setFunctionBodyEndPos(uint32_t pos) {
functionBodyEndPos = pos.end; functionBodyEndPos = mozilla::Some(pos);
functionBodyEndPosSet = true; }
void setScriptStartOffsetIfUnset(uint32_t pos) {
if (scriptStartOffset.isNothing()) {
scriptStartOffset = mozilla::Some(pos);
}
} }
bool reportError(ParseNode* pn, unsigned errorNumber, ...); bool reportError(ParseNode* pn, unsigned errorNumber, ...);