Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(288)

Side by Side Diff: src/data-flow.cc

Issue 669155: Add an assigned variables analysis.... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/data-flow.h ('k') | src/ia32/codegen-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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"
31 32
32 namespace v8 { 33 namespace v8 {
33 namespace internal { 34 namespace internal {
34 35
35 36
36 void FlowGraph::AppendInstruction(AstNode* instruction) { 37 void FlowGraph::AppendInstruction(AstNode* instruction) {
37 ASSERT(instruction != NULL); 38 ASSERT(instruction != NULL);
38 if (is_empty() || !exit()->IsBlockNode()) { 39 if (is_empty() || !exit()->IsBlockNode()) {
39 AppendNode(new BlockNode()); 40 AppendNode(new BlockNode());
40 } 41 }
(...skipping 1050 matching lines...) Expand 10 before | Expand all | Expand 10 after
1091 void LivenessAnalyzer::VisitCompareOperation(CompareOperation* expr) { 1092 void LivenessAnalyzer::VisitCompareOperation(CompareOperation* expr) {
1092 UNREACHABLE(); 1093 UNREACHABLE();
1093 } 1094 }
1094 1095
1095 1096
1096 void LivenessAnalyzer::VisitThisFunction(ThisFunction* expr) { 1097 void LivenessAnalyzer::VisitThisFunction(ThisFunction* expr) {
1097 UNREACHABLE(); 1098 UNREACHABLE();
1098 } 1099 }
1099 1100
1100 1101
1102 AssignedVariablesAnalyzer::AssignedVariablesAnalyzer(FunctionLiteral* fun)
1103 : fun_(fun),
1104 av_(fun->scope()->num_parameters() + fun->scope()->num_stack_slots()) {}
1105
1106
1107 void AssignedVariablesAnalyzer::Analyze() {
1108 ASSERT(av_.length() > 0);
1109 VisitStatements(fun_->body());
1110 }
1111
1112
1113 Variable* AssignedVariablesAnalyzer::FindSmiLoopVariable(ForStatement* stmt) {
1114 // The loop must have all necessary parts.
1115 if (stmt->init() == NULL || stmt->cond() == NULL || stmt->next() == NULL) {
1116 return NULL;
1117 }
1118 // The initialization statement has to be a simple assignment.
1119 Assignment* init = stmt->init()->StatementAsSimpleAssignment();
1120 if (init == NULL) return NULL;
1121
1122 // We only deal with local variables.
1123 Variable* loop_var = init->target()->AsVariableProxy()->AsVariable();
1124 if (!loop_var->IsStackAllocated()) return NULL;
1125
1126 // The initial value has to be a smi.
1127 Literal* init_lit = init->value()->AsLiteral();
1128 if (init_lit == NULL || !init_lit->handle()->IsSmi()) return NULL;
1129 int init_value = Smi::cast(*init_lit->handle())->value();
1130
1131 // The condition must be a compare of variable with <, <=, >, or >=.
1132 CompareOperation* cond = stmt->cond()->AsCompareOperation();
1133 if (cond == NULL) return NULL;
1134 if (cond->op() != Token::LT
1135 && cond->op() != Token::LTE
1136 && cond->op() != Token::GT
1137 && cond->op() != Token::GTE) return NULL;
1138
1139 // The lhs must be the same variable as in the init expression.
1140 if (cond->left()->AsVariableProxy()->AsVariable() != loop_var) return NULL;
1141
1142 // The rhs must be a smi.
1143 Literal* term_lit = cond->right()->AsLiteral();
1144 if (term_lit == NULL || !term_lit->handle()->IsSmi()) return NULL;
1145 int term_value = Smi::cast(*term_lit->handle())->value();
1146
1147 // The count operation updates the same variable as in the init expression.
1148 CountOperation* update = stmt->next()->StatementAsCountOperation();
1149 if (update == NULL) return NULL;
1150 if (update->expression()->AsVariableProxy()->AsVariable() != loop_var) {
1151 return NULL;
1152 }
1153
1154 // The direction of the count operation must agree with the start and the end
1155 // value. We currently do not allow the initial value to be the same as the
1156 // terminal value. This _would_ be ok as long as the loop body never executes
1157 // or executes exactly one time.
1158 if (init_value == term_value) return NULL;
1159 if (init_value < term_value && update->op() != Token::INC) return NULL;
1160 if (init_value > term_value && update->op() != Token::DEC) return NULL;
1161
1162 // Found a smi loop variable.
1163 return loop_var;
1164 }
1165
1166 int AssignedVariablesAnalyzer::BitIndex(Variable* var) {
1167 ASSERT(var != NULL);
1168 ASSERT(var->IsStackAllocated());
1169 Slot* slot = var->slot();
1170 if (slot->type() == Slot::PARAMETER) {
1171 return slot->index();
1172 } else {
1173 return fun_->scope()->num_parameters() + slot->index();
1174 }
1175 }
1176
1177
1178 void AssignedVariablesAnalyzer::RecordAssignedVar(Variable* var) {
1179 ASSERT(var != NULL);
1180 if (var->IsStackAllocated()) {
1181 av_.Add(BitIndex(var));
1182 }
1183 }
1184
1185
1186 void AssignedVariablesAnalyzer::MarkIfTrivial(Expression* expr) {
1187 Variable* var = expr->AsVariableProxy()->AsVariable();
1188 if (var != NULL &&
1189 var->IsStackAllocated() &&
1190 (var->is_this() || !av_.Contains(BitIndex(var)))) {
1191 expr->AsVariableProxy()->set_is_trivial(true);
1192 }
1193 }
1194
1195
1196 void AssignedVariablesAnalyzer::ProcessExpression(Expression* expr) {
1197 BitVector saved_av(av_);
1198 av_.Clear();
1199 Visit(expr);
1200 av_.Union(saved_av);
1201 }
1202
1203 void AssignedVariablesAnalyzer::VisitBlock(Block* stmt) {
1204 VisitStatements(stmt->statements());
1205 }
1206
1207
1208 void AssignedVariablesAnalyzer::VisitExpressionStatement(
1209 ExpressionStatement* stmt) {
1210 ProcessExpression(stmt->expression());
1211 }
1212
1213
1214 void AssignedVariablesAnalyzer::VisitEmptyStatement(EmptyStatement* stmt) {
1215 // Do nothing.
1216 }
1217
1218
1219 void AssignedVariablesAnalyzer::VisitIfStatement(IfStatement* stmt) {
1220 ProcessExpression(stmt->condition());
1221 Visit(stmt->then_statement());
1222 Visit(stmt->else_statement());
1223 }
1224
1225
1226 void AssignedVariablesAnalyzer::VisitContinueStatement(
1227 ContinueStatement* stmt) {
1228 // Nothing to do.
1229 }
1230
1231
1232 void AssignedVariablesAnalyzer::VisitBreakStatement(BreakStatement* stmt) {
1233 // Nothing to do.
1234 }
1235
1236
1237 void AssignedVariablesAnalyzer::VisitReturnStatement(ReturnStatement* stmt) {
1238 ProcessExpression(stmt->expression());
1239 }
1240
1241
1242 void AssignedVariablesAnalyzer::VisitWithEnterStatement(
1243 WithEnterStatement* stmt) {
1244 ProcessExpression(stmt->expression());
1245 }
1246
1247
1248 void AssignedVariablesAnalyzer::VisitWithExitStatement(
1249 WithExitStatement* stmt) {
1250 // Nothing to do.
1251 }
1252
1253
1254 void AssignedVariablesAnalyzer::VisitSwitchStatement(SwitchStatement* stmt) {
1255 BitVector result(av_);
1256 av_.Clear();
1257 Visit(stmt->tag());
1258 result.Union(av_);
1259 for (int i = 0; i < stmt->cases()->length(); i++) {
1260 CaseClause* clause = stmt->cases()->at(i);
1261 if (!clause->is_default()) {
1262 av_.Clear();
1263 Visit(clause->label());
1264 result.Union(av_);
1265 }
1266 VisitStatements(clause->statements());
1267 }
1268 av_.Union(result);
1269 }
1270
1271
1272 void AssignedVariablesAnalyzer::VisitDoWhileStatement(DoWhileStatement* stmt) {
1273 ProcessExpression(stmt->cond());
1274 Visit(stmt->body());
1275 }
1276
1277
1278 void AssignedVariablesAnalyzer::VisitWhileStatement(WhileStatement* stmt) {
1279 ProcessExpression(stmt->cond());
1280 Visit(stmt->body());
1281 }
1282
1283
1284 void AssignedVariablesAnalyzer::VisitForStatement(ForStatement* stmt) {
1285 if (stmt->init() != NULL) Visit(stmt->init());
1286
1287 if (stmt->cond() != NULL) ProcessExpression(stmt->cond());
1288
1289 if (stmt->next() != NULL) Visit(stmt->next());
1290
1291 // Process loop body. After visiting the loop body av_ contains
1292 // the assigned variables of the loop body.
1293 BitVector saved_av(av_);
1294 av_.Clear();
1295 Visit(stmt->body());
1296
1297 Variable* var = FindSmiLoopVariable(stmt);
1298 if (var != NULL && !av_.Contains(BitIndex(var))) {
1299 stmt->set_loop_variable(var);
1300 }
1301
1302 av_.Union(saved_av);
1303 }
1304
1305
1306 void AssignedVariablesAnalyzer::VisitForInStatement(ForInStatement* stmt) {
1307 ProcessExpression(stmt->each());
1308 ProcessExpression(stmt->enumerable());
1309 Visit(stmt->body());
1310 }
1311
1312
1313 void AssignedVariablesAnalyzer::VisitTryCatchStatement(
1314 TryCatchStatement* stmt) {
1315 Visit(stmt->try_block());
1316 Visit(stmt->catch_block());
1317 }
1318
1319
1320 void AssignedVariablesAnalyzer::VisitTryFinallyStatement(
1321 TryFinallyStatement* stmt) {
1322 Visit(stmt->try_block());
1323 Visit(stmt->finally_block());
1324 }
1325
1326
1327 void AssignedVariablesAnalyzer::VisitDebuggerStatement(
1328 DebuggerStatement* stmt) {
1329 // Nothing to do.
1330 }
1331
1332
1333 void AssignedVariablesAnalyzer::VisitFunctionLiteral(FunctionLiteral* expr) {
1334 // Nothing to do.
1335 ASSERT(av_.IsEmpty());
1336 }
1337
1338
1339 void AssignedVariablesAnalyzer::VisitFunctionBoilerplateLiteral(
1340 FunctionBoilerplateLiteral* expr) {
1341 // Nothing to do.
1342 ASSERT(av_.IsEmpty());
1343 }
1344
1345
1346 void AssignedVariablesAnalyzer::VisitConditional(Conditional* expr) {
1347 ASSERT(av_.IsEmpty());
1348
1349 Visit(expr->condition());
1350
1351 BitVector result(av_);
1352 av_.Clear();
1353 Visit(expr->then_expression());
1354 result.Union(av_);
1355
1356 av_.Clear();
1357 Visit(expr->else_expression());
1358 av_.Union(result);
1359 }
1360
1361
1362 void AssignedVariablesAnalyzer::VisitSlot(Slot* expr) {
1363 UNREACHABLE();
1364 }
1365
1366
1367 void AssignedVariablesAnalyzer::VisitVariableProxy(VariableProxy* expr) {
1368 // Nothing to do.
1369 ASSERT(av_.IsEmpty());
1370 }
1371
1372
1373 void AssignedVariablesAnalyzer::VisitLiteral(Literal* expr) {
1374 // Nothing to do.
1375 ASSERT(av_.IsEmpty());
1376 }
1377
1378
1379 void AssignedVariablesAnalyzer::VisitRegExpLiteral(RegExpLiteral* expr) {
1380 // Nothing to do.
1381 ASSERT(av_.IsEmpty());
1382 }
1383
1384
1385 void AssignedVariablesAnalyzer::VisitObjectLiteral(ObjectLiteral* expr) {
1386 ASSERT(av_.IsEmpty());
1387 BitVector result(av_.length());
1388 for (int i = 0; i < expr->properties()->length(); i++) {
1389 Visit(expr->properties()->at(i)->value());
1390 result.Union(av_);
1391 av_.Clear();
1392 }
1393 av_.CopyFrom(result);
1394 }
1395
1396
1397 void AssignedVariablesAnalyzer::VisitArrayLiteral(ArrayLiteral* expr) {
1398 ASSERT(av_.IsEmpty());
1399 BitVector result(av_.length());
1400 for (int i = 0; i < expr->values()->length(); i++) {
1401 Visit(expr->values()->at(i));
1402 result.Union(av_);
1403 av_.Clear();
1404 }
1405 av_.CopyFrom(result);
1406 }
1407
1408
1409 void AssignedVariablesAnalyzer::VisitCatchExtensionObject(
1410 CatchExtensionObject* expr) {
1411 ASSERT(av_.IsEmpty());
1412 Visit(expr->key());
1413 ProcessExpression(expr->value());
1414 }
1415
1416
1417 void AssignedVariablesAnalyzer::VisitAssignment(Assignment* expr) {
1418 ASSERT(av_.IsEmpty());
1419
1420 Visit(expr->target());
1421
1422 ProcessExpression(expr->value());
1423
1424 Variable* var = expr->target()->AsVariableProxy()->AsVariable();
1425 if (var != NULL) RecordAssignedVar(var);
1426
1427 // If we have a variable as a receiver in a property store, check if
1428 // we can mark it as trivial.
1429 if (expr->target()->AsProperty() != NULL) {
1430 MarkIfTrivial(expr->target()->AsProperty()->obj());
1431 }
1432 }
1433
1434
1435 void AssignedVariablesAnalyzer::VisitThrow(Throw* expr) {
1436 ASSERT(av_.IsEmpty());
1437 Visit(expr->exception());
1438 }
1439
1440
1441 void AssignedVariablesAnalyzer::VisitProperty(Property* expr) {
1442 ASSERT(av_.IsEmpty());
1443 Visit(expr->obj());
1444 ProcessExpression(expr->key());
1445
1446 // In case we have a variable as a receiver, check if we can mark
1447 // it as trivial.
1448 MarkIfTrivial(expr->obj());
1449 }
1450
1451
1452 void AssignedVariablesAnalyzer::VisitCall(Call* expr) {
1453 ASSERT(av_.IsEmpty());
1454 Visit(expr->expression());
1455 BitVector result(av_);
1456 for (int i = 0; i < expr->arguments()->length(); i++) {
1457 av_.Clear();
1458 Visit(expr->arguments()->at(i));
1459 result.Union(av_);
1460 }
1461 av_.CopyFrom(result);
1462 }
1463
1464
1465 void AssignedVariablesAnalyzer::VisitCallNew(CallNew* expr) {
1466 ASSERT(av_.IsEmpty());
1467 Visit(expr->expression());
1468 BitVector result(av_);
1469 for (int i = 0; i < expr->arguments()->length(); i++) {
1470 av_.Clear();
1471 Visit(expr->arguments()->at(i));
1472 result.Union(av_);
1473 }
1474 av_.CopyFrom(result);
1475 }
1476
1477
1478 void AssignedVariablesAnalyzer::VisitCallRuntime(CallRuntime* expr) {
1479 ASSERT(av_.IsEmpty());
1480 BitVector result(av_);
1481 for (int i = 0; i < expr->arguments()->length(); i++) {
1482 av_.Clear();
1483 Visit(expr->arguments()->at(i));
1484 result.Union(av_);
1485 }
1486 av_.CopyFrom(result);
1487 }
1488
1489
1490 void AssignedVariablesAnalyzer::VisitUnaryOperation(UnaryOperation* expr) {
1491 ASSERT(av_.IsEmpty());
1492 Visit(expr->expression());
1493 }
1494
1495
1496 void AssignedVariablesAnalyzer::VisitCountOperation(CountOperation* expr) {
1497 ASSERT(av_.IsEmpty());
1498
1499 Visit(expr->expression());
1500
1501 Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
1502 if (var != NULL) RecordAssignedVar(var);
1503 }
1504
1505
1506 void AssignedVariablesAnalyzer::VisitBinaryOperation(BinaryOperation* expr) {
1507 ASSERT(av_.IsEmpty());
1508 Visit(expr->left());
1509
1510 ProcessExpression(expr->right());
1511
1512 // In case we have a variable on the left side, check if we can mark
1513 // it as trivial.
1514 MarkIfTrivial(expr->left());
1515 }
1516
1517
1518 void AssignedVariablesAnalyzer::VisitCompareOperation(CompareOperation* expr) {
1519 ASSERT(av_.IsEmpty());
1520 Visit(expr->left());
1521
1522 ProcessExpression(expr->right());
1523
1524 // In case we have a variable on the left side, check if we can mark
1525 // it as trivial.
1526 MarkIfTrivial(expr->left());
1527 }
1528
1529
1530 void AssignedVariablesAnalyzer::VisitThisFunction(ThisFunction* expr) {
1531 // Nothing to do.
1532 ASSERT(av_.IsEmpty());
1533 }
1534
1535
1536 void AssignedVariablesAnalyzer::VisitDeclaration(Declaration* decl) {
1537 UNREACHABLE();
1538 }
1539
1540
1101 #ifdef DEBUG 1541 #ifdef DEBUG
1102 1542
1103 // Print a textual representation of an instruction in a flow graph. Using 1543 // Print a textual representation of an instruction in a flow graph. Using
1104 // the AstVisitor is overkill because there is no recursion here. It is 1544 // the AstVisitor is overkill because there is no recursion here. It is
1105 // only used for printing in debug mode. 1545 // only used for printing in debug mode.
1106 class TextInstructionPrinter: public AstVisitor { 1546 class TextInstructionPrinter: public AstVisitor {
1107 public: 1547 public:
1108 TextInstructionPrinter() {} 1548 TextInstructionPrinter() {}
1109 1549
1110 private: 1550 private:
(...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after
1458 for (int i = postorder->length() - 1; i >= 0; i--) { 1898 for (int i = postorder->length() - 1; i >= 0; i--) {
1459 postorder->at(i)->PrintText(); 1899 postorder->at(i)->PrintText();
1460 } 1900 }
1461 } 1901 }
1462 1902
1463 1903
1464 #endif // defined(DEBUG) 1904 #endif // defined(DEBUG)
1465 1905
1466 1906
1467 } } // namespace v8::internal 1907 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/data-flow.h ('k') | src/ia32/codegen-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698