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}
This commit is contained in:
parent
41e0965c9c
commit
d820268c0b
@ -153,11 +153,10 @@ Handle<BytecodeArray> BytecodeGenerator::MakeBytecode(CompilationInfo* info) {
|
|||||||
|
|
||||||
builder()->set_parameter_count(info->num_parameters_including_this());
|
builder()->set_parameter_count(info->num_parameters_including_this());
|
||||||
builder()->set_locals_count(scope()->num_stack_slots());
|
builder()->set_locals_count(scope()->num_stack_slots());
|
||||||
// TODO(rmcilroy): Set correct context count.
|
builder()->set_context_count(scope()->MaxNestedContextChainLength());
|
||||||
builder()->set_context_count(info->num_heap_slots() > 0 ? 1 : 0);
|
|
||||||
|
|
||||||
// Build function context only if there are context allocated variables.
|
// 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.
|
// Push a new inner context scope for the function.
|
||||||
VisitNewLocalFunctionContext();
|
VisitNewLocalFunctionContext();
|
||||||
ContextScope top_context(this, true);
|
ContextScope top_context(this, true);
|
||||||
|
@ -765,15 +765,26 @@ int Scope::ContextChainLength(Scope* scope) {
|
|||||||
int n = 0;
|
int n = 0;
|
||||||
for (Scope* s = this; s != scope; s = s->outer_scope_) {
|
for (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->is_with_scope() || s->num_heap_slots() > 0) n++;
|
if (s->NeedsContext()) 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);
|
|
||||||
}
|
}
|
||||||
return 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::DeclarationScope() {
|
||||||
Scope* scope = this;
|
Scope* scope = this;
|
||||||
while (!scope->is_declaration_scope()) {
|
while (!scope->is_declaration_scope()) {
|
||||||
|
11
src/scopes.h
11
src/scopes.h
@ -341,7 +341,12 @@ class Scope: public ZoneObject {
|
|||||||
bool is_nonlinear() const { return scope_nonlinear_; }
|
bool is_nonlinear() const { return scope_nonlinear_; }
|
||||||
|
|
||||||
// Whether this needs to be represented by a runtime context.
|
// 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 {
|
bool NeedsHomeObject() const {
|
||||||
return scope_uses_super_property_ ||
|
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.
|
// The number of contexts between this and scope; zero if this == scope.
|
||||||
int ContextChainLength(Scope* 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
|
// Find the first function, script, eval or (declaration) block scope. This is
|
||||||
// the scope where var declarations will be hoisted to in the implementation.
|
// the scope where var declarations will be hoisted to in the implementation.
|
||||||
Scope* DeclarationScope();
|
Scope* DeclarationScope();
|
||||||
|
Loading…
Reference in New Issue
Block a user