Home | History | Annotate | Download | only in src
      1 // Copyright 2011 the V8 project authors. All rights reserved.
      2 // Redistribution and use in source and binary forms, with or without
      3 // modification, are permitted provided that the following conditions are
      4 // met:
      5 //
      6 //     * Redistributions of source code must retain the above copyright
      7 //       notice, this list of conditions and the following disclaimer.
      8 //     * Redistributions in binary form must reproduce the above
      9 //       copyright notice, this list of conditions and the following
     10 //       disclaimer in the documentation and/or other materials provided
     11 //       with the distribution.
     12 //     * Neither the name of Google Inc. nor the names of its
     13 //       contributors may be used to endorse or promote products derived
     14 //       from this software without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 
     28 #include "v8.h"
     29 
     30 #include "rewriter.h"
     31 
     32 #include "ast.h"
     33 #include "compiler.h"
     34 #include "scopes.h"
     35 
     36 namespace v8 {
     37 namespace internal {
     38 
     39 class Processor: public AstVisitor {
     40  public:
     41   explicit Processor(Variable* result)
     42       : result_(result),
     43         result_assigned_(false),
     44         is_set_(false),
     45         in_try_(false) {
     46   }
     47 
     48   void Process(ZoneList<Statement*>* statements);
     49   bool result_assigned() const { return result_assigned_; }
     50 
     51  private:
     52   Variable* result_;
     53 
     54   // We are not tracking result usage via the result_'s use
     55   // counts (we leave the accurate computation to the
     56   // usage analyzer). Instead we simple remember if
     57   // there was ever an assignment to result_.
     58   bool result_assigned_;
     59 
     60   // To avoid storing to .result all the time, we eliminate some of
     61   // the stores by keeping track of whether or not we're sure .result
     62   // will be overwritten anyway. This is a bit more tricky than what I
     63   // was hoping for
     64   bool is_set_;
     65   bool in_try_;
     66 
     67   Expression* SetResult(Expression* value) {
     68     result_assigned_ = true;
     69     VariableProxy* result_proxy = new VariableProxy(result_);
     70     return new Assignment(Token::ASSIGN, result_proxy, value,
     71                           RelocInfo::kNoPosition);
     72   }
     73 
     74   // Node visitors.
     75 #define DEF_VISIT(type) \
     76   virtual void Visit##type(type* node);
     77   AST_NODE_LIST(DEF_VISIT)
     78 #undef DEF_VISIT
     79 
     80   void VisitIterationStatement(IterationStatement* stmt);
     81 };
     82 
     83 
     84 void Processor::Process(ZoneList<Statement*>* statements) {
     85   for (int i = statements->length() - 1; i >= 0; --i) {
     86     Visit(statements->at(i));
     87   }
     88 }
     89 
     90 
     91 void Processor::VisitBlock(Block* node) {
     92   // An initializer block is the rewritten form of a variable declaration
     93   // with initialization expressions. The initializer block contains the
     94   // list of assignments corresponding to the initialization expressions.
     95   // While unclear from the spec (ECMA-262, 3rd., 12.2), the value of
     96   // a variable declaration with initialization expression is 'undefined'
     97   // with some JS VMs: For instance, using smjs, print(eval('var x = 7'))
     98   // returns 'undefined'. To obtain the same behavior with v8, we need
     99   // to prevent rewriting in that case.
    100   if (!node->is_initializer_block()) Process(node->statements());
    101 }
    102 
    103 
    104 void Processor::VisitExpressionStatement(ExpressionStatement* node) {
    105   // Rewrite : <x>; -> .result = <x>;
    106   if (!is_set_) {
    107     node->set_expression(SetResult(node->expression()));
    108     if (!in_try_) is_set_ = true;
    109   }
    110 }
    111 
    112 
    113 void Processor::VisitIfStatement(IfStatement* node) {
    114   // Rewrite both then and else parts (reversed).
    115   bool save = is_set_;
    116   Visit(node->else_statement());
    117   bool set_after_then = is_set_;
    118   is_set_ = save;
    119   Visit(node->then_statement());
    120   is_set_ = is_set_ && set_after_then;
    121 }
    122 
    123 
    124 void Processor::VisitIterationStatement(IterationStatement* node) {
    125   // Rewrite the body.
    126   bool set_after_loop = is_set_;
    127   Visit(node->body());
    128   is_set_ = is_set_ && set_after_loop;
    129 }
    130 
    131 
    132 void Processor::VisitDoWhileStatement(DoWhileStatement* node) {
    133   VisitIterationStatement(node);
    134 }
    135 
    136 
    137 void Processor::VisitWhileStatement(WhileStatement* node) {
    138   VisitIterationStatement(node);
    139 }
    140 
    141 
    142 void Processor::VisitForStatement(ForStatement* node) {
    143   VisitIterationStatement(node);
    144 }
    145 
    146 
    147 void Processor::VisitForInStatement(ForInStatement* node) {
    148   VisitIterationStatement(node);
    149 }
    150 
    151 
    152 void Processor::VisitTryCatchStatement(TryCatchStatement* node) {
    153   // Rewrite both try and catch blocks (reversed order).
    154   bool set_after_catch = is_set_;
    155   Visit(node->catch_block());
    156   is_set_ = is_set_ && set_after_catch;
    157   bool save = in_try_;
    158   in_try_ = true;
    159   Visit(node->try_block());
    160   in_try_ = save;
    161 }
    162 
    163 
    164 void Processor::VisitTryFinallyStatement(TryFinallyStatement* node) {
    165   // Rewrite both try and finally block (reversed order).
    166   Visit(node->finally_block());
    167   bool save = in_try_;
    168   in_try_ = true;
    169   Visit(node->try_block());
    170   in_try_ = save;
    171 }
    172 
    173 
    174 void Processor::VisitSwitchStatement(SwitchStatement* node) {
    175   // Rewrite statements in all case clauses in reversed order.
    176   ZoneList<CaseClause*>* clauses = node->cases();
    177   bool set_after_switch = is_set_;
    178   for (int i = clauses->length() - 1; i >= 0; --i) {
    179     CaseClause* clause = clauses->at(i);
    180     Process(clause->statements());
    181   }
    182   is_set_ = is_set_ && set_after_switch;
    183 }
    184 
    185 
    186 void Processor::VisitContinueStatement(ContinueStatement* node) {
    187   is_set_ = false;
    188 }
    189 
    190 
    191 void Processor::VisitBreakStatement(BreakStatement* node) {
    192   is_set_ = false;
    193 }
    194 
    195 
    196 // Do nothing:
    197 void Processor::VisitDeclaration(Declaration* node) {}
    198 void Processor::VisitEmptyStatement(EmptyStatement* node) {}
    199 void Processor::VisitReturnStatement(ReturnStatement* node) {}
    200 void Processor::VisitWithEnterStatement(WithEnterStatement* node) {}
    201 void Processor::VisitWithExitStatement(WithExitStatement* node) {}
    202 void Processor::VisitDebuggerStatement(DebuggerStatement* node) {}
    203 
    204 
    205 // Expressions are never visited yet.
    206 void Processor::VisitFunctionLiteral(FunctionLiteral* node) {
    207   USE(node);
    208   UNREACHABLE();
    209 }
    210 
    211 
    212 void Processor::VisitSharedFunctionInfoLiteral(
    213     SharedFunctionInfoLiteral* node) {
    214   USE(node);
    215   UNREACHABLE();
    216 }
    217 
    218 
    219 void Processor::VisitConditional(Conditional* node) {
    220   USE(node);
    221   UNREACHABLE();
    222 }
    223 
    224 
    225 void Processor::VisitVariableProxy(VariableProxy* node) {
    226   USE(node);
    227   UNREACHABLE();
    228 }
    229 
    230 
    231 void Processor::VisitLiteral(Literal* node) {
    232   USE(node);
    233   UNREACHABLE();
    234 }
    235 
    236 
    237 void Processor::VisitRegExpLiteral(RegExpLiteral* node) {
    238   USE(node);
    239   UNREACHABLE();
    240 }
    241 
    242 
    243 void Processor::VisitArrayLiteral(ArrayLiteral* node) {
    244   USE(node);
    245   UNREACHABLE();
    246 }
    247 
    248 
    249 void Processor::VisitObjectLiteral(ObjectLiteral* node) {
    250   USE(node);
    251   UNREACHABLE();
    252 }
    253 
    254 
    255 void Processor::VisitCatchExtensionObject(CatchExtensionObject* node) {
    256   USE(node);
    257   UNREACHABLE();
    258 }
    259 
    260 
    261 void Processor::VisitAssignment(Assignment* node) {
    262   USE(node);
    263   UNREACHABLE();
    264 }
    265 
    266 
    267 void Processor::VisitThrow(Throw* node) {
    268   USE(node);
    269   UNREACHABLE();
    270 }
    271 
    272 
    273 void Processor::VisitProperty(Property* node) {
    274   USE(node);
    275   UNREACHABLE();
    276 }
    277 
    278 
    279 void Processor::VisitCall(Call* node) {
    280   USE(node);
    281   UNREACHABLE();
    282 }
    283 
    284 
    285 void Processor::VisitCallNew(CallNew* node) {
    286   USE(node);
    287   UNREACHABLE();
    288 }
    289 
    290 
    291 void Processor::VisitCallRuntime(CallRuntime* node) {
    292   USE(node);
    293   UNREACHABLE();
    294 }
    295 
    296 
    297 void Processor::VisitUnaryOperation(UnaryOperation* node) {
    298   USE(node);
    299   UNREACHABLE();
    300 }
    301 
    302 
    303 void Processor::VisitCountOperation(CountOperation* node) {
    304   USE(node);
    305   UNREACHABLE();
    306 }
    307 
    308 
    309 void Processor::VisitBinaryOperation(BinaryOperation* node) {
    310   USE(node);
    311   UNREACHABLE();
    312 }
    313 
    314 
    315 void Processor::VisitCompareOperation(CompareOperation* node) {
    316   USE(node);
    317   UNREACHABLE();
    318 }
    319 
    320 
    321 void Processor::VisitCompareToNull(CompareToNull* node) {
    322   USE(node);
    323   UNREACHABLE();
    324 }
    325 
    326 
    327 void Processor::VisitThisFunction(ThisFunction* node) {
    328   USE(node);
    329   UNREACHABLE();
    330 }
    331 
    332 
    333 // Assumes code has been parsed and scopes have been analyzed.  Mutates the
    334 // AST, so the AST should not continue to be used in the case of failure.
    335 bool Rewriter::Rewrite(CompilationInfo* info) {
    336   FunctionLiteral* function = info->function();
    337   ASSERT(function != NULL);
    338   Scope* scope = function->scope();
    339   ASSERT(scope != NULL);
    340   if (scope->is_function_scope()) return true;
    341 
    342   ZoneList<Statement*>* body = function->body();
    343   if (!body->is_empty()) {
    344     Variable* result = scope->NewTemporary(
    345         info->isolate()->factory()->result_symbol());
    346     Processor processor(result);
    347     processor.Process(body);
    348     if (processor.HasStackOverflow()) return false;
    349 
    350     if (processor.result_assigned()) {
    351       VariableProxy* result_proxy = new VariableProxy(result);
    352       body->Add(new ReturnStatement(result_proxy));
    353     }
    354   }
    355 
    356   return true;
    357 }
    358 
    359 
    360 } }  // namespace v8::internal
    361