[debug] Check ScopeInfo before writing to/reading from context

Currently, the ScopeIterator uses the re-parsed lexical scope info to
write to, and read from contexts. This assumes that we always manage
to match the re-parsed scope chain with the context chain on a pause.
Unfortunately there are rare edge cases where we have a miss match.

This CL adds a check that makes sure that a Context's ScopeInfo knows
about the variables we actually want to read/write and don't rely
solely on the AST. Once the bug is fixed, we can turn this into a
CHECK instead.

R=jarin@chormium.org

Bug: chromium:753338
Change-Id: Iefe1fdc025dcb570fc98167134e230b204d595b5
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4061077
Reviewed-by: Jaroslav Sevcik <jarin@chromium.org>
Commit-Queue: Simon Zünd <szuend@chromium.org>
Cr-Commit-Position: refs/heads/main@{#84537}
This commit is contained in:
Simon Zünd 2022-11-29 14:13:40 +01:00 committed by V8 LUCI CQ
parent e54d30b7ef
commit fa9720b229

View File

@ -921,7 +921,16 @@ bool ScopeIterator::VisitLocals(const Visitor& visitor, Mode mode,
case VariableLocation::CONTEXT:
if (mode == Mode::STACK) continue;
DCHECK(var->IsContextSlot());
value = handle(context_->get(index), isolate_);
// We know of at least one open bug where the context and scope chain
// don't match (https://crbug.com/753338).
// Return `undefined` if the context's ScopeInfo doesn't know anything
// about this variable.
if (context_->scope_info().ContextSlotIndex(var->name()) != index) {
value = isolate_->factory()->undefined_value();
} else {
value = handle(context_->get(index), isolate_);
}
break;
case VariableLocation::MODULE: {
@ -1069,6 +1078,14 @@ bool ScopeIterator::SetLocalVariableValue(Handle<String> variable_name,
case VariableLocation::CONTEXT:
DCHECK(var->IsContextSlot());
// We know of at least one open bug where the context and scope chain
// don't match (https://crbug.com/753338).
// Skip the write if the context's ScopeInfo doesn't know anything
// about this variable.
if (context_->scope_info().ContextSlotIndex(variable_name) != index) {
return false;
}
context_->set(index, *new_value);
return true;