Revision: 9117
Author: [email protected]
Date: Fri Sep 2 05:43:28 2011
Log: Prune empty block scopes from scope tree
BUG=
TEST=
Review URL: http://codereview.chromium.org/7825006
http://code.google.com/p/v8/source/detail?r=9117
Modified:
/branches/bleeding_edge/src/heap.h
/branches/bleeding_edge/src/parser.cc
/branches/bleeding_edge/src/scopes.cc
/branches/bleeding_edge/src/scopes.h
/branches/bleeding_edge/test/mjsunit/harmony/debug-blockscopes.js
=======================================
--- /branches/bleeding_edge/src/heap.h Fri Aug 26 06:03:30 2011
+++ /branches/bleeding_edge/src/heap.h Fri Sep 2 05:43:28 2011
@@ -225,8 +225,7 @@
V(closure_symbol, "(closure)") \
V(use_strict, "use strict") \
V(dot_symbol, ".") \
- V(anonymous_function_symbol, "(anonymous function)") \
- V(block_scope_symbol, ".block")
+ V(anonymous_function_symbol, "(anonymous function)")
// Forward declarations.
class GCTracer;
=======================================
--- /branches/bleeding_edge/src/parser.cc Thu Sep 1 05:31:18 2011
+++ /branches/bleeding_edge/src/parser.cc Fri Sep 2 05:43:28 2011
@@ -1559,9 +1559,6 @@
Scope* block_scope = NewScope(top_scope_,
Scope::BLOCK_SCOPE,
inside_with());
- body->set_block_scope(block_scope);
- block_scope->DeclareLocal(isolate()->factory()->block_scope_symbol(),
- Variable::VAR);
if (top_scope_->is_strict_mode()) {
block_scope->EnableStrictMode();
}
@@ -1584,21 +1581,28 @@
}
}
Expect(Token::RBRACE, CHECK_OK);
-
- // Create exit block.
- Block* exit = new(zone()) Block(isolate(), NULL, 1, false);
- exit->AddStatement(new(zone()) ExitContextStatement());
-
- // Create a try-finally statement.
- TryFinallyStatement* try_finally =
- new(zone()) TryFinallyStatement(body, exit);
- try_finally->set_escaping_targets(collector.targets());
- top_scope_ = saved_scope;
-
- // Create a result block.
- Block* result = new(zone()) Block(isolate(), NULL, 1, false);
- result->AddStatement(try_finally);
- return result;
+ top_scope_ = saved_scope;
+
+ block_scope = block_scope->FinalizeBlockScope();
+ body->set_block_scope(block_scope);
+
+ if (block_scope != NULL) {
+ // Create exit block.
+ Block* exit = new(zone()) Block(isolate(), NULL, 1, false);
+ exit->AddStatement(new(zone()) ExitContextStatement());
+
+ // Create a try-finally statement.
+ TryFinallyStatement* try_finally =
+ new(zone()) TryFinallyStatement(body, exit);
+ try_finally->set_escaping_targets(collector.targets());
+
+ // Create a result block.
+ Block* result = new(zone()) Block(isolate(), NULL, 1, false);
+ result->AddStatement(try_finally);
+ return result;
+ } else {
+ return body;
+ }
}
=======================================
--- /branches/bleeding_edge/src/scopes.cc Thu Sep 1 09:33:57 2011
+++ /branches/bleeding_edge/src/scopes.cc Fri Sep 2 05:43:28 2011
@@ -329,6 +329,35 @@
Variable::ARGUMENTS);
}
}
+
+
+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) {
=======================================
--- /branches/bleeding_edge/src/scopes.h Thu Sep 1 09:33:57 2011
+++ /branches/bleeding_edge/src/scopes.h Fri Sep 2 05:43:28 2011
@@ -112,6 +112,11 @@
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
=======================================
--- /branches/bleeding_edge/test/mjsunit/harmony/debug-blockscopes.js Tue
Aug 16 07:24:12 2011
+++ /branches/bleeding_edge/test/mjsunit/harmony/debug-blockscopes.js Fri
Sep 2 05:43:28 2011
@@ -202,17 +202,15 @@
}
listener_delegate = function(exec_state) {
- CheckScopeChain([debug.ScopeType.Block,
- debug.ScopeType.Local,
+ CheckScopeChain([debug.ScopeType.Local,
debug.ScopeType.Global], exec_state);
CheckScopeContent({}, 0, exec_state);
- CheckScopeContent({}, 1, exec_state);
};
local_block_1();
EndTest();
-// Local scope with a parameter.
+// Simple empty block scope in local scope with a parameter.
BeginTest("Local 2");
function local_2(a) {
@@ -222,10 +220,9 @@
}
listener_delegate = function(exec_state) {
- CheckScopeChain([debug.ScopeType.Block,
- debug.ScopeType.Local,
+ CheckScopeChain([debug.ScopeType.Local,
debug.ScopeType.Global], exec_state);
- CheckScopeContent({a:1}, 1, exec_state);
+ CheckScopeContent({a:1}, 0, exec_state);
};
local_2(1);
EndTest();
@@ -266,6 +263,72 @@
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.
BeginTest("With block 1");
@@ -276,8 +339,7 @@
}
listener_delegate = function(exec_state) {
- CheckScopeChain([debug.ScopeType.Block,
- debug.ScopeType.With,
+ CheckScopeChain([debug.ScopeType.With,
debug.ScopeType.Local,
debug.ScopeType.Global], exec_state);
CheckScopeContent({}, 0, exec_state);
@@ -299,16 +361,13 @@
}
listener_delegate = function(exec_state) {
- CheckScopeChain([debug.ScopeType.Block,
- debug.ScopeType.With,
- debug.ScopeType.Block,
+ CheckScopeChain([debug.ScopeType.With,
debug.ScopeType.With,
debug.ScopeType.Local,
debug.ScopeType.Global], exec_state);
CheckScopeContent({}, 0, exec_state);
CheckScopeContent({}, 1, exec_state);
CheckScopeContent({}, 2, exec_state);
- CheckScopeContent({}, 3, exec_state);
};
with_block_2();
EndTest();
@@ -324,12 +383,10 @@
}
listener_delegate = function(exec_state) {
- CheckScopeChain([debug.ScopeType.Block,
- debug.ScopeType.With,
+ CheckScopeChain([debug.ScopeType.With,
debug.ScopeType.Local,
debug.ScopeType.Global], exec_state);
- CheckScopeContent({}, 0, exec_state);
- CheckScopeContent({a:1,b:2}, 1, exec_state);
+ CheckScopeContent({a:1,b:2}, 0, exec_state);
};
with_block_3();
EndTest();
@@ -347,14 +404,12 @@
}
listener_delegate = function(exec_state) {
- CheckScopeChain([debug.ScopeType.Block,
- debug.ScopeType.With,
- debug.ScopeType.Block,
+ CheckScopeChain([debug.ScopeType.With,
debug.ScopeType.With,
debug.ScopeType.Local,
debug.ScopeType.Global], exec_state);
- CheckScopeContent({a:2,b:1}, 1, exec_state);
- CheckScopeContent({a:1,b:2}, 3, exec_state);
+ CheckScopeContent({a:2,b:1}, 0, exec_state);
+ CheckScopeContent({a:1,b:2}, 1, exec_state);
};
with_block_4();
EndTest();
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev