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