説明を見る。00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "v8.h"
00029
00030 #include "ast.h"
00031 #include "scopes.h"
00032 #include "usage-analyzer.h"
00033
00034 namespace v8 { namespace internal {
00035
00036
00037 static const int MinWeight = 1;
00038 static const int MaxWeight = 1000000;
00039 static const int InitialWeight = 100;
00040
00041
00042 class UsageComputer: public Visitor {
00043 public:
00044 static bool Traverse(Node* node);
00045
00046 void VisitBlock(Block* node);
00047 void VisitDeclaration(Declaration* node);
00048 void VisitExpressionStatement(ExpressionStatement* node);
00049 void VisitEmptyStatement(EmptyStatement* node);
00050 void VisitIfStatement(IfStatement* node);
00051 void VisitContinueStatement(ContinueStatement* node);
00052 void VisitBreakStatement(BreakStatement* node);
00053 void VisitReturnStatement(ReturnStatement* node);
00054 void VisitWithEnterStatement(WithEnterStatement* node);
00055 void VisitWithExitStatement(WithExitStatement* node);
00056 void VisitSwitchStatement(SwitchStatement* node);
00057 void VisitLoopStatement(LoopStatement* node);
00058 void VisitForInStatement(ForInStatement* node);
00059 void VisitTryCatch(TryCatch* node);
00060 void VisitTryFinally(TryFinally* node);
00061 void VisitDebuggerStatement(DebuggerStatement* node);
00062 void VisitFunctionLiteral(FunctionLiteral* node);
00063 void VisitFunctionBoilerplateLiteral(FunctionBoilerplateLiteral* node);
00064 void VisitConditional(Conditional* node);
00065 void VisitSlot(Slot* node);
00066 void VisitVariable(Variable* node);
00067 void VisitVariableProxy(VariableProxy* node);
00068 void VisitLiteral(Literal* node);
00069 void VisitRegExpLiteral(RegExpLiteral* node);
00070 void VisitObjectLiteral(ObjectLiteral* node);
00071 void VisitArrayLiteral(ArrayLiteral* node);
00072 void VisitAssignment(Assignment* node);
00073 void VisitThrow(Throw* node);
00074 void VisitProperty(Property* node);
00075 void VisitCall(Call* node);
00076 void VisitCallNew(CallNew* node);
00077 void VisitCallRuntime(CallRuntime* node);
00078 void VisitUnaryOperation(UnaryOperation* node);
00079 void VisitCountOperation(CountOperation* node);
00080 void VisitBinaryOperation(BinaryOperation* node);
00081 void VisitCompareOperation(CompareOperation* node);
00082 void VisitThisFunction(ThisFunction* node);
00083
00084 private:
00085 int weight_;
00086 bool is_write_;
00087
00088 UsageComputer(int weight, bool is_write);
00089 virtual ~UsageComputer();
00090
00091
00092 void RecordUses(UseCount* uses);
00093 void Read(Expression* x);
00094 void Write(Expression* x);
00095 void ReadList(ZoneList<Expression*>* list);
00096 void ReadList(ZoneList<ObjectLiteral::Property*>* list);
00097
00098 friend class WeightScaler;
00099 };
00100
00101
00102 class WeightScaler BASE_EMBEDDED {
00103 public:
00104 WeightScaler(UsageComputer* uc, float scale);
00105 ~WeightScaler();
00106
00107 private:
00108 UsageComputer* uc_;
00109 int old_weight_;
00110 };
00111
00112
00113
00114
00115
00116 bool UsageComputer::Traverse(Node* node) {
00117 UsageComputer uc(InitialWeight, false);
00118 uc.Visit(node);
00119 return !uc.HasStackOverflow();
00120 }
00121
00122
00123 void UsageComputer::VisitBlock(Block* node) {
00124 VisitStatements(node->statements());
00125 }
00126
00127
00128 void UsageComputer::VisitDeclaration(Declaration* node) {
00129 Write(node->proxy());
00130 if (node->fun() != NULL)
00131 VisitFunctionLiteral(node->fun());
00132 }
00133
00134
00135 void UsageComputer::VisitExpressionStatement(ExpressionStatement* node) {
00136 Visit(node->expression());
00137 }
00138
00139
00140 void UsageComputer::VisitEmptyStatement(EmptyStatement* node) {
00141
00142 }
00143
00144
00145 void UsageComputer::VisitIfStatement(IfStatement* node) {
00146 Read(node->condition());
00147 { WeightScaler ws(this, 0.5);
00148 Visit(node->then_statement());
00149 Visit(node->else_statement());
00150 }
00151 }
00152
00153
00154 void UsageComputer::VisitContinueStatement(ContinueStatement* node) {
00155
00156 }
00157
00158
00159 void UsageComputer::VisitBreakStatement(BreakStatement* node) {
00160
00161 }
00162
00163
00164 void UsageComputer::VisitReturnStatement(ReturnStatement* node) {
00165 Read(node->expression());
00166 }
00167
00168
00169 void UsageComputer::VisitWithEnterStatement(WithEnterStatement* node) {
00170 Read(node->expression());
00171 }
00172
00173
00174 void UsageComputer::VisitWithExitStatement(WithExitStatement* node) {
00175
00176 }
00177
00178
00179 void UsageComputer::VisitSwitchStatement(SwitchStatement* node) {
00180 Read(node->tag());
00181 ZoneList<CaseClause*>* cases = node->cases();
00182 for (int i = cases->length(); i-- > 0;) {
00183 WeightScaler ws(this, static_cast<float>(1.0 / cases->length()));
00184 CaseClause* clause = cases->at(i);
00185 if (!clause->is_default())
00186 Read(clause->label());
00187 VisitStatements(clause->statements());
00188 }
00189 }
00190
00191
00192 void UsageComputer::VisitLoopStatement(LoopStatement* node) {
00193 if (node->init() != NULL)
00194 Visit(node->init());
00195 { WeightScaler ws(this, 10.0);
00196 if (node->cond() != NULL)
00197 Read(node->cond());
00198 if (node->next() != NULL)
00199 Visit(node->next());
00200 Visit(node->body());
00201 }
00202 }
00203
00204
00205 void UsageComputer::VisitForInStatement(ForInStatement* node) {
00206 WeightScaler ws(this, 10.0);
00207 Write(node->each());
00208 Read(node->enumerable());
00209 Visit(node->body());
00210 }
00211
00212
00213 void UsageComputer::VisitTryCatch(TryCatch* node) {
00214 Visit(node->try_block());
00215 { WeightScaler ws(this, 0.25);
00216 Write(node->catch_var());
00217 Visit(node->catch_block());
00218 }
00219 }
00220
00221
00222 void UsageComputer::VisitTryFinally(TryFinally* node) {
00223 Visit(node->try_block());
00224 Visit(node->finally_block());
00225 }
00226
00227
00228 void UsageComputer::VisitDebuggerStatement(DebuggerStatement* node) {
00229 }
00230
00231
00232 void UsageComputer::VisitFunctionLiteral(FunctionLiteral* node) {
00233 ZoneList<Declaration*>* decls = node->scope()->declarations();
00234 for (int i = 0; i < decls->length(); i++) VisitDeclaration(decls->at(i));
00235 VisitStatements(node->body());
00236 }
00237
00238
00239 void UsageComputer::VisitFunctionBoilerplateLiteral(
00240 FunctionBoilerplateLiteral* node) {
00241
00242 }
00243
00244
00245 void UsageComputer::VisitConditional(Conditional* node) {
00246 Read(node->condition());
00247 { WeightScaler ws(this, 0.5);
00248 Read(node->then_expression());
00249 Read(node->else_expression());
00250 }
00251 }
00252
00253
00254 void UsageComputer::VisitSlot(Slot* node) {
00255 UNREACHABLE();
00256 }
00257
00258
00259 void UsageComputer::VisitVariable(Variable* node) {
00260 RecordUses(node->var_uses());
00261 }
00262
00263
00264 void UsageComputer::VisitVariableProxy(VariableProxy* node) {
00265
00266
00267 RecordUses(node->var_uses());
00268 }
00269
00270
00271 void UsageComputer::VisitLiteral(Literal* node) {
00272
00273 }
00274
00275 void UsageComputer::VisitRegExpLiteral(RegExpLiteral* node) {
00276
00277 }
00278
00279
00280 void UsageComputer::VisitObjectLiteral(ObjectLiteral* node) {
00281 ReadList(node->properties());
00282 }
00283
00284
00285 void UsageComputer::VisitArrayLiteral(ArrayLiteral* node) {
00286 ReadList(node->values());
00287 }
00288
00289
00290 void UsageComputer::VisitAssignment(Assignment* node) {
00291 if (node->op() != Token::ASSIGN)
00292 Read(node->target());
00293 Write(node->target());
00294 Read(node->value());
00295 }
00296
00297
00298 void UsageComputer::VisitThrow(Throw* node) {
00299 Read(node->exception());
00300 }
00301
00302
00303 void UsageComputer::VisitProperty(Property* node) {
00304
00305
00306 Read(node->obj());
00307 Read(node->key());
00308
00309
00310
00311 VariableProxy* proxy = node->obj()->AsVariableProxy();
00312 if (proxy != NULL) {
00313 RecordUses(proxy->obj_uses());
00314 }
00315 }
00316
00317
00318 void UsageComputer::VisitCall(Call* node) {
00319 Read(node->expression());
00320 ReadList(node->arguments());
00321 }
00322
00323
00324 void UsageComputer::VisitCallNew(CallNew* node) {
00325 VisitCall(node);
00326 }
00327
00328
00329 void UsageComputer::VisitCallRuntime(CallRuntime* node) {
00330 ReadList(node->arguments());
00331 }
00332
00333
00334 void UsageComputer::VisitUnaryOperation(UnaryOperation* node) {
00335 Read(node->expression());
00336 }
00337
00338
00339 void UsageComputer::VisitCountOperation(CountOperation* node) {
00340 Read(node->expression());
00341 Write(node->expression());
00342 }
00343
00344
00345 void UsageComputer::VisitBinaryOperation(BinaryOperation* node) {
00346 Read(node->left());
00347 Read(node->right());
00348 }
00349
00350
00351 void UsageComputer::VisitCompareOperation(CompareOperation* node) {
00352 Read(node->left());
00353 Read(node->right());
00354 }
00355
00356
00357 void UsageComputer::VisitThisFunction(ThisFunction* node) {
00358 }
00359
00360
00361 UsageComputer::UsageComputer(int weight, bool is_write) {
00362 weight_ = weight;
00363 is_write_ = is_write;
00364 }
00365
00366
00367 UsageComputer::~UsageComputer() {
00368
00369 }
00370
00371
00372 void UsageComputer::RecordUses(UseCount* uses) {
00373 if (is_write_)
00374 uses->RecordWrite(weight_);
00375 else
00376 uses->RecordRead(weight_);
00377 }
00378
00379
00380 void UsageComputer::Read(Expression* x) {
00381 if (is_write_) {
00382 UsageComputer uc(weight_, false);
00383 uc.Visit(x);
00384 } else {
00385 Visit(x);
00386 }
00387 }
00388
00389
00390 void UsageComputer::Write(Expression* x) {
00391 if (!is_write_) {
00392 UsageComputer uc(weight_, true);
00393 uc.Visit(x);
00394 } else {
00395 Visit(x);
00396 }
00397 }
00398
00399
00400 void UsageComputer::ReadList(ZoneList<Expression*>* list) {
00401 for (int i = list->length(); i-- > 0; )
00402 Read(list->at(i));
00403 }
00404
00405
00406 void UsageComputer::ReadList(ZoneList<ObjectLiteral::Property*>* list) {
00407 for (int i = list->length(); i-- > 0; )
00408 Read(list->at(i)->value());
00409 }
00410
00411
00412
00413
00414
00415 WeightScaler::WeightScaler(UsageComputer* uc, float scale) {
00416 uc_ = uc;
00417 old_weight_ = uc->weight_;
00418 int new_weight = static_cast<int>(uc->weight_ * scale);
00419 if (new_weight <= 0) new_weight = MinWeight;
00420 else if (new_weight > MaxWeight) new_weight = MaxWeight;
00421 uc->weight_ = new_weight;
00422 }
00423
00424
00425 WeightScaler::~WeightScaler() {
00426 uc_->weight_ = old_weight_;
00427 }
00428
00429
00430
00431
00432
00433 bool AnalyzeVariableUsage(FunctionLiteral* lit) {
00434 if (!FLAG_usage_computation) return true;
00435 return UsageComputer::Traverse(lit);
00436 }
00437
00438 } }