Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1757)

Unified Diff: src/parsing/rewriter.cc

Issue 2431273002: Only rewrite all statements in a block if we're in a breakable scope (Closed)
Patch Set: comment Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/parsing/rewriter.cc
diff --git a/src/parsing/rewriter.cc b/src/parsing/rewriter.cc
index 57009bd20707af3260e2e6e367d72eef374dffb6..19e9e4cd80d05d9cc07138f6c61e91d16a06c8d3 100644
--- a/src/parsing/rewriter.cc
+++ b/src/parsing/rewriter.cc
@@ -20,6 +20,7 @@ class Processor final : public AstVisitor<Processor> {
result_assigned_(false),
replacement_(nullptr),
is_set_(false),
+ breakable_(false),
zone_(ast_value_factory->zone()),
closure_scope_(closure_scope),
factory_(ast_value_factory) {
@@ -33,6 +34,7 @@ class Processor final : public AstVisitor<Processor> {
result_assigned_(false),
replacement_(nullptr),
is_set_(false),
+ breakable_(false),
zone_(ast_value_factory->zone()),
closure_scope_(closure_scope),
factory_(ast_value_factory) {
@@ -77,6 +79,22 @@ class Processor final : public AstVisitor<Processor> {
// was hoping for.
bool is_set_;
+ bool breakable_;
+
+ class BreakableScope final {
+ public:
+ explicit BreakableScope(Processor* processor, bool breakable = true)
+ : processor_(processor), previous_(processor->breakable_) {
+ processor->breakable_ = processor->breakable_ || breakable;
+ }
+
+ ~BreakableScope() { processor_->breakable_ = previous_; }
+
+ private:
+ Processor* processor_;
+ bool previous_;
+ };
+
Zone* zone_;
DeclarationScope* closure_scope_;
AstNodeFactory factory_;
@@ -106,7 +124,13 @@ Statement* Processor::AssignUndefinedBefore(Statement* s) {
void Processor::Process(ZoneList<Statement*>* statements) {
- for (int i = statements->length() - 1; i >= 0; --i) {
+ // If we're in a breakable scope (named block, iteration, or switch), we walk
+ // all statements. The last value producing statement before the break needs
+ // to assign to .result. If we're not in a breakable scope, only the last
+ // value producing statement in the block assigns to .result, so we can stop
+ // early.
+ for (int i = statements->length() - 1; i >= 0 && (breakable_ || !is_set_);
+ --i) {
Visit(statements->at(i));
statements->Set(i, replacement_);
}
@@ -122,7 +146,10 @@ void Processor::VisitBlock(Block* node) {
// with some JS VMs: For instance, using smjs, print(eval('var x = 7'))
// returns 'undefined'. To obtain the same behavior with v8, we need
// to prevent rewriting in that case.
- if (!node->ignore_completion_value()) Process(node->statements());
+ if (!node->ignore_completion_value()) {
+ BreakableScope scope(this, node->labels() != nullptr);
+ Process(node->statements());
+ }
replacement_ = node;
}
@@ -157,6 +184,7 @@ void Processor::VisitIfStatement(IfStatement* node) {
void Processor::VisitIterationStatement(IterationStatement* node) {
+ BreakableScope scope(this);
// Rewrite the body.
bool set_after = is_set_;
is_set_ = false; // We are in a loop, so we can't rely on [set_after].
@@ -253,6 +281,7 @@ void Processor::VisitTryFinallyStatement(TryFinallyStatement* node) {
void Processor::VisitSwitchStatement(SwitchStatement* node) {
+ BreakableScope scope(this);
// Rewrite statements in all case clauses (in reverse order).
ZoneList<CaseClause*>* clauses = node->cases();
bool set_after = is_set_;
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698