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() {
is_hidden_ = false;
is_debug_evaluate_scope_ = false;
outer_scope_calls_sloppy_eval_ = false;
inner_scope_calls_eval_ = false;
force_eager_compilation_ = false;
force_context_allocation_ = false;
......@@ -297,7 +296,7 @@ Scope* Scope::DeserializeScopeChain(Isolate* isolate, Zone* zone,
}
script_scope->AddInnerScope(current_scope);
script_scope->PropagateScopeInfo(false);
script_scope->PropagateScopeInfo();
return (innermost_scope == NULL) ? script_scope : innermost_scope;
}
......@@ -864,13 +863,7 @@ void Scope::CollectStackAndContextLocals(ZoneList<Variable*>* stack_locals,
void DeclarationScope::AllocateVariables(ParseInfo* info,
AstNodeFactory* factory) {
// 1) Propagate scope information.
bool outer_scope_calls_sloppy_eval = false;
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);
PropagateScopeInfo();
// 2) Resolve variables.
ResolveVariablesRecursively(info, factory);
......@@ -905,16 +898,27 @@ bool Scope::AllowsLazyCompilationWithoutContext() const {
return true;
}
int Scope::ContextChainLength(Scope* scope) {
int Scope::ContextChainLength(Scope* scope) const {
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
if (s->NeedsContext()) 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 max_context_chain_length = 0;
......@@ -976,7 +980,7 @@ Handle<StringSet> DeclarationScope::CollectNonLocals(
void DeclarationScope::AnalyzePartially(DeclarationScope* migrate_to,
AstNodeFactory* ast_node_factory) {
// Gather info from inner scopes.
PropagateScopeInfo(false);
PropagateScopeInfo();
// 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
......@@ -1154,9 +1158,6 @@ void Scope::Print(int n) {
if (scope_calls_eval_) Indent(n1, "// scope calls 'eval'\n");
if (scope_uses_super_property_)
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 (num_stack_slots_ > 0) {
Indent(n1, "// ");
......@@ -1464,15 +1465,9 @@ VariableProxy* Scope::FetchFreeVariables(DeclarationScope* max_outer_scope,
return stack;
}
void Scope::PropagateScopeInfo(bool outer_scope_calls_sloppy_eval) {
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_;
void Scope::PropagateScopeInfo() {
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_) {
inner_scope_calls_eval_ = true;
}
......
......@@ -310,9 +310,6 @@ class Scope: public ZoneObject {
bool calls_sloppy_eval() const {
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 IsAsmFunction() const;
// Does this scope access "super" property (super.foo).
......@@ -383,7 +380,11 @@ class Scope: public ZoneObject {
bool AllowsLazyCompilationWithoutContext() const;
// 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
// scopes.
......@@ -512,7 +513,6 @@ class Scope: public ZoneObject {
bool is_debug_evaluate_scope_ : 1;
// Computed via PropagateScopeInfo.
bool outer_scope_calls_sloppy_eval_ : 1;
bool inner_scope_calls_eval_ : 1;
bool force_eager_compilation_ : 1;
bool force_context_allocation_ : 1;
......@@ -591,7 +591,7 @@ class Scope: public ZoneObject {
VariableProxy* stack = nullptr);
// Scope analysis.
void PropagateScopeInfo(bool outer_scope_calls_sloppy_eval);
void PropagateScopeInfo();
// Predicates.
bool MustAllocate(Variable* var);
......
......@@ -1184,23 +1184,19 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy,
Register next = r1;
Register temp = r2;
Scope* s = scope();
while (s != NULL) {
if (s->num_heap_slots() > 0) {
if (s->calls_sloppy_eval()) {
// Check that extension is "the hole".
__ ldr(temp, ContextMemOperand(current, Context::EXTENSION_INDEX));
__ JumpIfNotRoot(temp, Heap::kTheHoleValueRootIndex, slow);
}
// Load next context in chain.
__ ldr(next, ContextMemOperand(current, Context::PREVIOUS_INDEX));
// Walk the rest of the chain without clobbering cp.
current = next;
}
// 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();
int to_check = scope()->ContextChainLengthUntilOutermostSloppyEval();
for (Scope* s = scope(); to_check > 0; s = s->outer_scope()) {
if (!s->NeedsContext()) continue;
if (s->calls_sloppy_eval()) {
// Check that extension is "the hole".
__ ldr(temp, ContextMemOperand(current, Context::EXTENSION_INDEX));
__ JumpIfNotRoot(temp, Heap::kTheHoleValueRootIndex, slow);
}
// Load next context in chain.
__ ldr(next, ContextMemOperand(current, Context::PREVIOUS_INDEX));
// Walk the rest of the chain without clobbering cp.
current = next;
to_check--;
}
// All extension objects were empty and it is safe to use a normal global
......
......@@ -1172,23 +1172,19 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy,
Register next = x10;
Register temp = x11;
Scope* s = scope();
while (s != NULL) {
if (s->num_heap_slots() > 0) {
if (s->calls_sloppy_eval()) {
// Check that extension is "the hole".
__ Ldr(temp, ContextMemOperand(current, Context::EXTENSION_INDEX));
__ JumpIfNotRoot(temp, Heap::kTheHoleValueRootIndex, slow);
}
// Load next context in chain.
__ Ldr(next, ContextMemOperand(current, Context::PREVIOUS_INDEX));
// Walk the rest of the chain without clobbering cp.
current = next;
}
// 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();
int to_check = scope()->ContextChainLengthUntilOutermostSloppyEval();
for (Scope* s = scope(); to_check > 0; s = s->outer_scope()) {
if (!s->NeedsContext()) continue;
if (s->calls_sloppy_eval()) {
// Check that extension is "the hole".
__ Ldr(temp, ContextMemOperand(current, Context::EXTENSION_INDEX));
__ JumpIfNotRoot(temp, Heap::kTheHoleValueRootIndex, slow);
}
// Load next context in chain.
__ Ldr(next, ContextMemOperand(current, Context::PREVIOUS_INDEX));
// Walk the rest of the chain without clobbering cp.
current = next;
to_check--;
}
// All extension objects were empty and it is safe to use a normal global
......
......@@ -1108,23 +1108,19 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy,
Register context = esi;
Register temp = edx;
Scope* s = scope();
while (s != NULL) {
if (s->num_heap_slots() > 0) {
if (s->calls_sloppy_eval()) {
// Check that extension is "the hole".
__ JumpIfNotRoot(ContextOperand(context, Context::EXTENSION_INDEX),
Heap::kTheHoleValueRootIndex, slow);
}
// Load next context in chain.
__ mov(temp, ContextOperand(context, Context::PREVIOUS_INDEX));
// Walk the rest of the chain without clobbering esi.
context = temp;
}
// 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();
int to_check = scope()->ContextChainLengthUntilOutermostSloppyEval();
for (Scope* s = scope(); to_check > 0; s = s->outer_scope()) {
if (!s->NeedsContext()) continue;
if (s->calls_sloppy_eval()) {
// Check that extension is "the hole".
__ JumpIfNotRoot(ContextOperand(context, Context::EXTENSION_INDEX),
Heap::kTheHoleValueRootIndex, slow);
}
// Load next context in chain.
__ mov(temp, ContextOperand(context, Context::PREVIOUS_INDEX));
// Walk the rest of the chain without clobbering esi.
context = temp;
to_check--;
}
// All extension objects were empty and it is safe to use a normal global
......
......@@ -1179,23 +1179,19 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy,
Register next = a1;
Register temp = a2;
Scope* s = scope();
while (s != NULL) {
if (s->num_heap_slots() > 0) {
if (s->calls_sloppy_eval()) {
// Check that extension is "the hole".
__ lw(temp, ContextMemOperand(current, Context::EXTENSION_INDEX));
__ JumpIfNotRoot(temp, Heap::kTheHoleValueRootIndex, slow);
}
// Load next context in chain.
__ lw(next, ContextMemOperand(current, Context::PREVIOUS_INDEX));
// Walk the rest of the chain without clobbering cp.
current = next;
}
// 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();
int to_check = scope()->ContextChainLengthUntilOutermostSloppyEval();
for (Scope* s = scope(); to_check > 0; s = s->outer_scope()) {
if (!s->NeedsContext()) continue;
if (s->calls_sloppy_eval()) {
// Check that extension is "the hole".
__ lw(temp, ContextMemOperand(current, Context::EXTENSION_INDEX));
__ JumpIfNotRoot(temp, Heap::kTheHoleValueRootIndex, slow);
}
// Load next context in chain.
__ lw(next, ContextMemOperand(current, Context::PREVIOUS_INDEX));
// Walk the rest of the chain without clobbering cp.
current = next;
to_check--;
}
// All extension objects were empty and it is safe to use a normal global
......
......@@ -1180,23 +1180,19 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy,
Register next = a1;
Register temp = a2;
Scope* s = scope();
while (s != NULL) {
if (s->num_heap_slots() > 0) {
if (s->calls_sloppy_eval()) {
// Check that extension is "the hole".
__ ld(temp, ContextMemOperand(current, Context::EXTENSION_INDEX));
__ JumpIfNotRoot(temp, Heap::kTheHoleValueRootIndex, slow);
}
// Load next context in chain.
__ ld(next, ContextMemOperand(current, Context::PREVIOUS_INDEX));
// Walk the rest of the chain without clobbering cp.
current = next;
}
// 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();
int to_check = scope()->ContextChainLengthUntilOutermostSloppyEval();
for (Scope* s = scope(); to_check > 0; s = s->outer_scope()) {
if (!s->NeedsContext()) continue;
if (s->calls_sloppy_eval()) {
// Check that extension is "the hole".
__ ld(temp, ContextMemOperand(current, Context::EXTENSION_INDEX));
__ JumpIfNotRoot(temp, Heap::kTheHoleValueRootIndex, slow);
}
// Load next context in chain.
__ ld(next, ContextMemOperand(current, Context::PREVIOUS_INDEX));
// Walk the rest of the chain without clobbering cp.
current = next;
to_check--;
}
// All extension objects were empty and it is safe to use a normal global
......
......@@ -1148,23 +1148,19 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy,
Register next = r4;
Register temp = r5;
Scope* s = scope();
while (s != NULL) {
if (s->num_heap_slots() > 0) {
if (s->calls_sloppy_eval()) {
// Check that extension is "the hole".
__ LoadP(temp, ContextMemOperand(current, Context::EXTENSION_INDEX));
__ JumpIfNotRoot(temp, Heap::kTheHoleValueRootIndex, slow);
}
// Load next context in chain.
__ LoadP(next, ContextMemOperand(current, Context::PREVIOUS_INDEX));
// Walk the rest of the chain without clobbering cp.
current = next;
}
// 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();
int to_check = scope()->ContextChainLengthUntilOutermostSloppyEval();
for (Scope* s = scope(); to_check > 0; s = s->outer_scope()) {
if (!s->NeedsContext()) continue;
if (s->calls_sloppy_eval()) {
// Check that extension is "the hole".
__ LoadP(temp, ContextMemOperand(current, Context::EXTENSION_INDEX));
__ JumpIfNotRoot(temp, Heap::kTheHoleValueRootIndex, slow);
}
// Load next context in chain.
__ LoadP(next, ContextMemOperand(current, Context::PREVIOUS_INDEX));
// Walk the rest of the chain without clobbering cp.
current = next;
to_check--;
}
// All extension objects were empty and it is safe to use a normal global
......
......@@ -1115,23 +1115,19 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy,
Register next = r3;
Register temp = r4;
Scope* s = scope();
while (s != NULL) {
if (s->num_heap_slots() > 0) {
if (s->calls_sloppy_eval()) {
// Check that extension is "the hole".
__ LoadP(temp, ContextMemOperand(current, Context::EXTENSION_INDEX));
__ JumpIfNotRoot(temp, Heap::kTheHoleValueRootIndex, slow);
}
// Load next context in chain.
__ LoadP(next, ContextMemOperand(current, Context::PREVIOUS_INDEX));
// Walk the rest of the chain without clobbering cp.
current = next;
}
// 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();
int to_check = scope()->ContextChainLengthUntilOutermostSloppyEval();
for (Scope* s = scope(); to_check > 0; s = s->outer_scope()) {
if (!s->NeedsContext()) continue;
if (s->calls_sloppy_eval()) {
// Check that extension is "the hole".
__ LoadP(temp, ContextMemOperand(current, Context::EXTENSION_INDEX));
__ JumpIfNotRoot(temp, Heap::kTheHoleValueRootIndex, slow);
}
// Load next context in chain.
__ LoadP(next, ContextMemOperand(current, Context::PREVIOUS_INDEX));
// Walk the rest of the chain without clobbering cp.
current = next;
to_check--;
}
// All extension objects were empty and it is safe to use a normal global
......
......@@ -1136,23 +1136,19 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy,
Register context = rsi;
Register temp = rdx;
Scope* s = scope();
while (s != NULL) {
if (s->num_heap_slots() > 0) {
if (s->calls_sloppy_eval()) {
// Check that extension is "the hole".
__ JumpIfNotRoot(ContextOperand(context, Context::EXTENSION_INDEX),
Heap::kTheHoleValueRootIndex, slow);
}
// Load next context in chain.
__ movp(temp, ContextOperand(context, Context::PREVIOUS_INDEX));
// Walk the rest of the chain without clobbering rsi.
context = temp;
}
// 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();
int to_check = scope()->ContextChainLengthUntilOutermostSloppyEval();
for (Scope* s = scope(); to_check > 0; s = s->outer_scope()) {
if (!s->NeedsContext()) continue;
if (s->calls_sloppy_eval()) {
// Check that extension is "the hole".
__ JumpIfNotRoot(ContextOperand(context, Context::EXTENSION_INDEX),
Heap::kTheHoleValueRootIndex, slow);
}
// Load next context in chain.
__ movp(temp, ContextOperand(context, Context::PREVIOUS_INDEX));
// Walk the rest of the chain without clobbering rsi.
context = temp;
to_check--;
}
// All extension objects were empty and it is safe to use a normal global
......
......@@ -1100,24 +1100,19 @@ void FullCodeGenerator::EmitLoadGlobalCheckExtensions(VariableProxy* proxy,
Register context = esi;
Register temp = edx;
Scope* s = scope();
while (s != NULL) {
if (s->num_heap_slots() > 0) {
if (s->calls_sloppy_eval()) {
// Check that extension is "the hole".
__ JumpIfNotRoot(ContextOperand(context, Context::EXTENSION_INDEX),
Heap::kTheHoleValueRootIndex, slow);
}
// Load next context in chain.
__ mov(temp, ContextOperand(context, Context::PREVIOUS_INDEX));
// Walk the rest of the chain without clobbering esi.
context = temp;
}
// 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();
int to_check = scope()->ContextChainLengthUntilOutermostSloppyEval();
for (Scope* s = scope(); to_check > 0; s = s->outer_scope()) {
if (!s->NeedsContext()) continue;
if (s->calls_sloppy_eval()) {
// Check that extension is "the hole".
__ JumpIfNotRoot(ContextOperand(context, Context::EXTENSION_INDEX),
Heap::kTheHoleValueRootIndex, slow);
}
// Load next context in chain.
__ mov(temp, ContextOperand(context, Context::PREVIOUS_INDEX));
// Walk the rest of the chain without clobbering esi.
context = temp;
to_check--;
}
// 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