Commit 8f8a9067 authored by verwaest's avatar verwaest Committed by Commit bot

Find the last outer eval scope to check in fullcodegen rather than scope analysis

This is the only user of outer_scope_calls_sloppy_eval. Inlining it simplifies scope analysis.

BUG=v8:5209

Review-Url: https://codereview.chromium.org/2263123002
Cr-Commit-Position: refs/heads/master@{#38779}
parent 0996cea5
...@@ -214,7 +214,6 @@ void Scope::SetDefaults() { ...@@ -214,7 +214,6 @@ void Scope::SetDefaults() {
is_hidden_ = false; is_hidden_ = false;
is_debug_evaluate_scope_ = false; is_debug_evaluate_scope_ = false;
outer_scope_calls_sloppy_eval_ = false;
inner_scope_calls_eval_ = false; inner_scope_calls_eval_ = false;
force_eager_compilation_ = false; force_eager_compilation_ = false;
force_context_allocation_ = false; force_context_allocation_ = false;
...@@ -297,7 +296,7 @@ Scope* Scope::DeserializeScopeChain(Isolate* isolate, Zone* zone, ...@@ -297,7 +296,7 @@ Scope* Scope::DeserializeScopeChain(Isolate* isolate, Zone* zone,
} }
script_scope->AddInnerScope(current_scope); script_scope->AddInnerScope(current_scope);
script_scope->PropagateScopeInfo(false); script_scope->PropagateScopeInfo();
return (innermost_scope == NULL) ? script_scope : innermost_scope; return (innermost_scope == NULL) ? script_scope : innermost_scope;
} }
...@@ -864,13 +863,7 @@ void Scope::CollectStackAndContextLocals(ZoneList<Variable*>* stack_locals, ...@@ -864,13 +863,7 @@ void Scope::CollectStackAndContextLocals(ZoneList<Variable*>* stack_locals,
void DeclarationScope::AllocateVariables(ParseInfo* info, void DeclarationScope::AllocateVariables(ParseInfo* info,
AstNodeFactory* factory) { AstNodeFactory* factory) {
// 1) Propagate scope information. // 1) Propagate scope information.
bool outer_scope_calls_sloppy_eval = false; PropagateScopeInfo();
if (outer_scope_ != NULL) {
outer_scope_calls_sloppy_eval =
outer_scope_->outer_scope_calls_sloppy_eval() |
outer_scope_->calls_sloppy_eval();
}
PropagateScopeInfo(outer_scope_calls_sloppy_eval);
// 2) Resolve variables. // 2) Resolve variables.
ResolveVariablesRecursively(info, factory); ResolveVariablesRecursively(info, factory);
...@@ -905,16 +898,27 @@ bool Scope::AllowsLazyCompilationWithoutContext() const { ...@@ -905,16 +898,27 @@ bool Scope::AllowsLazyCompilationWithoutContext() const {
return true; return true;
} }
int Scope::ContextChainLength(Scope* scope) const {
int Scope::ContextChainLength(Scope* scope) {
int n = 0; int n = 0;
for (Scope* s = this; s != scope; s = s->outer_scope_) { for (const Scope* s = this; s != scope; s = s->outer_scope_) {
DCHECK(s != NULL); // scope must be in the scope chain DCHECK(s != NULL); // scope must be in the scope chain
if (s->NeedsContext()) n++; if (s->NeedsContext()) n++;
} }
return n; return n;
} }
int Scope::ContextChainLengthUntilOutermostSloppyEval() const {
int result = 0;
int length = 0;
for (const Scope* s = this; s != nullptr; s = s->outer_scope()) {
if (!s->NeedsContext()) continue;
length++;
if (s->calls_sloppy_eval()) result = length;
}
return result;
}
int Scope::MaxNestedContextChainLength() { int Scope::MaxNestedContextChainLength() {
int max_context_chain_length = 0; int max_context_chain_length = 0;
...@@ -976,7 +980,7 @@ Handle<StringSet> DeclarationScope::CollectNonLocals( ...@@ -976,7 +980,7 @@ Handle<StringSet> DeclarationScope::CollectNonLocals(
void DeclarationScope::AnalyzePartially(DeclarationScope* migrate_to, void DeclarationScope::AnalyzePartially(DeclarationScope* migrate_to,
AstNodeFactory* ast_node_factory) { AstNodeFactory* ast_node_factory) {
// Gather info from inner scopes. // Gather info from inner scopes.
PropagateScopeInfo(false); PropagateScopeInfo();
// Try to resolve unresolved variables for this Scope and migrate those which // Try to resolve unresolved variables for this Scope and migrate those which
// cannot be resolved inside. It doesn't make sense to try to resolve them in // cannot be resolved inside. It doesn't make sense to try to resolve them in
...@@ -1154,9 +1158,6 @@ void Scope::Print(int n) { ...@@ -1154,9 +1158,6 @@ void Scope::Print(int n) {
if (scope_calls_eval_) Indent(n1, "// scope calls 'eval'\n"); if (scope_calls_eval_) Indent(n1, "// scope calls 'eval'\n");
if (scope_uses_super_property_) if (scope_uses_super_property_)
Indent(n1, "// scope uses 'super' property\n"); Indent(n1, "// scope uses 'super' property\n");
if (outer_scope_calls_sloppy_eval_) {
Indent(n1, "// outer scope calls 'eval' in sloppy context\n");
}
if (inner_scope_calls_eval_) Indent(n1, "// inner scope calls 'eval'\n"); if (inner_scope_calls_eval_) Indent(n1, "// inner scope calls 'eval'\n");
if (num_stack_slots_ > 0) { if (num_stack_slots_ > 0) {
Indent(n1, "// "); Indent(n1, "// ");
...@@ -1464,15 +1465,9 @@ VariableProxy* Scope::FetchFreeVariables(DeclarationScope* max_outer_scope, ...@@ -1464,15 +1465,9 @@ VariableProxy* Scope::FetchFreeVariables(DeclarationScope* max_outer_scope,
return stack; return stack;
} }
void Scope::PropagateScopeInfo(bool outer_scope_calls_sloppy_eval) { void Scope::PropagateScopeInfo() {
if (outer_scope_calls_sloppy_eval) {
outer_scope_calls_sloppy_eval_ = true;
}
bool calls_sloppy_eval =
this->calls_sloppy_eval() || outer_scope_calls_sloppy_eval_;
for (Scope* inner = inner_scope_; inner != nullptr; inner = inner->sibling_) { for (Scope* inner = inner_scope_; inner != nullptr; inner = inner->sibling_) {
inner->PropagateScopeInfo(calls_sloppy_eval); inner->PropagateScopeInfo();
if (inner->scope_calls_eval_ || inner->inner_scope_calls_eval_) { if (inner->scope_calls_eval_ || inner->inner_scope_calls_eval_) {
inner_scope_calls_eval_ = true; inner_scope_calls_eval_ = true;
} }
......
...@@ -310,9 +310,6 @@ class Scope: public ZoneObject { ...@@ -310,9 +310,6 @@ class Scope: public ZoneObject {
bool calls_sloppy_eval() const { bool calls_sloppy_eval() const {
return scope_calls_eval_ && is_sloppy(language_mode()); return scope_calls_eval_ && is_sloppy(language_mode());
} }
bool outer_scope_calls_sloppy_eval() const {
return outer_scope_calls_sloppy_eval_;
}
bool IsAsmModule() const; bool IsAsmModule() const;
bool IsAsmFunction() const; bool IsAsmFunction() const;
// Does this scope access "super" property (super.foo). // Does this scope access "super" property (super.foo).
...@@ -383,7 +380,11 @@ class Scope: public ZoneObject { ...@@ -383,7 +380,11 @@ class Scope: public ZoneObject {
bool AllowsLazyCompilationWithoutContext() const; bool AllowsLazyCompilationWithoutContext() const;
// The number of contexts between this and scope; zero if this == scope. // The number of contexts between this and scope; zero if this == scope.
int ContextChainLength(Scope* scope); int ContextChainLength(Scope* scope) const;
// The number of contexts between this and the outermost context that has a
// sloppy eval call. One if this->calls_sloppy_eval().
int ContextChainLengthUntilOutermostSloppyEval() const;
// The maximum number of nested contexts required for this scope and any inner // The maximum number of nested contexts required for this scope and any inner
// scopes. // scopes.
...@@ -512,7 +513,6 @@ class Scope: public ZoneObject { ...@@ -512,7 +513,6 @@ class Scope: public ZoneObject {
bool is_debug_evaluate_scope_ : 1; bool is_debug_evaluate_scope_ : 1;
// Computed via PropagateScopeInfo. // Computed via PropagateScopeInfo.
bool outer_scope_calls_sloppy_eval_ : 1;
bool inner_scope_calls_eval_ : 1; bool inner_scope_calls_eval_ : 1;
bool force_eager_compilation_ : 1; bool force_eager_compilation_ : 1;
bool force_context_allocation_ : 1; bool force_context_allocation_ : 1;
...@@ -591,7 +591,7 @@ class Scope: public ZoneObject { ...@@ -591,7 +591,7 @@ class Scope: public ZoneObject {
VariableProxy* stack = nullptr); VariableProxy* stack = nullptr);
// Scope analysis. // Scope analysis.
void PropagateScopeInfo(bool outer_scope_calls_sloppy_eval); void PropagateScopeInfo();
// Predicates. // Predicates.
bool MustAllocate(Variable* var); bool MustAllocate(Variable* var);
......
...@@ -1184,23 +1184,19 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy, ...@@ -1184,23 +1184,19 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy,
Register next = r1; Register next = r1;
Register temp = r2; Register temp = r2;
Scope* s = scope(); int to_check = scope()->ContextChainLengthUntilOutermostSloppyEval();
while (s != NULL) { for (Scope* s = scope(); to_check > 0; s = s->outer_scope()) {
if (s->num_heap_slots() > 0) { if (!s->NeedsContext()) continue;
if (s->calls_sloppy_eval()) { if (s->calls_sloppy_eval()) {
// Check that extension is "the hole". // Check that extension is "the hole".
__ ldr(temp, ContextMemOperand(current, Context::EXTENSION_INDEX)); __ ldr(temp, ContextMemOperand(current, Context::EXTENSION_INDEX));
__ JumpIfNotRoot(temp, Heap::kTheHoleValueRootIndex, slow); __ JumpIfNotRoot(temp, Heap::kTheHoleValueRootIndex, slow);
} }
// Load next context in chain. // Load next context in chain.
__ ldr(next, ContextMemOperand(current, Context::PREVIOUS_INDEX)); __ ldr(next, ContextMemOperand(current, Context::PREVIOUS_INDEX));
// Walk the rest of the chain without clobbering cp. // Walk the rest of the chain without clobbering cp.
current = next; current = next;
} to_check--;
// If no outer scope calls eval, we do not need to check more
// context extensions.
if (!s->outer_scope_calls_sloppy_eval()) break;
s = s->outer_scope();
} }
// All extension objects were empty and it is safe to use a normal global // All extension objects were empty and it is safe to use a normal global
......
...@@ -1172,23 +1172,19 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy, ...@@ -1172,23 +1172,19 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy,
Register next = x10; Register next = x10;
Register temp = x11; Register temp = x11;
Scope* s = scope(); int to_check = scope()->ContextChainLengthUntilOutermostSloppyEval();
while (s != NULL) { for (Scope* s = scope(); to_check > 0; s = s->outer_scope()) {
if (s->num_heap_slots() > 0) { if (!s->NeedsContext()) continue;
if (s->calls_sloppy_eval()) { if (s->calls_sloppy_eval()) {
// Check that extension is "the hole". // Check that extension is "the hole".
__ Ldr(temp, ContextMemOperand(current, Context::EXTENSION_INDEX)); __ Ldr(temp, ContextMemOperand(current, Context::EXTENSION_INDEX));
__ JumpIfNotRoot(temp, Heap::kTheHoleValueRootIndex, slow); __ JumpIfNotRoot(temp, Heap::kTheHoleValueRootIndex, slow);
} }
// Load next context in chain. // Load next context in chain.
__ Ldr(next, ContextMemOperand(current, Context::PREVIOUS_INDEX)); __ Ldr(next, ContextMemOperand(current, Context::PREVIOUS_INDEX));
// Walk the rest of the chain without clobbering cp. // Walk the rest of the chain without clobbering cp.
current = next; current = next;
} to_check--;
// If no outer scope calls eval, we do not need to check more
// context extensions.
if (!s->outer_scope_calls_sloppy_eval()) break;
s = s->outer_scope();
} }
// All extension objects were empty and it is safe to use a normal global // All extension objects were empty and it is safe to use a normal global
......
...@@ -1108,23 +1108,19 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy, ...@@ -1108,23 +1108,19 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy,
Register context = esi; Register context = esi;
Register temp = edx; Register temp = edx;
Scope* s = scope(); int to_check = scope()->ContextChainLengthUntilOutermostSloppyEval();
while (s != NULL) { for (Scope* s = scope(); to_check > 0; s = s->outer_scope()) {
if (s->num_heap_slots() > 0) { if (!s->NeedsContext()) continue;
if (s->calls_sloppy_eval()) { if (s->calls_sloppy_eval()) {
// Check that extension is "the hole". // Check that extension is "the hole".
__ JumpIfNotRoot(ContextOperand(context, Context::EXTENSION_INDEX), __ JumpIfNotRoot(ContextOperand(context, Context::EXTENSION_INDEX),
Heap::kTheHoleValueRootIndex, slow); Heap::kTheHoleValueRootIndex, slow);
} }
// Load next context in chain. // Load next context in chain.
__ mov(temp, ContextOperand(context, Context::PREVIOUS_INDEX)); __ mov(temp, ContextOperand(context, Context::PREVIOUS_INDEX));
// Walk the rest of the chain without clobbering esi. // Walk the rest of the chain without clobbering esi.
context = temp; context = temp;
} to_check--;
// If no outer scope calls eval, we do not need to check more
// context extensions.
if (!s->outer_scope_calls_sloppy_eval()) break;
s = s->outer_scope();
} }
// All extension objects were empty and it is safe to use a normal global // All extension objects were empty and it is safe to use a normal global
......
...@@ -1179,23 +1179,19 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy, ...@@ -1179,23 +1179,19 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy,
Register next = a1; Register next = a1;
Register temp = a2; Register temp = a2;
Scope* s = scope(); int to_check = scope()->ContextChainLengthUntilOutermostSloppyEval();
while (s != NULL) { for (Scope* s = scope(); to_check > 0; s = s->outer_scope()) {
if (s->num_heap_slots() > 0) { if (!s->NeedsContext()) continue;
if (s->calls_sloppy_eval()) { if (s->calls_sloppy_eval()) {
// Check that extension is "the hole". // Check that extension is "the hole".
__ lw(temp, ContextMemOperand(current, Context::EXTENSION_INDEX)); __ lw(temp, ContextMemOperand(current, Context::EXTENSION_INDEX));
__ JumpIfNotRoot(temp, Heap::kTheHoleValueRootIndex, slow); __ JumpIfNotRoot(temp, Heap::kTheHoleValueRootIndex, slow);
} }
// Load next context in chain. // Load next context in chain.
__ lw(next, ContextMemOperand(current, Context::PREVIOUS_INDEX)); __ lw(next, ContextMemOperand(current, Context::PREVIOUS_INDEX));
// Walk the rest of the chain without clobbering cp. // Walk the rest of the chain without clobbering cp.
current = next; current = next;
} to_check--;
// If no outer scope calls eval, we do not need to check more
// context extensions.
if (!s->outer_scope_calls_sloppy_eval()) break;
s = s->outer_scope();
} }
// All extension objects were empty and it is safe to use a normal global // All extension objects were empty and it is safe to use a normal global
......
...@@ -1180,23 +1180,19 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy, ...@@ -1180,23 +1180,19 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy,
Register next = a1; Register next = a1;
Register temp = a2; Register temp = a2;
Scope* s = scope(); int to_check = scope()->ContextChainLengthUntilOutermostSloppyEval();
while (s != NULL) { for (Scope* s = scope(); to_check > 0; s = s->outer_scope()) {
if (s->num_heap_slots() > 0) { if (!s->NeedsContext()) continue;
if (s->calls_sloppy_eval()) { if (s->calls_sloppy_eval()) {
// Check that extension is "the hole". // Check that extension is "the hole".
__ ld(temp, ContextMemOperand(current, Context::EXTENSION_INDEX)); __ ld(temp, ContextMemOperand(current, Context::EXTENSION_INDEX));
__ JumpIfNotRoot(temp, Heap::kTheHoleValueRootIndex, slow); __ JumpIfNotRoot(temp, Heap::kTheHoleValueRootIndex, slow);
} }
// Load next context in chain. // Load next context in chain.
__ ld(next, ContextMemOperand(current, Context::PREVIOUS_INDEX)); __ ld(next, ContextMemOperand(current, Context::PREVIOUS_INDEX));
// Walk the rest of the chain without clobbering cp. // Walk the rest of the chain without clobbering cp.
current = next; current = next;
} to_check--;
// If no outer scope calls eval, we do not need to check more
// context extensions.
if (!s->outer_scope_calls_sloppy_eval()) break;
s = s->outer_scope();
} }
// All extension objects were empty and it is safe to use a normal global // All extension objects were empty and it is safe to use a normal global
......
...@@ -1148,23 +1148,19 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy, ...@@ -1148,23 +1148,19 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy,
Register next = r4; Register next = r4;
Register temp = r5; Register temp = r5;
Scope* s = scope(); int to_check = scope()->ContextChainLengthUntilOutermostSloppyEval();
while (s != NULL) { for (Scope* s = scope(); to_check > 0; s = s->outer_scope()) {
if (s->num_heap_slots() > 0) { if (!s->NeedsContext()) continue;
if (s->calls_sloppy_eval()) { if (s->calls_sloppy_eval()) {
// Check that extension is "the hole". // Check that extension is "the hole".
__ LoadP(temp, ContextMemOperand(current, Context::EXTENSION_INDEX)); __ LoadP(temp, ContextMemOperand(current, Context::EXTENSION_INDEX));
__ JumpIfNotRoot(temp, Heap::kTheHoleValueRootIndex, slow); __ JumpIfNotRoot(temp, Heap::kTheHoleValueRootIndex, slow);
} }
// Load next context in chain. // Load next context in chain.
__ LoadP(next, ContextMemOperand(current, Context::PREVIOUS_INDEX)); __ LoadP(next, ContextMemOperand(current, Context::PREVIOUS_INDEX));
// Walk the rest of the chain without clobbering cp. // Walk the rest of the chain without clobbering cp.
current = next; current = next;
} to_check--;
// If no outer scope calls eval, we do not need to check more
// context extensions.
if (!s->outer_scope_calls_sloppy_eval()) break;
s = s->outer_scope();
} }
// All extension objects were empty and it is safe to use a normal global // All extension objects were empty and it is safe to use a normal global
......
...@@ -1115,23 +1115,19 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy, ...@@ -1115,23 +1115,19 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy,
Register next = r3; Register next = r3;
Register temp = r4; Register temp = r4;
Scope* s = scope(); int to_check = scope()->ContextChainLengthUntilOutermostSloppyEval();
while (s != NULL) { for (Scope* s = scope(); to_check > 0; s = s->outer_scope()) {
if (s->num_heap_slots() > 0) { if (!s->NeedsContext()) continue;
if (s->calls_sloppy_eval()) { if (s->calls_sloppy_eval()) {
// Check that extension is "the hole". // Check that extension is "the hole".
__ LoadP(temp, ContextMemOperand(current, Context::EXTENSION_INDEX)); __ LoadP(temp, ContextMemOperand(current, Context::EXTENSION_INDEX));
__ JumpIfNotRoot(temp, Heap::kTheHoleValueRootIndex, slow); __ JumpIfNotRoot(temp, Heap::kTheHoleValueRootIndex, slow);
} }
// Load next context in chain. // Load next context in chain.
__ LoadP(next, ContextMemOperand(current, Context::PREVIOUS_INDEX)); __ LoadP(next, ContextMemOperand(current, Context::PREVIOUS_INDEX));
// Walk the rest of the chain without clobbering cp. // Walk the rest of the chain without clobbering cp.
current = next; current = next;
} to_check--;
// If no outer scope calls eval, we do not need to check more
// context extensions.
if (!s->outer_scope_calls_sloppy_eval()) break;
s = s->outer_scope();
} }
// All extension objects were empty and it is safe to use a normal global // All extension objects were empty and it is safe to use a normal global
......
...@@ -1136,23 +1136,19 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy, ...@@ -1136,23 +1136,19 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy,
Register context = rsi; Register context = rsi;
Register temp = rdx; Register temp = rdx;
Scope* s = scope(); int to_check = scope()->ContextChainLengthUntilOutermostSloppyEval();
while (s != NULL) { for (Scope* s = scope(); to_check > 0; s = s->outer_scope()) {
if (s->num_heap_slots() > 0) { if (!s->NeedsContext()) continue;
if (s->calls_sloppy_eval()) { if (s->calls_sloppy_eval()) {
// Check that extension is "the hole". // Check that extension is "the hole".
__ JumpIfNotRoot(ContextOperand(context, Context::EXTENSION_INDEX), __ JumpIfNotRoot(ContextOperand(context, Context::EXTENSION_INDEX),
Heap::kTheHoleValueRootIndex, slow); Heap::kTheHoleValueRootIndex, slow);
} }
// Load next context in chain. // Load next context in chain.
__ movp(temp, ContextOperand(context, Context::PREVIOUS_INDEX)); __ movp(temp, ContextOperand(context, Context::PREVIOUS_INDEX));
// Walk the rest of the chain without clobbering rsi. // Walk the rest of the chain without clobbering rsi.
context = temp; context = temp;
} to_check--;
// If no outer scope calls eval, we do not need to check more
// context extensions.
if (!s->outer_scope_calls_sloppy_eval()) break;
s = s->outer_scope();
} }
// All extension objects were empty and it is safe to use a normal global // All extension objects were empty and it is safe to use a normal global
......
...@@ -1100,24 +1100,19 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy, ...@@ -1100,24 +1100,19 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy,
Register context = esi; Register context = esi;
Register temp = edx; Register temp = edx;
Scope* s = scope(); int to_check = scope()->ContextChainLengthUntilOutermostSloppyEval();
while (s != NULL) { for (Scope* s = scope(); to_check > 0; s = s->outer_scope()) {
if (s->num_heap_slots() > 0) { if (!s->NeedsContext()) continue;
if (s->calls_sloppy_eval()) { if (s->calls_sloppy_eval()) {
// Check that extension is "the hole". // Check that extension is "the hole".
__ JumpIfNotRoot(ContextOperand(context, Context::EXTENSION_INDEX), __ JumpIfNotRoot(ContextOperand(context, Context::EXTENSION_INDEX),
Heap::kTheHoleValueRootIndex, slow); Heap::kTheHoleValueRootIndex, slow);
} }
// Load next context in chain. // Load next context in chain.
__ mov(temp, ContextOperand(context, Context::PREVIOUS_INDEX)); __ mov(temp, ContextOperand(context, Context::PREVIOUS_INDEX));
// Walk the rest of the chain without clobbering esi. // Walk the rest of the chain without clobbering esi.
context = temp; context = temp;
} to_check--;
// If no outer scope calls eval, we do not need to check more
// context extensions. If we have reached an eval scope, we check
// all extensions from this point.
if (!s->outer_scope_calls_sloppy_eval()) break;
s = s->outer_scope();
} }
// All extension objects were empty and it is safe to use a normal global // All extension objects were empty and it is safe to use a normal global
......
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