Commit d820268c authored by rmcilroy's avatar rmcilroy Committed by Commit bot

Add support for calculating a scopes maximum nested context chain.

Adds Scope::MaxNestedContextChainLength() which calculates the maximum length
of the context chain for the given scope. This is used by the interpreter to
preallocate the approprate number of context registers when compiling the
function.

BUG=v8:4280
LOG=N

Review URL: https://codereview.chromium.org/1404793004

Cr-Commit-Position: refs/heads/master@{#31309}
parent 41e0965c
......@@ -153,11 +153,10 @@ Handle<BytecodeArray> BytecodeGenerator::MakeBytecode(CompilationInfo* info) {
builder()->set_parameter_count(info->num_parameters_including_this());
builder()->set_locals_count(scope()->num_stack_slots());
// TODO(rmcilroy): Set correct context count.
builder()->set_context_count(info->num_heap_slots() > 0 ? 1 : 0);
builder()->set_context_count(scope()->MaxNestedContextChainLength());
// Build function context only if there are context allocated variables.
if (info->num_heap_slots() > 0) {
if (scope()->NeedsContext()) {
// Push a new inner context scope for the function.
VisitNewLocalFunctionContext();
ContextScope top_context(this, true);
......
......@@ -765,15 +765,26 @@ int Scope::ContextChainLength(Scope* scope) {
int n = 0;
for (Scope* s = this; s != scope; s = s->outer_scope_) {
DCHECK(s != NULL); // scope must be in the scope chain
if (s->is_with_scope() || s->num_heap_slots() > 0) n++;
// Catch and module scopes always have heap slots.
DCHECK(!s->is_catch_scope() || s->num_heap_slots() > 0);
DCHECK(!s->is_module_scope() || s->num_heap_slots() > 0);
if (s->NeedsContext()) n++;
}
return n;
}
int Scope::MaxNestedContextChainLength() {
int max_context_chain_length = 0;
for (int i = 0; i < inner_scopes_.length(); i++) {
Scope* scope = inner_scopes_[i];
max_context_chain_length = std::max(scope->MaxNestedContextChainLength(),
max_context_chain_length);
}
if (NeedsContext()) {
max_context_chain_length += 1;
}
return max_context_chain_length;
}
Scope* Scope::DeclarationScope() {
Scope* scope = this;
while (!scope->is_declaration_scope()) {
......
......@@ -341,7 +341,12 @@ class Scope: public ZoneObject {
bool is_nonlinear() const { return scope_nonlinear_; }
// Whether this needs to be represented by a runtime context.
bool NeedsContext() const { return num_heap_slots() > 0; }
bool NeedsContext() const {
// Catch and module scopes always have heap slots.
DCHECK(!is_catch_scope() || num_heap_slots() > 0);
DCHECK(!is_module_scope() || num_heap_slots() > 0);
return is_with_scope() || num_heap_slots() > 0;
}
bool NeedsHomeObject() const {
return scope_uses_super_property_ ||
......@@ -519,6 +524,10 @@ class Scope: public ZoneObject {
// The number of contexts between this and scope; zero if this == scope.
int ContextChainLength(Scope* scope);
// The maximum number of nested contexts required for this scope and any inner
// scopes.
int MaxNestedContextChainLength();
// Find the first function, script, eval or (declaration) block scope. This is
// the scope where var declarations will be hoisted to in the implementation.
Scope* DeclarationScope();
......
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