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 10 matching lines...) Expand all Loading... |
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 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. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | 27 |
28 #include "v8.h" | 28 #include "v8.h" |
29 | 29 |
30 #include "data-flow.h" | 30 #include "data-flow.h" |
31 #include "scopes.h" | |
32 | 31 |
33 namespace v8 { | 32 namespace v8 { |
34 namespace internal { | 33 namespace internal { |
35 | 34 |
36 | 35 |
37 void FlowGraph::AppendInstruction(AstNode* instruction) { | 36 void FlowGraph::AppendInstruction(AstNode* instruction) { |
38 // Add a (non-null) AstNode to the end of the graph fragment. | 37 // Add a (non-null) AstNode to the end of the graph fragment. |
39 ASSERT(instruction != NULL); | 38 ASSERT(instruction != NULL); |
40 if (exit()->IsExitNode()) return; | 39 if (exit()->IsExitNode()) return; |
41 if (!exit()->IsBlockNode()) AppendNode(new BlockNode()); | 40 if (!exit()->IsBlockNode()) AppendNode(new BlockNode()); |
(...skipping 987 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1029 void LivenessAnalyzer::VisitCompareOperation(CompareOperation* expr) { | 1028 void LivenessAnalyzer::VisitCompareOperation(CompareOperation* expr) { |
1030 UNREACHABLE(); | 1029 UNREACHABLE(); |
1031 } | 1030 } |
1032 | 1031 |
1033 | 1032 |
1034 void LivenessAnalyzer::VisitThisFunction(ThisFunction* expr) { | 1033 void LivenessAnalyzer::VisitThisFunction(ThisFunction* expr) { |
1035 UNREACHABLE(); | 1034 UNREACHABLE(); |
1036 } | 1035 } |
1037 | 1036 |
1038 | 1037 |
1039 AssignedVariablesAnalyzer::AssignedVariablesAnalyzer(FunctionLiteral* fun) | |
1040 : fun_(fun), | |
1041 av_(fun->scope()->num_parameters() + fun->scope()->num_stack_slots()) {} | |
1042 | |
1043 | |
1044 void AssignedVariablesAnalyzer::Analyze() { | |
1045 ASSERT(av_.length() > 0); | |
1046 VisitStatements(fun_->body()); | |
1047 } | |
1048 | |
1049 | |
1050 Variable* AssignedVariablesAnalyzer::FindSmiLoopVariable(ForStatement* stmt) { | |
1051 // The loop must have all necessary parts. | |
1052 if (stmt->init() == NULL || stmt->cond() == NULL || stmt->next() == NULL) { | |
1053 return NULL; | |
1054 } | |
1055 // The initialization statement has to be a simple assignment. | |
1056 Assignment* init = stmt->init()->StatementAsSimpleAssignment(); | |
1057 if (init == NULL) return NULL; | |
1058 | |
1059 // We only deal with local variables. | |
1060 Variable* loop_var = init->target()->AsVariableProxy()->AsVariable(); | |
1061 if (!loop_var->IsStackAllocated()) return NULL; | |
1062 | |
1063 // The initial value has to be a smi. | |
1064 Literal* init_lit = init->value()->AsLiteral(); | |
1065 if (init_lit == NULL || !init_lit->handle()->IsSmi()) return NULL; | |
1066 int init_value = Smi::cast(*init_lit->handle())->value(); | |
1067 | |
1068 // The condition must be a compare of variable with <, <=, >, or >=. | |
1069 CompareOperation* cond = stmt->cond()->AsCompareOperation(); | |
1070 if (cond == NULL) return NULL; | |
1071 if (cond->op() != Token::LT | |
1072 && cond->op() != Token::LTE | |
1073 && cond->op() != Token::GT | |
1074 && cond->op() != Token::GTE) return NULL; | |
1075 | |
1076 // The lhs must be the same variable as in the init expression. | |
1077 if (cond->left()->AsVariableProxy()->AsVariable() != loop_var) return NULL; | |
1078 | |
1079 // The rhs must be a smi. | |
1080 Literal* term_lit = cond->right()->AsLiteral(); | |
1081 if (term_lit == NULL || !term_lit->handle()->IsSmi()) return NULL; | |
1082 int term_value = Smi::cast(*term_lit->handle())->value(); | |
1083 | |
1084 // The count operation updates the same variable as in the init expression. | |
1085 CountOperation* update = stmt->next()->StatementAsCountOperation(); | |
1086 if (update == NULL) return NULL; | |
1087 if (update->expression()->AsVariableProxy()->AsVariable() != loop_var) { | |
1088 return NULL; | |
1089 } | |
1090 | |
1091 // The direction of the count operation must agree with the start and the end | |
1092 // value. We currently do not allow the initial value to be the same as the | |
1093 // terminal value. This _would_ be ok as long as the loop body never executes | |
1094 // or executes exactly one time. | |
1095 if (init_value == term_value) return NULL; | |
1096 if (init_value < term_value && update->op() != Token::INC) return NULL; | |
1097 if (init_value > term_value && update->op() != Token::DEC) return NULL; | |
1098 | |
1099 // Found a smi loop variable. | |
1100 return loop_var; | |
1101 } | |
1102 | |
1103 int AssignedVariablesAnalyzer::BitIndex(Variable* var) { | |
1104 ASSERT(var != NULL); | |
1105 ASSERT(var->IsStackAllocated()); | |
1106 Slot* slot = var->slot(); | |
1107 if (slot->type() == Slot::PARAMETER) { | |
1108 return slot->index(); | |
1109 } else { | |
1110 return fun_->scope()->num_parameters() + slot->index(); | |
1111 } | |
1112 } | |
1113 | |
1114 | |
1115 void AssignedVariablesAnalyzer::RecordAssignedVar(Variable* var) { | |
1116 ASSERT(var != NULL); | |
1117 if (var->IsStackAllocated()) { | |
1118 av_.Add(BitIndex(var)); | |
1119 } | |
1120 } | |
1121 | |
1122 | |
1123 void AssignedVariablesAnalyzer::MarkIfTrivial(Expression* expr) { | |
1124 Variable* var = expr->AsVariableProxy()->AsVariable(); | |
1125 if (var != NULL && | |
1126 var->IsStackAllocated() && | |
1127 (var->is_this() || !av_.Contains(BitIndex(var)))) { | |
1128 expr->AsVariableProxy()->set_is_trivial(true); | |
1129 } | |
1130 } | |
1131 | |
1132 | |
1133 void AssignedVariablesAnalyzer::ProcessExpression(Expression* expr) { | |
1134 BitVector saved_av(av_); | |
1135 av_.Clear(); | |
1136 Visit(expr); | |
1137 av_.Union(saved_av); | |
1138 } | |
1139 | |
1140 void AssignedVariablesAnalyzer::VisitBlock(Block* stmt) { | |
1141 VisitStatements(stmt->statements()); | |
1142 } | |
1143 | |
1144 | |
1145 void AssignedVariablesAnalyzer::VisitExpressionStatement( | |
1146 ExpressionStatement* stmt) { | |
1147 ProcessExpression(stmt->expression()); | |
1148 } | |
1149 | |
1150 | |
1151 void AssignedVariablesAnalyzer::VisitEmptyStatement(EmptyStatement* stmt) { | |
1152 // Do nothing. | |
1153 } | |
1154 | |
1155 | |
1156 void AssignedVariablesAnalyzer::VisitIfStatement(IfStatement* stmt) { | |
1157 ProcessExpression(stmt->condition()); | |
1158 Visit(stmt->then_statement()); | |
1159 Visit(stmt->else_statement()); | |
1160 } | |
1161 | |
1162 | |
1163 void AssignedVariablesAnalyzer::VisitContinueStatement( | |
1164 ContinueStatement* stmt) { | |
1165 // Nothing to do. | |
1166 } | |
1167 | |
1168 | |
1169 void AssignedVariablesAnalyzer::VisitBreakStatement(BreakStatement* stmt) { | |
1170 // Nothing to do. | |
1171 } | |
1172 | |
1173 | |
1174 void AssignedVariablesAnalyzer::VisitReturnStatement(ReturnStatement* stmt) { | |
1175 ProcessExpression(stmt->expression()); | |
1176 } | |
1177 | |
1178 | |
1179 void AssignedVariablesAnalyzer::VisitWithEnterStatement( | |
1180 WithEnterStatement* stmt) { | |
1181 ProcessExpression(stmt->expression()); | |
1182 } | |
1183 | |
1184 | |
1185 void AssignedVariablesAnalyzer::VisitWithExitStatement( | |
1186 WithExitStatement* stmt) { | |
1187 // Nothing to do. | |
1188 } | |
1189 | |
1190 | |
1191 void AssignedVariablesAnalyzer::VisitSwitchStatement(SwitchStatement* stmt) { | |
1192 BitVector result(av_); | |
1193 av_.Clear(); | |
1194 Visit(stmt->tag()); | |
1195 result.Union(av_); | |
1196 for (int i = 0; i < stmt->cases()->length(); i++) { | |
1197 CaseClause* clause = stmt->cases()->at(i); | |
1198 if (!clause->is_default()) { | |
1199 av_.Clear(); | |
1200 Visit(clause->label()); | |
1201 result.Union(av_); | |
1202 } | |
1203 VisitStatements(clause->statements()); | |
1204 } | |
1205 av_.Union(result); | |
1206 } | |
1207 | |
1208 | |
1209 void AssignedVariablesAnalyzer::VisitDoWhileStatement(DoWhileStatement* stmt) { | |
1210 ProcessExpression(stmt->cond()); | |
1211 Visit(stmt->body()); | |
1212 } | |
1213 | |
1214 | |
1215 void AssignedVariablesAnalyzer::VisitWhileStatement(WhileStatement* stmt) { | |
1216 ProcessExpression(stmt->cond()); | |
1217 Visit(stmt->body()); | |
1218 } | |
1219 | |
1220 | |
1221 void AssignedVariablesAnalyzer::VisitForStatement(ForStatement* stmt) { | |
1222 if (stmt->init() != NULL) Visit(stmt->init()); | |
1223 | |
1224 if (stmt->cond() != NULL) ProcessExpression(stmt->cond()); | |
1225 | |
1226 if (stmt->next() != NULL) Visit(stmt->next()); | |
1227 | |
1228 // Process loop body. After visiting the loop body av_ contains | |
1229 // the assigned variables of the loop body. | |
1230 BitVector saved_av(av_); | |
1231 av_.Clear(); | |
1232 Visit(stmt->body()); | |
1233 | |
1234 Variable* var = FindSmiLoopVariable(stmt); | |
1235 if (var != NULL && !av_.Contains(BitIndex(var))) { | |
1236 stmt->set_loop_variable(var); | |
1237 } | |
1238 | |
1239 av_.Union(saved_av); | |
1240 } | |
1241 | |
1242 | |
1243 void AssignedVariablesAnalyzer::VisitForInStatement(ForInStatement* stmt) { | |
1244 ProcessExpression(stmt->each()); | |
1245 ProcessExpression(stmt->enumerable()); | |
1246 Visit(stmt->body()); | |
1247 } | |
1248 | |
1249 | |
1250 void AssignedVariablesAnalyzer::VisitTryCatchStatement( | |
1251 TryCatchStatement* stmt) { | |
1252 Visit(stmt->try_block()); | |
1253 Visit(stmt->catch_block()); | |
1254 } | |
1255 | |
1256 | |
1257 void AssignedVariablesAnalyzer::VisitTryFinallyStatement( | |
1258 TryFinallyStatement* stmt) { | |
1259 Visit(stmt->try_block()); | |
1260 Visit(stmt->finally_block()); | |
1261 } | |
1262 | |
1263 | |
1264 void AssignedVariablesAnalyzer::VisitDebuggerStatement( | |
1265 DebuggerStatement* stmt) { | |
1266 // Nothing to do. | |
1267 } | |
1268 | |
1269 | |
1270 void AssignedVariablesAnalyzer::VisitFunctionLiteral(FunctionLiteral* expr) { | |
1271 // Nothing to do. | |
1272 ASSERT(av_.IsEmpty()); | |
1273 } | |
1274 | |
1275 | |
1276 void AssignedVariablesAnalyzer::VisitFunctionBoilerplateLiteral( | |
1277 FunctionBoilerplateLiteral* expr) { | |
1278 // Nothing to do. | |
1279 ASSERT(av_.IsEmpty()); | |
1280 } | |
1281 | |
1282 | |
1283 void AssignedVariablesAnalyzer::VisitConditional(Conditional* expr) { | |
1284 ASSERT(av_.IsEmpty()); | |
1285 | |
1286 Visit(expr->condition()); | |
1287 | |
1288 BitVector result(av_); | |
1289 av_.Clear(); | |
1290 Visit(expr->then_expression()); | |
1291 result.Union(av_); | |
1292 | |
1293 av_.Clear(); | |
1294 Visit(expr->else_expression()); | |
1295 av_.Union(result); | |
1296 } | |
1297 | |
1298 | |
1299 void AssignedVariablesAnalyzer::VisitSlot(Slot* expr) { | |
1300 UNREACHABLE(); | |
1301 } | |
1302 | |
1303 | |
1304 void AssignedVariablesAnalyzer::VisitVariableProxy(VariableProxy* expr) { | |
1305 // Nothing to do. | |
1306 ASSERT(av_.IsEmpty()); | |
1307 } | |
1308 | |
1309 | |
1310 void AssignedVariablesAnalyzer::VisitLiteral(Literal* expr) { | |
1311 // Nothing to do. | |
1312 ASSERT(av_.IsEmpty()); | |
1313 } | |
1314 | |
1315 | |
1316 void AssignedVariablesAnalyzer::VisitRegExpLiteral(RegExpLiteral* expr) { | |
1317 // Nothing to do. | |
1318 ASSERT(av_.IsEmpty()); | |
1319 } | |
1320 | |
1321 | |
1322 void AssignedVariablesAnalyzer::VisitObjectLiteral(ObjectLiteral* expr) { | |
1323 ASSERT(av_.IsEmpty()); | |
1324 BitVector result(av_.length()); | |
1325 for (int i = 0; i < expr->properties()->length(); i++) { | |
1326 Visit(expr->properties()->at(i)->value()); | |
1327 result.Union(av_); | |
1328 av_.Clear(); | |
1329 } | |
1330 av_.CopyFrom(result); | |
1331 } | |
1332 | |
1333 | |
1334 void AssignedVariablesAnalyzer::VisitArrayLiteral(ArrayLiteral* expr) { | |
1335 ASSERT(av_.IsEmpty()); | |
1336 BitVector result(av_.length()); | |
1337 for (int i = 0; i < expr->values()->length(); i++) { | |
1338 Visit(expr->values()->at(i)); | |
1339 result.Union(av_); | |
1340 av_.Clear(); | |
1341 } | |
1342 av_.CopyFrom(result); | |
1343 } | |
1344 | |
1345 | |
1346 void AssignedVariablesAnalyzer::VisitCatchExtensionObject( | |
1347 CatchExtensionObject* expr) { | |
1348 ASSERT(av_.IsEmpty()); | |
1349 Visit(expr->key()); | |
1350 ProcessExpression(expr->value()); | |
1351 } | |
1352 | |
1353 | |
1354 void AssignedVariablesAnalyzer::VisitAssignment(Assignment* expr) { | |
1355 ASSERT(av_.IsEmpty()); | |
1356 | |
1357 Visit(expr->target()); | |
1358 | |
1359 ProcessExpression(expr->value()); | |
1360 | |
1361 Variable* var = expr->target()->AsVariableProxy()->AsVariable(); | |
1362 if (var != NULL) RecordAssignedVar(var); | |
1363 | |
1364 // If we have a variable as a receiver in a property store, check if | |
1365 // we can mark it as trivial. | |
1366 if (expr->target()->AsProperty() != NULL) { | |
1367 MarkIfTrivial(expr->target()->AsProperty()->obj()); | |
1368 } | |
1369 } | |
1370 | |
1371 | |
1372 void AssignedVariablesAnalyzer::VisitThrow(Throw* expr) { | |
1373 ASSERT(av_.IsEmpty()); | |
1374 Visit(expr->exception()); | |
1375 } | |
1376 | |
1377 | |
1378 void AssignedVariablesAnalyzer::VisitProperty(Property* expr) { | |
1379 ASSERT(av_.IsEmpty()); | |
1380 Visit(expr->obj()); | |
1381 ProcessExpression(expr->key()); | |
1382 | |
1383 // In case we have a variable as a receiver, check if we can mark | |
1384 // it as trivial. | |
1385 MarkIfTrivial(expr->obj()); | |
1386 } | |
1387 | |
1388 | |
1389 void AssignedVariablesAnalyzer::VisitCall(Call* expr) { | |
1390 ASSERT(av_.IsEmpty()); | |
1391 Visit(expr->expression()); | |
1392 BitVector result(av_); | |
1393 for (int i = 0; i < expr->arguments()->length(); i++) { | |
1394 av_.Clear(); | |
1395 Visit(expr->arguments()->at(i)); | |
1396 result.Union(av_); | |
1397 } | |
1398 av_.CopyFrom(result); | |
1399 } | |
1400 | |
1401 | |
1402 void AssignedVariablesAnalyzer::VisitCallNew(CallNew* expr) { | |
1403 ASSERT(av_.IsEmpty()); | |
1404 Visit(expr->expression()); | |
1405 BitVector result(av_); | |
1406 for (int i = 0; i < expr->arguments()->length(); i++) { | |
1407 av_.Clear(); | |
1408 Visit(expr->arguments()->at(i)); | |
1409 result.Union(av_); | |
1410 } | |
1411 av_.CopyFrom(result); | |
1412 } | |
1413 | |
1414 | |
1415 void AssignedVariablesAnalyzer::VisitCallRuntime(CallRuntime* expr) { | |
1416 ASSERT(av_.IsEmpty()); | |
1417 BitVector result(av_); | |
1418 for (int i = 0; i < expr->arguments()->length(); i++) { | |
1419 av_.Clear(); | |
1420 Visit(expr->arguments()->at(i)); | |
1421 result.Union(av_); | |
1422 } | |
1423 av_.CopyFrom(result); | |
1424 } | |
1425 | |
1426 | |
1427 void AssignedVariablesAnalyzer::VisitUnaryOperation(UnaryOperation* expr) { | |
1428 ASSERT(av_.IsEmpty()); | |
1429 Visit(expr->expression()); | |
1430 } | |
1431 | |
1432 | |
1433 void AssignedVariablesAnalyzer::VisitCountOperation(CountOperation* expr) { | |
1434 ASSERT(av_.IsEmpty()); | |
1435 | |
1436 Visit(expr->expression()); | |
1437 | |
1438 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); | |
1439 if (var != NULL) RecordAssignedVar(var); | |
1440 } | |
1441 | |
1442 | |
1443 void AssignedVariablesAnalyzer::VisitBinaryOperation(BinaryOperation* expr) { | |
1444 ASSERT(av_.IsEmpty()); | |
1445 Visit(expr->left()); | |
1446 | |
1447 ProcessExpression(expr->right()); | |
1448 | |
1449 // In case we have a variable on the left side, check if we can mark | |
1450 // it as trivial. | |
1451 MarkIfTrivial(expr->left()); | |
1452 } | |
1453 | |
1454 | |
1455 void AssignedVariablesAnalyzer::VisitCompareOperation(CompareOperation* expr) { | |
1456 ASSERT(av_.IsEmpty()); | |
1457 Visit(expr->left()); | |
1458 | |
1459 ProcessExpression(expr->right()); | |
1460 | |
1461 // In case we have a variable on the left side, check if we can mark | |
1462 // it as trivial. | |
1463 MarkIfTrivial(expr->left()); | |
1464 } | |
1465 | |
1466 | |
1467 void AssignedVariablesAnalyzer::VisitThisFunction(ThisFunction* expr) { | |
1468 // Nothing to do. | |
1469 ASSERT(av_.IsEmpty()); | |
1470 } | |
1471 | |
1472 | |
1473 void AssignedVariablesAnalyzer::VisitDeclaration(Declaration* decl) { | |
1474 UNREACHABLE(); | |
1475 } | |
1476 | |
1477 | |
1478 #ifdef DEBUG | 1038 #ifdef DEBUG |
1479 | 1039 |
1480 // Print a textual representation of an instruction in a flow graph. Using | 1040 // Print a textual representation of an instruction in a flow graph. Using |
1481 // the AstVisitor is overkill because there is no recursion here. It is | 1041 // the AstVisitor is overkill because there is no recursion here. It is |
1482 // only used for printing in debug mode. | 1042 // only used for printing in debug mode. |
1483 class TextInstructionPrinter: public AstVisitor { | 1043 class TextInstructionPrinter: public AstVisitor { |
1484 public: | 1044 public: |
1485 TextInstructionPrinter() {} | 1045 TextInstructionPrinter() {} |
1486 | 1046 |
1487 private: | 1047 private: |
(...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1830 for (int i = postorder->length() - 1; i >= 0; i--) { | 1390 for (int i = postorder->length() - 1; i >= 0; i--) { |
1831 postorder->at(i)->PrintText(); | 1391 postorder->at(i)->PrintText(); |
1832 } | 1392 } |
1833 } | 1393 } |
1834 | 1394 |
1835 | 1395 |
1836 #endif // defined(DEBUG) | 1396 #endif // defined(DEBUG) |
1837 | 1397 |
1838 | 1398 |
1839 } } // namespace v8::internal | 1399 } } // namespace v8::internal |
OLD | NEW |