1 // Copyright 2010 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 "data-flow.h" 31 #include "scopes.h" 32 33 namespace v8 { 34 namespace internal { 35 36 #ifdef DEBUG 37 void BitVector::Print() { 38 bool first = true; 39 PrintF("{"); 40 for (int i = 0; i < length(); i++) { 41 if (Contains(i)) { 42 if (!first) PrintF(","); 43 first = false; 44 PrintF("%d", i); 45 } 46 } 47 PrintF("}"); 48 } 49 #endif 50 51 52 void BitVector::Iterator::Advance() { 53 current_++; 54 uint32_t val = current_value_; 55 while (val == 0) { 56 current_index_++; 57 if (Done()) return; 58 val = target_->data_[current_index_]; 59 current_ = current_index_ << 5; 60 } 61 val = SkipZeroBytes(val); 62 val = SkipZeroBits(val); 63 current_value_ = val >> 1; 64 } 65 66 67 bool AssignedVariablesAnalyzer::Analyze(CompilationInfo* info) { 68 Scope* scope = info->scope(); 69 int size = scope->num_parameters() + scope->num_stack_slots(); 70 if (size == 0) return true; 71 AssignedVariablesAnalyzer analyzer(info, size); 72 return analyzer.Analyze(); 73 } 74 75 76 AssignedVariablesAnalyzer::AssignedVariablesAnalyzer(CompilationInfo* info, 77 int size) 78 : info_(info), av_(size) { 79 } 80 81 82 bool AssignedVariablesAnalyzer::Analyze() { 83 ASSERT(av_.length() > 0); 84 VisitStatements(info_->function()->body()); 85 return !HasStackOverflow(); 86 } 87 88 89 Variable* AssignedVariablesAnalyzer::FindSmiLoopVariable(ForStatement* stmt) { 90 // The loop must have all necessary parts. 91 if (stmt->init() == NULL || stmt->cond() == NULL || stmt->next() == NULL) { 92 return NULL; 93 } 94 // The initialization statement has to be a simple assignment. 95 Assignment* init = stmt->init()->StatementAsSimpleAssignment(); 96 if (init == NULL) return NULL; 97 98 // We only deal with local variables. 99 Variable* loop_var = init->target()->AsVariableProxy()->AsVariable(); 100 if (loop_var == NULL || !loop_var->IsStackAllocated()) return NULL; 101 102 // Don't try to get clever with const or dynamic variables. 103 if (loop_var->mode() != Variable::VAR) return NULL; 104 105 // The initial value has to be a smi. 106 Literal* init_lit = init->value()->AsLiteral(); 107 if (init_lit == NULL || !init_lit->handle()->IsSmi()) return NULL; 108 int init_value = Smi::cast(*init_lit->handle())->value(); 109 110 // The condition must be a compare of variable with <, <=, >, or >=. 111 CompareOperation* cond = stmt->cond()->AsCompareOperation(); 112 if (cond == NULL) return NULL; 113 if (cond->op() != Token::LT 114 && cond->op() != Token::LTE 115 && cond->op() != Token::GT 116 && cond->op() != Token::GTE) return NULL; 117 118 // The lhs must be the same variable as in the init expression. 119 if (cond->left()->AsVariableProxy()->AsVariable() != loop_var) return NULL; 120 121 // The rhs must be a smi. 122 Literal* term_lit = cond->right()->AsLiteral(); 123 if (term_lit == NULL || !term_lit->handle()->IsSmi()) return NULL; 124 int term_value = Smi::cast(*term_lit->handle())->value(); 125 126 // The count operation updates the same variable as in the init expression. 127 CountOperation* update = stmt->next()->StatementAsCountOperation(); 128 if (update == NULL) return NULL; 129 if (update->expression()->AsVariableProxy()->AsVariable() != loop_var) { 130 return NULL; 131 } 132 133 // The direction of the count operation must agree with the start and the end 134 // value. We currently do not allow the initial value to be the same as the 135 // terminal value. This _would_ be ok as long as the loop body never executes 136 // or executes exactly one time. 137 if (init_value == term_value) return NULL; 138 if (init_value < term_value && update->op() != Token::INC) return NULL; 139 if (init_value > term_value && update->op() != Token::DEC) return NULL; 140 141 // Check that the update operation cannot overflow the smi range. This can 142 // occur in the two cases where the loop bound is equal to the largest or 143 // smallest smi. 144 if (update->op() == Token::INC && term_value == Smi::kMaxValue) return NULL; 145 if (update->op() == Token::DEC && term_value == Smi::kMinValue) return NULL; 146 147 // Found a smi loop variable. 148 return loop_var; 149 } 150 151 int AssignedVariablesAnalyzer::BitIndex(Variable* var) { 152 ASSERT(var != NULL); 153 ASSERT(var->IsStackAllocated()); 154 Slot* slot = var->AsSlot(); 155 if (slot->type() == Slot::PARAMETER) { 156 return slot->index(); 157 } else { 158 return info_->scope()->num_parameters() + slot->index(); 159 } 160 } 161 162 163 void AssignedVariablesAnalyzer::RecordAssignedVar(Variable* var) { 164 ASSERT(var != NULL); 165 if (var->IsStackAllocated()) { 166 av_.Add(BitIndex(var)); 167 } 168 } 169 170 171 void AssignedVariablesAnalyzer::MarkIfTrivial(Expression* expr) { 172 Variable* var = expr->AsVariableProxy()->AsVariable(); 173 if (var != NULL && 174 var->IsStackAllocated() && 175 !var->is_arguments() && 176 var->mode() != Variable::CONST && 177 (var->is_this() || !av_.Contains(BitIndex(var)))) { 178 expr->AsVariableProxy()->MarkAsTrivial(); 179 } 180 } 181 182 183 void AssignedVariablesAnalyzer::ProcessExpression(Expression* expr) { 184 BitVector saved_av(av_); 185 av_.Clear(); 186 Visit(expr); 187 av_.Union(saved_av); 188 } 189 190 void AssignedVariablesAnalyzer::VisitBlock(Block* stmt) { 191 VisitStatements(stmt->statements()); 192 } 193 194 195 void AssignedVariablesAnalyzer::VisitExpressionStatement( 196 ExpressionStatement* stmt) { 197 ProcessExpression(stmt->expression()); 198 } 199 200 201 void AssignedVariablesAnalyzer::VisitEmptyStatement(EmptyStatement* stmt) { 202 // Do nothing. 203 } 204 205 206 void AssignedVariablesAnalyzer::VisitIfStatement(IfStatement* stmt) { 207 ProcessExpression(stmt->condition()); 208 Visit(stmt->then_statement()); 209 Visit(stmt->else_statement()); 210 } 211 212 213 void AssignedVariablesAnalyzer::VisitContinueStatement( 214 ContinueStatement* stmt) { 215 // Nothing to do. 216 } 217 218 219 void AssignedVariablesAnalyzer::VisitBreakStatement(BreakStatement* stmt) { 220 // Nothing to do. 221 } 222 223 224 void AssignedVariablesAnalyzer::VisitReturnStatement(ReturnStatement* stmt) { 225 ProcessExpression(stmt->expression()); 226 } 227 228 229 void AssignedVariablesAnalyzer::VisitWithEnterStatement( 230 WithEnterStatement* stmt) { 231 ProcessExpression(stmt->expression()); 232 } 233 234 235 void AssignedVariablesAnalyzer::VisitWithExitStatement( 236 WithExitStatement* stmt) { 237 // Nothing to do. 238 } 239 240 241 void AssignedVariablesAnalyzer::VisitSwitchStatement(SwitchStatement* stmt) { 242 BitVector result(av_); 243 av_.Clear(); 244 Visit(stmt->tag()); 245 result.Union(av_); 246 for (int i = 0; i < stmt->cases()->length(); i++) { 247 CaseClause* clause = stmt->cases()->at(i); 248 if (!clause->is_default()) { 249 av_.Clear(); 250 Visit(clause->label()); 251 result.Union(av_); 252 } 253 VisitStatements(clause->statements()); 254 } 255 av_.Union(result); 256 } 257 258 259 void AssignedVariablesAnalyzer::VisitDoWhileStatement(DoWhileStatement* stmt) { 260 ProcessExpression(stmt->cond()); 261 Visit(stmt->body()); 262 } 263 264 265 void AssignedVariablesAnalyzer::VisitWhileStatement(WhileStatement* stmt) { 266 ProcessExpression(stmt->cond()); 267 Visit(stmt->body()); 268 } 269 270 271 void AssignedVariablesAnalyzer::VisitForStatement(ForStatement* stmt) { 272 if (stmt->init() != NULL) Visit(stmt->init()); 273 if (stmt->cond() != NULL) ProcessExpression(stmt->cond()); 274 if (stmt->next() != NULL) Visit(stmt->next()); 275 276 // Process loop body. After visiting the loop body av_ contains 277 // the assigned variables of the loop body. 278 BitVector saved_av(av_); 279 av_.Clear(); 280 Visit(stmt->body()); 281 282 Variable* var = FindSmiLoopVariable(stmt); 283 if (var != NULL && !av_.Contains(BitIndex(var))) { 284 stmt->set_loop_variable(var); 285 } 286 av_.Union(saved_av); 287 } 288 289 290 void AssignedVariablesAnalyzer::VisitForInStatement(ForInStatement* stmt) { 291 ProcessExpression(stmt->each()); 292 ProcessExpression(stmt->enumerable()); 293 Visit(stmt->body()); 294 } 295 296 297 void AssignedVariablesAnalyzer::VisitTryCatchStatement( 298 TryCatchStatement* stmt) { 299 Visit(stmt->try_block()); 300 Visit(stmt->catch_block()); 301 } 302 303 304 void AssignedVariablesAnalyzer::VisitTryFinallyStatement( 305 TryFinallyStatement* stmt) { 306 Visit(stmt->try_block()); 307 Visit(stmt->finally_block()); 308 } 309 310 311 void AssignedVariablesAnalyzer::VisitDebuggerStatement( 312 DebuggerStatement* stmt) { 313 // Nothing to do. 314 } 315 316 317 void AssignedVariablesAnalyzer::VisitFunctionLiteral(FunctionLiteral* expr) { 318 // Nothing to do. 319 ASSERT(av_.IsEmpty()); 320 } 321 322 323 void AssignedVariablesAnalyzer::VisitSharedFunctionInfoLiteral( 324 SharedFunctionInfoLiteral* expr) { 325 // Nothing to do. 326 ASSERT(av_.IsEmpty()); 327 } 328 329 330 void AssignedVariablesAnalyzer::VisitConditional(Conditional* expr) { 331 ASSERT(av_.IsEmpty()); 332 333 Visit(expr->condition()); 334 335 BitVector result(av_); 336 av_.Clear(); 337 Visit(expr->then_expression()); 338 result.Union(av_); 339 340 av_.Clear(); 341 Visit(expr->else_expression()); 342 av_.Union(result); 343 } 344 345 346 void AssignedVariablesAnalyzer::VisitVariableProxy(VariableProxy* expr) { 347 // Nothing to do. 348 ASSERT(av_.IsEmpty()); 349 } 350 351 352 void AssignedVariablesAnalyzer::VisitLiteral(Literal* expr) { 353 // Nothing to do. 354 ASSERT(av_.IsEmpty()); 355 } 356 357 358 void AssignedVariablesAnalyzer::VisitRegExpLiteral(RegExpLiteral* expr) { 359 // Nothing to do. 360 ASSERT(av_.IsEmpty()); 361 } 362 363 364 void AssignedVariablesAnalyzer::VisitObjectLiteral(ObjectLiteral* expr) { 365 ASSERT(av_.IsEmpty()); 366 BitVector result(av_.length()); 367 for (int i = 0; i < expr->properties()->length(); i++) { 368 Visit(expr->properties()->at(i)->value()); 369 result.Union(av_); 370 av_.Clear(); 371 } 372 av_ = result; 373 } 374 375 376 void AssignedVariablesAnalyzer::VisitArrayLiteral(ArrayLiteral* expr) { 377 ASSERT(av_.IsEmpty()); 378 BitVector result(av_.length()); 379 for (int i = 0; i < expr->values()->length(); i++) { 380 Visit(expr->values()->at(i)); 381 result.Union(av_); 382 av_.Clear(); 383 } 384 av_ = result; 385 } 386 387 388 void AssignedVariablesAnalyzer::VisitCatchExtensionObject( 389 CatchExtensionObject* expr) { 390 ASSERT(av_.IsEmpty()); 391 Visit(expr->key()); 392 ProcessExpression(expr->value()); 393 } 394 395 396 void AssignedVariablesAnalyzer::VisitAssignment(Assignment* expr) { 397 ASSERT(av_.IsEmpty()); 398 399 // There are three kinds of assignments: variable assignments, property 400 // assignments, and reference errors (invalid left-hand sides). 401 Variable* var = expr->target()->AsVariableProxy()->AsVariable(); 402 Property* prop = expr->target()->AsProperty(); 403 ASSERT(var == NULL || prop == NULL); 404 405 if (var != NULL) { 406 MarkIfTrivial(expr->value()); 407 Visit(expr->value()); 408 if (expr->is_compound()) { 409 // Left-hand side occurs also as an rvalue. 410 MarkIfTrivial(expr->target()); 411 ProcessExpression(expr->target()); 412 } 413 RecordAssignedVar(var); 414 415 } else if (prop != NULL) { 416 MarkIfTrivial(expr->value()); 417 Visit(expr->value()); 418 if (!prop->key()->IsPropertyName()) { 419 MarkIfTrivial(prop->key()); 420 ProcessExpression(prop->key()); 421 } 422 MarkIfTrivial(prop->obj()); 423 ProcessExpression(prop->obj()); 424 425 } else { 426 Visit(expr->target()); 427 } 428 } 429 430 431 void AssignedVariablesAnalyzer::VisitThrow(Throw* expr) { 432 ASSERT(av_.IsEmpty()); 433 Visit(expr->exception()); 434 } 435 436 437 void AssignedVariablesAnalyzer::VisitProperty(Property* expr) { 438 ASSERT(av_.IsEmpty()); 439 if (!expr->key()->IsPropertyName()) { 440 MarkIfTrivial(expr->key()); 441 Visit(expr->key()); 442 } 443 MarkIfTrivial(expr->obj()); 444 ProcessExpression(expr->obj()); 445 } 446 447 448 void AssignedVariablesAnalyzer::VisitCall(Call* expr) { 449 ASSERT(av_.IsEmpty()); 450 Visit(expr->expression()); 451 BitVector result(av_); 452 for (int i = 0; i < expr->arguments()->length(); i++) { 453 av_.Clear(); 454 Visit(expr->arguments()->at(i)); 455 result.Union(av_); 456 } 457 av_ = result; 458 } 459 460 461 void AssignedVariablesAnalyzer::VisitCallNew(CallNew* expr) { 462 ASSERT(av_.IsEmpty()); 463 Visit(expr->expression()); 464 BitVector result(av_); 465 for (int i = 0; i < expr->arguments()->length(); i++) { 466 av_.Clear(); 467 Visit(expr->arguments()->at(i)); 468 result.Union(av_); 469 } 470 av_ = result; 471 } 472 473 474 void AssignedVariablesAnalyzer::VisitCallRuntime(CallRuntime* expr) { 475 ASSERT(av_.IsEmpty()); 476 BitVector result(av_); 477 for (int i = 0; i < expr->arguments()->length(); i++) { 478 av_.Clear(); 479 Visit(expr->arguments()->at(i)); 480 result.Union(av_); 481 } 482 av_ = result; 483 } 484 485 486 void AssignedVariablesAnalyzer::VisitUnaryOperation(UnaryOperation* expr) { 487 ASSERT(av_.IsEmpty()); 488 MarkIfTrivial(expr->expression()); 489 Visit(expr->expression()); 490 } 491 492 493 void AssignedVariablesAnalyzer::VisitCountOperation(CountOperation* expr) { 494 ASSERT(av_.IsEmpty()); 495 if (expr->is_prefix()) MarkIfTrivial(expr->expression()); 496 Visit(expr->expression()); 497 498 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); 499 if (var != NULL) RecordAssignedVar(var); 500 } 501 502 503 void AssignedVariablesAnalyzer::VisitBinaryOperation(BinaryOperation* expr) { 504 ASSERT(av_.IsEmpty()); 505 MarkIfTrivial(expr->right()); 506 Visit(expr->right()); 507 MarkIfTrivial(expr->left()); 508 ProcessExpression(expr->left()); 509 } 510 511 512 void AssignedVariablesAnalyzer::VisitCompareOperation(CompareOperation* expr) { 513 ASSERT(av_.IsEmpty()); 514 MarkIfTrivial(expr->right()); 515 Visit(expr->right()); 516 MarkIfTrivial(expr->left()); 517 ProcessExpression(expr->left()); 518 } 519 520 521 void AssignedVariablesAnalyzer::VisitCompareToNull(CompareToNull* expr) { 522 ASSERT(av_.IsEmpty()); 523 MarkIfTrivial(expr->expression()); 524 Visit(expr->expression()); 525 } 526 527 528 void AssignedVariablesAnalyzer::VisitThisFunction(ThisFunction* expr) { 529 // Nothing to do. 530 ASSERT(av_.IsEmpty()); 531 } 532 533 534 void AssignedVariablesAnalyzer::VisitDeclaration(Declaration* decl) { 535 UNREACHABLE(); 536 } 537 538 539 } } // namespace v8::internal 540