| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 56 current_index_++; | 56 current_index_++; |
| 57 if (Done()) return; | 57 if (Done()) return; |
| 58 val = target_->data_[current_index_]; | 58 val = target_->data_[current_index_]; |
| 59 current_ = current_index_ << 5; | 59 current_ = current_index_ << 5; |
| 60 } | 60 } |
| 61 val = SkipZeroBytes(val); | 61 val = SkipZeroBytes(val); |
| 62 val = SkipZeroBits(val); | 62 val = SkipZeroBits(val); |
| 63 current_value_ = val >> 1; | 63 current_value_ = val >> 1; |
| 64 } | 64 } |
| 65 | 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 | 66 } } // namespace v8::internal |
| OLD | NEW |