Commit 911c7170 authored by Simon Zünd's avatar Simon Zünd Committed by V8 LUCI CQ

[debug] CHECK that a function's context is always available

After https://crrev.com/c/3854501 has landed, we no longer have to
handle the case that we do not find a function's context in the
scope iterator even though the function requires one.

This CL renames `NeedsAndHasContext` to `NeedsContext` since we
always find a scope's context now. Additionally we turn this
assumption into a dedicated check.

R=bmeurer@chromium.org

Bug: chromium:1246907
Change-Id: I6458df76689c0bfa6d6b2f8c421f9ce481855547
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3865153Reviewed-by: 's avatarBenedikt Meurer <bmeurer@chromium.org>
Commit-Queue: Simon Zünd <szuend@chromium.org>
Cr-Commit-Position: refs/heads/main@{#82848}
parent 251d7374
...@@ -376,21 +376,27 @@ bool ScopeIterator::DeclaresLocals(Mode mode) const { ...@@ -376,21 +376,27 @@ bool ScopeIterator::DeclaresLocals(Mode mode) const {
} }
bool ScopeIterator::HasContext() const { bool ScopeIterator::HasContext() const {
return !InInnerScope() || NeedsAndHasContext(); return !InInnerScope() || NeedsContext();
} }
bool ScopeIterator::NeedsAndHasContext() const { bool ScopeIterator::NeedsContext() const {
if (!current_scope_->NeedsContext()) return false; const bool needs_context = current_scope_->NeedsContext();
// Generally, if a scope needs a context, then we can assume that it has a
// context. However, the stack check during function entry happens before the // We try very hard to ensure that a function's context is already
// function has a chance to create and push its own context, so we must check // available when we pause right at the beginning of that function.
// for the case where the function is executing in its parent context. This // This can be tricky when we pause via stack check or via
// case is only possible in function scopes; top-level code (modules and // `BreakOnNextFunctionCall`, which happens normally in the middle of frame
// non-module scripts) begin execution in the context they need and don't have // construction and we have to "step into" the function first.
// a separate step to push the correct context. //
return !(current_scope_ == closure_scope_ && // We check this by ensuring that the current context is not the closure
current_scope_->is_function_scope() && !function_.is_null() && // context should the function need one. In that case the function has already
function_->context() == *context_); // pushed the context and we are good.
CHECK_IMPLIES(needs_context && current_scope_ == closure_scope_ &&
current_scope_->is_function_scope() &&
!function_->is_null(),
function_->context() != *context_);
return needs_context;
} }
bool ScopeIterator::AdvanceOneScope() { bool ScopeIterator::AdvanceOneScope() {
...@@ -415,7 +421,7 @@ void ScopeIterator::AdvanceScope() { ...@@ -415,7 +421,7 @@ void ScopeIterator::AdvanceScope() {
DCHECK(InInnerScope()); DCHECK(InInnerScope());
do { do {
if (NeedsAndHasContext()) { if (NeedsContext()) {
// current_scope_ needs a context so moving one scope up requires us to // current_scope_ needs a context so moving one scope up requires us to
// also move up one context. // also move up one context.
AdvanceOneContext(); AdvanceOneContext();
...@@ -432,7 +438,7 @@ void ScopeIterator::AdvanceContext() { ...@@ -432,7 +438,7 @@ void ScopeIterator::AdvanceContext() {
// scope, but until we hit the next scope that actually requires // scope, but until we hit the next scope that actually requires
// a context. All the locals collected along the way build the // a context. All the locals collected along the way build the
// blocklist for debug-evaluate for this context. // blocklist for debug-evaluate for this context.
while (AdvanceOneScope() && !NeedsAndHasContext()) { while (AdvanceOneScope() && !NeedsContext()) {
} }
} }
...@@ -470,7 +476,7 @@ void ScopeIterator::Next() { ...@@ -470,7 +476,7 @@ void ScopeIterator::Next() {
// and collect the blocklist along the way until we find the scope // and collect the blocklist along the way until we find the scope
// that should match `context_`. // that should match `context_`.
// But only do this if we have complete scope information. // But only do this if we have complete scope information.
while (!NeedsAndHasContext() && AdvanceOneScope()) { while (!NeedsContext() && AdvanceOneScope()) {
} }
} }
} }
...@@ -486,29 +492,28 @@ ScopeIterator::ScopeType ScopeIterator::Type() const { ...@@ -486,29 +492,28 @@ ScopeIterator::ScopeType ScopeIterator::Type() const {
if (InInnerScope()) { if (InInnerScope()) {
switch (current_scope_->scope_type()) { switch (current_scope_->scope_type()) {
case FUNCTION_SCOPE: case FUNCTION_SCOPE:
DCHECK_IMPLIES(NeedsAndHasContext(), DCHECK_IMPLIES(NeedsContext(), context_->IsFunctionContext() ||
context_->IsFunctionContext() ||
context_->IsDebugEvaluateContext()); context_->IsDebugEvaluateContext());
return ScopeTypeLocal; return ScopeTypeLocal;
case MODULE_SCOPE: case MODULE_SCOPE:
DCHECK_IMPLIES(NeedsAndHasContext(), context_->IsModuleContext()); DCHECK_IMPLIES(NeedsContext(), context_->IsModuleContext());
return ScopeTypeModule; return ScopeTypeModule;
case SCRIPT_SCOPE: case SCRIPT_SCOPE:
DCHECK_IMPLIES(NeedsAndHasContext(), context_->IsScriptContext() || DCHECK_IMPLIES(NeedsContext(), context_->IsScriptContext() ||
context_->IsNativeContext()); context_->IsNativeContext());
return ScopeTypeScript; return ScopeTypeScript;
case WITH_SCOPE: case WITH_SCOPE:
DCHECK_IMPLIES(NeedsAndHasContext(), context_->IsWithContext()); DCHECK_IMPLIES(NeedsContext(), context_->IsWithContext());
return ScopeTypeWith; return ScopeTypeWith;
case CATCH_SCOPE: case CATCH_SCOPE:
DCHECK(context_->IsCatchContext()); DCHECK(context_->IsCatchContext());
return ScopeTypeCatch; return ScopeTypeCatch;
case BLOCK_SCOPE: case BLOCK_SCOPE:
case CLASS_SCOPE: case CLASS_SCOPE:
DCHECK_IMPLIES(NeedsAndHasContext(), context_->IsBlockContext()); DCHECK_IMPLIES(NeedsContext(), context_->IsBlockContext());
return ScopeTypeBlock; return ScopeTypeBlock;
case EVAL_SCOPE: case EVAL_SCOPE:
DCHECK_IMPLIES(NeedsAndHasContext(), context_->IsEvalContext()); DCHECK_IMPLIES(NeedsContext(), context_->IsEvalContext());
return ScopeTypeEval; return ScopeTypeEval;
} }
UNREACHABLE(); UNREACHABLE();
...@@ -642,7 +647,7 @@ bool ScopeIterator::SetVariableValue(Handle<String> name, ...@@ -642,7 +647,7 @@ bool ScopeIterator::SetVariableValue(Handle<String> name,
DCHECK_EQ(ScopeTypeLocal, Type()); DCHECK_EQ(ScopeTypeLocal, Type());
if (SetLocalVariableValue(name, value)) return true; if (SetLocalVariableValue(name, value)) return true;
// There may not be an associated context since we're InInnerScope(). // There may not be an associated context since we're InInnerScope().
if (!NeedsAndHasContext()) return false; if (!NeedsContext()) return false;
} else { } else {
DCHECK_EQ(ScopeTypeClosure, Type()); DCHECK_EQ(ScopeTypeClosure, Type());
if (SetContextVariableValue(name, value)) return true; if (SetContextVariableValue(name, value)) return true;
...@@ -688,7 +693,7 @@ void ScopeIterator::DebugPrint() { ...@@ -688,7 +693,7 @@ void ScopeIterator::DebugPrint() {
case ScopeIterator::ScopeTypeLocal: { case ScopeIterator::ScopeTypeLocal: {
os << "Local:\n"; os << "Local:\n";
if (NeedsAndHasContext()) { if (NeedsContext()) {
context_->Print(os); context_->Print(os);
if (context_->has_extension()) { if (context_->has_extension()) {
Handle<HeapObject> extension(context_->extension(), isolate_); Handle<HeapObject> extension(context_->extension(), isolate_);
......
...@@ -101,7 +101,7 @@ class ScopeIterator { ...@@ -101,7 +101,7 @@ class ScopeIterator {
bool InInnerScope() const { return !function_.is_null(); } bool InInnerScope() const { return !function_.is_null(); }
bool HasContext() const; bool HasContext() const;
bool NeedsAndHasContext() const; bool NeedsContext() const;
Handle<Context> CurrentContext() const { Handle<Context> CurrentContext() const {
DCHECK(HasContext()); DCHECK(HasContext());
return context_; return context_;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment