Fix a bug where we might not unwind the lifo stack in empty scopes.
authorDavid Anderson <dvander@alliedmods.net>
Wed Jul 04 19:54:53 2012 -0400 (2012-07-04)
changeset 482b6904506469
parent 47 050939c6181e
child 49 a92afa7484fd
Fix a bug where we might not unwind the lifo stack in empty scopes.
jitcraft/Parser.cpp
jitcraft/Parser.h
     1.1 --- a/jitcraft/Parser.cpp	Wed Jul 04 19:39:00 2012 -0400
     1.2 +++ b/jitcraft/Parser.cpp	Wed Jul 04 19:54:53 2012 -0400
     1.3 @@ -1,4 +1,5 @@
     1.4 -/*
     1.5 +/* vim: set ts=4 sw=4 tw=99 et:
     1.6 + *
     1.7   * Copyright (C) 2012 David Anderson
     1.8   *
     1.9   * This file is part of JITCraft.
    1.10 @@ -440,10 +441,23 @@
    1.11      if (!expect(TOK_RPAREN))
    1.12          return NULL;
    1.13  
    1.14 -    Statement *body = localStatement();
    1.15 +    // Inside a loop, we force the creation of a scope object. Normally, we
    1.16 +    // will cull scopes if they have no variables. However inside a loop,
    1.17 +    // function calls that take references may compute a LIFO object, and to
    1.18 +    // avoid temporarily leaking many such objects, we ensure that a scope
    1.19 +    // is present so a LIFO slot can be allocated.
    1.20 +    if (!enterScope(Scope::BLOCK))
    1.21 +        return NULL;
    1.22 +
    1.23 +    Statement *body;
    1.24 +    if (scanner_.peek() == TOK_LBRACE)
    1.25 +        body = block(scope_);
    1.26 +    else
    1.27 +        body = localStatement();
    1.28      if (!body)
    1.29          return NULL;
    1.30  
    1.31 +    scope_ = scope_->enclosing();
    1.32      return new (pool_) WhileStatement(pos, TOK_WHILE, condition, body);
    1.33  }
    1.34  
    1.35 @@ -453,10 +467,20 @@
    1.36      SourcePosition pos = scanner_.begin();
    1.37      scanner_.scan();
    1.38  
    1.39 -    Statement *body = block();
    1.40 +    // See the comment in ::while_() as to why we force a scope.
    1.41 +    if (!enterScope(Scope::BLOCK))
    1.42 +        return NULL;
    1.43 +
    1.44 +    Statement *body;
    1.45 +    if (scanner_.peek() == TOK_LBRACE)
    1.46 +        body = block(scope_);
    1.47 +    else
    1.48 +        body = localStatement();
    1.49      if (!body)
    1.50          return NULL;
    1.51  
    1.52 +    scope_ = scope_->enclosing();
    1.53 +
    1.54      if (!expect(TOK_WHILE))
    1.55          return NULL;
    1.56  
    1.57 @@ -510,16 +534,26 @@
    1.58              return NULL;
    1.59      }
    1.60  
    1.61 -    Statement *body = localStatement();
    1.62 +    // See the comment in ::while_() as to why we force a scope.
    1.63 +    if (!enterScope(Scope::BLOCK))
    1.64 +        return NULL;
    1.65 +
    1.66 +    Statement *body;
    1.67 +    if (scanner_.peek() == TOK_LBRACE)
    1.68 +        body = block(scope_);
    1.69 +    else
    1.70 +        body = localStatement();
    1.71      if (!body)
    1.72          return NULL;
    1.73  
    1.74 -    Scope *blockScope = NULL;
    1.75 +    scope_ = scope_->enclosing();
    1.76 +
    1.77 +    Scope *declScope = NULL;
    1.78      if (decl && decl->isVariableDeclaration()) {
    1.79 -        blockScope = scope_->unlinkIfEmpty();
    1.80 +        declScope = scope_->unlinkIfEmpty();
    1.81          scope_ = scope_->enclosing();
    1.82      }
    1.83 -    return new (pool_) ForStatement(pos, blockScope, decl, condition, update, body);
    1.84 +    return new (pool_) ForStatement(pos, declScope, decl, condition, update, body);
    1.85  }
    1.86  
    1.87  VariableDeclaration *
    1.88 @@ -594,13 +628,13 @@
    1.89  }
    1.90  
    1.91  Statement *
    1.92 -Parser::block()
    1.93 +Parser::block(Scope *scope)
    1.94  {
    1.95      if (!expect(TOK_LBRACE))
    1.96          return NULL;
    1.97  
    1.98      SourcePosition pos = scanner_.begin();
    1.99 -    if (!enterScope(Scope::BLOCK))
   1.100 +    if (!scope && !enterScope(Scope::BLOCK))
   1.101          return NULL;
   1.102  
   1.103      StatementList *statements = new (pool_) StatementList();
   1.104 @@ -611,10 +645,11 @@
   1.105          statements->append(pool_, statement);
   1.106      }
   1.107  
   1.108 -    Scope *blockScope = scope_->unlinkIfEmpty();
   1.109 -    BlockStatement *block = new (pool_) BlockStatement(pos, blockScope, statements);
   1.110 -
   1.111 -    scope_ = scope_->enclosing();
   1.112 +    if (!scope) {
   1.113 +    	scope = scope_->unlinkIfEmpty();
   1.114 +        scope_ = scope_->enclosing();
   1.115 +    }
   1.116 +    BlockStatement *block = new (pool_) BlockStatement(pos, scope, statements);
   1.117      return block;
   1.118  }
   1.119  
     2.1 --- a/jitcraft/Parser.h	Wed Jul 04 19:39:00 2012 -0400
     2.2 +++ b/jitcraft/Parser.h	Wed Jul 04 19:54:53 2012 -0400
     2.3 @@ -66,7 +66,7 @@
     2.4  
     2.5      Statement *enum_();
     2.6      Statement *if_();
     2.7 -    Statement *block();
     2.8 +    Statement *block(Scope *scope = NULL);
     2.9      Statement *function();
    2.10      Statement *expressionStatement();
    2.11      Statement *while_();