diff -r 050939c6181e -r 2b6904506469 jitcraft/Parser.cpp --- a/jitcraft/Parser.cpp Wed Jul 04 19:39:00 2012 -0400 +++ b/jitcraft/Parser.cpp Wed Jul 04 19:54:53 2012 -0400 @@ -1,4 +1,5 @@ -/* +/* vim: set ts=4 sw=4 tw=99 et: + * * Copyright (C) 2012 David Anderson * * This file is part of JITCraft. @@ -440,10 +441,23 @@ if (!expect(TOK_RPAREN)) return NULL; - Statement *body = localStatement(); + // Inside a loop, we force the creation of a scope object. Normally, we + // will cull scopes if they have no variables. However inside a loop, + // function calls that take references may compute a LIFO object, and to + // avoid temporarily leaking many such objects, we ensure that a scope + // is present so a LIFO slot can be allocated. + if (!enterScope(Scope::BLOCK)) + return NULL; + + Statement *body; + if (scanner_.peek() == TOK_LBRACE) + body = block(scope_); + else + body = localStatement(); if (!body) return NULL; + scope_ = scope_->enclosing(); return new (pool_) WhileStatement(pos, TOK_WHILE, condition, body); } @@ -453,10 +467,20 @@ SourcePosition pos = scanner_.begin(); scanner_.scan(); - Statement *body = block(); + // See the comment in ::while_() as to why we force a scope. + if (!enterScope(Scope::BLOCK)) + return NULL; + + Statement *body; + if (scanner_.peek() == TOK_LBRACE) + body = block(scope_); + else + body = localStatement(); if (!body) return NULL; + scope_ = scope_->enclosing(); + if (!expect(TOK_WHILE)) return NULL; @@ -510,16 +534,26 @@ return NULL; } - Statement *body = localStatement(); + // See the comment in ::while_() as to why we force a scope. + if (!enterScope(Scope::BLOCK)) + return NULL; + + Statement *body; + if (scanner_.peek() == TOK_LBRACE) + body = block(scope_); + else + body = localStatement(); if (!body) return NULL; - Scope *blockScope = NULL; + scope_ = scope_->enclosing(); + + Scope *declScope = NULL; if (decl && decl->isVariableDeclaration()) { - blockScope = scope_->unlinkIfEmpty(); + declScope = scope_->unlinkIfEmpty(); scope_ = scope_->enclosing(); } - return new (pool_) ForStatement(pos, blockScope, decl, condition, update, body); + return new (pool_) ForStatement(pos, declScope, decl, condition, update, body); } VariableDeclaration * @@ -594,13 +628,13 @@ } Statement * -Parser::block() +Parser::block(Scope *scope) { if (!expect(TOK_LBRACE)) return NULL; SourcePosition pos = scanner_.begin(); - if (!enterScope(Scope::BLOCK)) + if (!scope && !enterScope(Scope::BLOCK)) return NULL; StatementList *statements = new (pool_) StatementList(); @@ -611,10 +645,11 @@ statements->append(pool_, statement); } - Scope *blockScope = scope_->unlinkIfEmpty(); - BlockStatement *block = new (pool_) BlockStatement(pos, blockScope, statements); - - scope_ = scope_->enclosing(); + if (!scope) { + scope = scope_->unlinkIfEmpty(); + scope_ = scope_->enclosing(); + } + BlockStatement *block = new (pool_) BlockStatement(pos, scope, statements); return block; }