Commit ccd2cd8f authored by keuchel@chromium.org's avatar keuchel@chromium.org

Prune empty block scopes from scope tree

BUG=
TEST=

Review URL: http://codereview.chromium.org/7825006

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9117 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent b7eb138e
...@@ -225,8 +225,7 @@ inline Heap* _inline_get_heap_(); ...@@ -225,8 +225,7 @@ inline Heap* _inline_get_heap_();
V(closure_symbol, "(closure)") \ V(closure_symbol, "(closure)") \
V(use_strict, "use strict") \ V(use_strict, "use strict") \
V(dot_symbol, ".") \ V(dot_symbol, ".") \
V(anonymous_function_symbol, "(anonymous function)") \ V(anonymous_function_symbol, "(anonymous function)")
V(block_scope_symbol, ".block")
// Forward declarations. // Forward declarations.
class GCTracer; class GCTracer;
......
...@@ -1559,9 +1559,6 @@ Block* Parser::ParseScopedBlock(ZoneStringList* labels, bool* ok) { ...@@ -1559,9 +1559,6 @@ Block* Parser::ParseScopedBlock(ZoneStringList* labels, bool* ok) {
Scope* block_scope = NewScope(top_scope_, Scope* block_scope = NewScope(top_scope_,
Scope::BLOCK_SCOPE, Scope::BLOCK_SCOPE,
inside_with()); inside_with());
body->set_block_scope(block_scope);
block_scope->DeclareLocal(isolate()->factory()->block_scope_symbol(),
Variable::VAR);
if (top_scope_->is_strict_mode()) { if (top_scope_->is_strict_mode()) {
block_scope->EnableStrictMode(); block_scope->EnableStrictMode();
} }
...@@ -1584,7 +1581,12 @@ Block* Parser::ParseScopedBlock(ZoneStringList* labels, bool* ok) { ...@@ -1584,7 +1581,12 @@ Block* Parser::ParseScopedBlock(ZoneStringList* labels, bool* ok) {
} }
} }
Expect(Token::RBRACE, CHECK_OK); Expect(Token::RBRACE, CHECK_OK);
top_scope_ = saved_scope;
block_scope = block_scope->FinalizeBlockScope();
body->set_block_scope(block_scope);
if (block_scope != NULL) {
// Create exit block. // Create exit block.
Block* exit = new(zone()) Block(isolate(), NULL, 1, false); Block* exit = new(zone()) Block(isolate(), NULL, 1, false);
exit->AddStatement(new(zone()) ExitContextStatement()); exit->AddStatement(new(zone()) ExitContextStatement());
...@@ -1593,12 +1595,14 @@ Block* Parser::ParseScopedBlock(ZoneStringList* labels, bool* ok) { ...@@ -1593,12 +1595,14 @@ Block* Parser::ParseScopedBlock(ZoneStringList* labels, bool* ok) {
TryFinallyStatement* try_finally = TryFinallyStatement* try_finally =
new(zone()) TryFinallyStatement(body, exit); new(zone()) TryFinallyStatement(body, exit);
try_finally->set_escaping_targets(collector.targets()); try_finally->set_escaping_targets(collector.targets());
top_scope_ = saved_scope;
// Create a result block. // Create a result block.
Block* result = new(zone()) Block(isolate(), NULL, 1, false); Block* result = new(zone()) Block(isolate(), NULL, 1, false);
result->AddStatement(try_finally); result->AddStatement(try_finally);
return result; return result;
} else {
return body;
}
} }
......
...@@ -331,6 +331,35 @@ void Scope::Initialize(bool inside_with) { ...@@ -331,6 +331,35 @@ void Scope::Initialize(bool inside_with) {
} }
Scope* Scope::FinalizeBlockScope() {
ASSERT(is_block_scope());
ASSERT(temps_.is_empty());
ASSERT(params_.is_empty());
if (num_var_or_const() > 0) return this;
// Remove this scope from outer scope.
for (int i = 0; i < outer_scope_->inner_scopes_.length(); i++) {
if (outer_scope_->inner_scopes_[i] == this) {
outer_scope_->inner_scopes_.Remove(i);
break;
}
}
// Reparent inner scopes.
for (int i = 0; i < inner_scopes_.length(); i++) {
outer_scope()->AddInnerScope(inner_scopes_[i]);
}
// Move unresolved variables
for (int i = 0; i < unresolved_.length(); i++) {
outer_scope()->unresolved_.Add(unresolved_[i]);
}
return NULL;
}
Variable* Scope::LocalLookup(Handle<String> name) { Variable* Scope::LocalLookup(Handle<String> name) {
Variable* result = variables_.Lookup(name); Variable* result = variables_.Lookup(name);
if (result != NULL || scope_info_.is_null()) { if (result != NULL || scope_info_.is_null()) {
......
...@@ -112,6 +112,11 @@ class Scope: public ZoneObject { ...@@ -112,6 +112,11 @@ class Scope: public ZoneObject {
void Initialize(bool inside_with); void Initialize(bool inside_with);
// Checks if the block scope is redundant, i.e. it does not contain any
// block scoped declarations. In that case it is removed from the scope
// tree and its children are reparented.
Scope* FinalizeBlockScope();
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Declarations // Declarations
......
...@@ -202,17 +202,15 @@ function local_block_1() { ...@@ -202,17 +202,15 @@ function local_block_1() {
} }
listener_delegate = function(exec_state) { listener_delegate = function(exec_state) {
CheckScopeChain([debug.ScopeType.Block, CheckScopeChain([debug.ScopeType.Local,
debug.ScopeType.Local,
debug.ScopeType.Global], exec_state); debug.ScopeType.Global], exec_state);
CheckScopeContent({}, 0, exec_state); CheckScopeContent({}, 0, exec_state);
CheckScopeContent({}, 1, exec_state);
}; };
local_block_1(); local_block_1();
EndTest(); EndTest();
// Local scope with a parameter. // Simple empty block scope in local scope with a parameter.
BeginTest("Local 2"); BeginTest("Local 2");
function local_2(a) { function local_2(a) {
...@@ -222,10 +220,9 @@ function local_2(a) { ...@@ -222,10 +220,9 @@ function local_2(a) {
} }
listener_delegate = function(exec_state) { listener_delegate = function(exec_state) {
CheckScopeChain([debug.ScopeType.Block, CheckScopeChain([debug.ScopeType.Local,
debug.ScopeType.Local,
debug.ScopeType.Global], exec_state); debug.ScopeType.Global], exec_state);
CheckScopeContent({a:1}, 1, exec_state); CheckScopeContent({a:1}, 0, exec_state);
}; };
local_2(1); local_2(1);
EndTest(); EndTest();
...@@ -266,6 +263,72 @@ local_4(1, 2); ...@@ -266,6 +263,72 @@ local_4(1, 2);
EndTest(); EndTest();
// Single variable in a block scope.
BeginTest("Local 5");
function local_5(a) {
{
let x = 5;
debugger;
}
}
listener_delegate = function(exec_state) {
CheckScopeChain([debug.ScopeType.Block,
debug.ScopeType.Local,
debug.ScopeType.Global], exec_state);
CheckScopeContent({x:5}, 0, exec_state);
CheckScopeContent({a:1}, 1, exec_state);
};
local_5(1);
EndTest();
// Two variables in a block scope.
BeginTest("Local 6");
function local_6(a) {
{
let x = 6;
let y = 7;
debugger;
}
}
listener_delegate = function(exec_state) {
CheckScopeChain([debug.ScopeType.Block,
debug.ScopeType.Local,
debug.ScopeType.Global], exec_state);
CheckScopeContent({x:6,y:7}, 0, exec_state);
CheckScopeContent({a:1}, 1, exec_state);
};
local_6(1);
EndTest();
// Two variables in a block scope.
BeginTest("Local 7");
function local_7(a) {
{
{
let x = 8;
debugger;
}
}
}
listener_delegate = function(exec_state) {
CheckScopeChain([debug.ScopeType.Block,
debug.ScopeType.Local,
debug.ScopeType.Global], exec_state);
CheckScopeContent({x:8}, 0, exec_state);
CheckScopeContent({a:1}, 1, exec_state);
};
local_7(1);
EndTest();
// Single empty with block. // Single empty with block.
BeginTest("With block 1"); BeginTest("With block 1");
...@@ -276,8 +339,7 @@ function with_block_1() { ...@@ -276,8 +339,7 @@ function with_block_1() {
} }
listener_delegate = function(exec_state) { listener_delegate = function(exec_state) {
CheckScopeChain([debug.ScopeType.Block, CheckScopeChain([debug.ScopeType.With,
debug.ScopeType.With,
debug.ScopeType.Local, debug.ScopeType.Local,
debug.ScopeType.Global], exec_state); debug.ScopeType.Global], exec_state);
CheckScopeContent({}, 0, exec_state); CheckScopeContent({}, 0, exec_state);
...@@ -299,16 +361,13 @@ function with_block_2() { ...@@ -299,16 +361,13 @@ function with_block_2() {
} }
listener_delegate = function(exec_state) { listener_delegate = function(exec_state) {
CheckScopeChain([debug.ScopeType.Block, CheckScopeChain([debug.ScopeType.With,
debug.ScopeType.With,
debug.ScopeType.Block,
debug.ScopeType.With, debug.ScopeType.With,
debug.ScopeType.Local, debug.ScopeType.Local,
debug.ScopeType.Global], exec_state); debug.ScopeType.Global], exec_state);
CheckScopeContent({}, 0, exec_state); CheckScopeContent({}, 0, exec_state);
CheckScopeContent({}, 1, exec_state); CheckScopeContent({}, 1, exec_state);
CheckScopeContent({}, 2, exec_state); CheckScopeContent({}, 2, exec_state);
CheckScopeContent({}, 3, exec_state);
}; };
with_block_2(); with_block_2();
EndTest(); EndTest();
...@@ -324,12 +383,10 @@ function with_block_3() { ...@@ -324,12 +383,10 @@ function with_block_3() {
} }
listener_delegate = function(exec_state) { listener_delegate = function(exec_state) {
CheckScopeChain([debug.ScopeType.Block, CheckScopeChain([debug.ScopeType.With,
debug.ScopeType.With,
debug.ScopeType.Local, debug.ScopeType.Local,
debug.ScopeType.Global], exec_state); debug.ScopeType.Global], exec_state);
CheckScopeContent({}, 0, exec_state); CheckScopeContent({a:1,b:2}, 0, exec_state);
CheckScopeContent({a:1,b:2}, 1, exec_state);
}; };
with_block_3(); with_block_3();
EndTest(); EndTest();
...@@ -347,14 +404,12 @@ function with_block_4() { ...@@ -347,14 +404,12 @@ function with_block_4() {
} }
listener_delegate = function(exec_state) { listener_delegate = function(exec_state) {
CheckScopeChain([debug.ScopeType.Block, CheckScopeChain([debug.ScopeType.With,
debug.ScopeType.With,
debug.ScopeType.Block,
debug.ScopeType.With, debug.ScopeType.With,
debug.ScopeType.Local, debug.ScopeType.Local,
debug.ScopeType.Global], exec_state); debug.ScopeType.Global], exec_state);
CheckScopeContent({a:2,b:1}, 1, exec_state); CheckScopeContent({a:2,b:1}, 0, exec_state);
CheckScopeContent({a:1,b:2}, 3, exec_state); CheckScopeContent({a:1,b:2}, 1, exec_state);
}; };
with_block_4(); with_block_4();
EndTest(); EndTest();
......
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