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

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

Issue 851002: Fix 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 // Add a (non-null) AstNode to the end of the graph fragment. 38 // Add a (non-null) AstNode to the end of the graph fragment.
38 ASSERT(instruction != NULL); 39 ASSERT(instruction != NULL);
39 if (exit()->IsExitNode()) return; 40 if (exit()->IsExitNode()) return;
40 if (!exit()->IsBlockNode()) AppendNode(new BlockNode()); 41 if (!exit()->IsBlockNode()) AppendNode(new BlockNode());
(...skipping 987 matching lines...) Expand 10 before | Expand all | Expand 10 after
1028 void LivenessAnalyzer::VisitCompareOperation(CompareOperation* expr) { 1029 void LivenessAnalyzer::VisitCompareOperation(CompareOperation* expr) {
1029 UNREACHABLE(); 1030 UNREACHABLE();
1030 } 1031 }
1031 1032
1032 1033
1033 void LivenessAnalyzer::VisitThisFunction(ThisFunction* expr) { 1034 void LivenessAnalyzer::VisitThisFunction(ThisFunction* expr) {
1034 UNREACHABLE(); 1035 UNREACHABLE();
1035 } 1036 }
1036 1037
1037 1038
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_arguments() &&
1128 (var->is_this() || !av_.Contains(BitIndex(var)))) {
1129 expr->AsVariableProxy()->set_is_trivial(true);
1130 }
1131 }
1132
1133
1134 void AssignedVariablesAnalyzer::ProcessExpression(Expression* expr) {
1135 BitVector saved_av(av_);
1136 av_.Clear();
1137 Visit(expr);
1138 av_.Union(saved_av);
1139 }
1140
1141 void AssignedVariablesAnalyzer::VisitBlock(Block* stmt) {
1142 VisitStatements(stmt->statements());
1143 }
1144
1145
1146 void AssignedVariablesAnalyzer::VisitExpressionStatement(
1147 ExpressionStatement* stmt) {
1148 ProcessExpression(stmt->expression());
1149 }
1150
1151
1152 void AssignedVariablesAnalyzer::VisitEmptyStatement(EmptyStatement* stmt) {
1153 // Do nothing.
1154 }
1155
1156
1157 void AssignedVariablesAnalyzer::VisitIfStatement(IfStatement* stmt) {
1158 ProcessExpression(stmt->condition());
1159 Visit(stmt->then_statement());
1160 Visit(stmt->else_statement());
1161 }
1162
1163
1164 void AssignedVariablesAnalyzer::VisitContinueStatement(
1165 ContinueStatement* stmt) {
1166 // Nothing to do.
1167 }
1168
1169
1170 void AssignedVariablesAnalyzer::VisitBreakStatement(BreakStatement* stmt) {
1171 // Nothing to do.
1172 }
1173
1174
1175 void AssignedVariablesAnalyzer::VisitReturnStatement(ReturnStatement* stmt) {
1176 ProcessExpression(stmt->expression());
1177 }
1178
1179
1180 void AssignedVariablesAnalyzer::VisitWithEnterStatement(
1181 WithEnterStatement* stmt) {
1182 ProcessExpression(stmt->expression());
1183 }
1184
1185
1186 void AssignedVariablesAnalyzer::VisitWithExitStatement(
1187 WithExitStatement* stmt) {
1188 // Nothing to do.
1189 }
1190
1191
1192 void AssignedVariablesAnalyzer::VisitSwitchStatement(SwitchStatement* stmt) {
1193 BitVector result(av_);
1194 av_.Clear();
1195 Visit(stmt->tag());
1196 result.Union(av_);
1197 for (int i = 0; i < stmt->cases()->length(); i++) {
1198 CaseClause* clause = stmt->cases()->at(i);
1199 if (!clause->is_default()) {
1200 av_.Clear();
1201 Visit(clause->label());
1202 result.Union(av_);
1203 }
1204 VisitStatements(clause->statements());
1205 }
1206 av_.Union(result);
1207 }
1208
1209
1210 void AssignedVariablesAnalyzer::VisitDoWhileStatement(DoWhileStatement* stmt) {
1211 ProcessExpression(stmt->cond());
1212 Visit(stmt->body());
1213 }
1214
1215
1216 void AssignedVariablesAnalyzer::VisitWhileStatement(WhileStatement* stmt) {
1217 ProcessExpression(stmt->cond());
1218 Visit(stmt->body());
1219 }
1220
1221
1222 void AssignedVariablesAnalyzer::VisitForStatement(ForStatement* stmt) {
1223 if (stmt->init() != NULL) Visit(stmt->init());
1224
1225 if (stmt->cond() != NULL) ProcessExpression(stmt->cond());
1226
1227 if (stmt->next() != NULL) Visit(stmt->next());
1228
1229 // Process loop body. After visiting the loop body av_ contains
1230 // the assigned variables of the loop body.
1231 BitVector saved_av(av_);
1232 av_.Clear();
1233 Visit(stmt->body());
1234
1235 Variable* var = FindSmiLoopVariable(stmt);
1236 if (var != NULL && !av_.Contains(BitIndex(var))) {
1237 stmt->set_loop_variable(var);
1238 }
1239
1240 av_.Union(saved_av);
1241 }
1242
1243
1244 void AssignedVariablesAnalyzer::VisitForInStatement(ForInStatement* stmt) {
1245 ProcessExpression(stmt->each());
1246 ProcessExpression(stmt->enumerable());
1247 Visit(stmt->body());
1248 }
1249
1250
1251 void AssignedVariablesAnalyzer::VisitTryCatchStatement(
1252 TryCatchStatement* stmt) {
1253 Visit(stmt->try_block());
1254 Visit(stmt->catch_block());
1255 }
1256
1257
1258 void AssignedVariablesAnalyzer::VisitTryFinallyStatement(
1259 TryFinallyStatement* stmt) {
1260 Visit(stmt->try_block());
1261 Visit(stmt->finally_block());
1262 }
1263
1264
1265 void AssignedVariablesAnalyzer::VisitDebuggerStatement(
1266 DebuggerStatement* stmt) {
1267 // Nothing to do.
1268 }
1269
1270
1271 void AssignedVariablesAnalyzer::VisitFunctionLiteral(FunctionLiteral* expr) {
1272 // Nothing to do.
1273 ASSERT(av_.IsEmpty());
1274 }
1275
1276
1277 void AssignedVariablesAnalyzer::VisitFunctionBoilerplateLiteral(
1278 FunctionBoilerplateLiteral* expr) {
1279 // Nothing to do.
1280 ASSERT(av_.IsEmpty());
1281 }
1282
1283
1284 void AssignedVariablesAnalyzer::VisitConditional(Conditional* expr) {
1285 ASSERT(av_.IsEmpty());
1286
1287 Visit(expr->condition());
1288
1289 BitVector result(av_);
1290 av_.Clear();
1291 Visit(expr->then_expression());
1292 result.Union(av_);
1293
1294 av_.Clear();
1295 Visit(expr->else_expression());
1296 av_.Union(result);
1297 }
1298
1299
1300 void AssignedVariablesAnalyzer::VisitSlot(Slot* expr) {
1301 UNREACHABLE();
1302 }
1303
1304
1305 void AssignedVariablesAnalyzer::VisitVariableProxy(VariableProxy* expr) {
1306 // Nothing to do.
1307 ASSERT(av_.IsEmpty());
1308 }
1309
1310
1311 void AssignedVariablesAnalyzer::VisitLiteral(Literal* expr) {
1312 // Nothing to do.
1313 ASSERT(av_.IsEmpty());
1314 }
1315
1316
1317 void AssignedVariablesAnalyzer::VisitRegExpLiteral(RegExpLiteral* expr) {
1318 // Nothing to do.
1319 ASSERT(av_.IsEmpty());
1320 }
1321
1322
1323 void AssignedVariablesAnalyzer::VisitObjectLiteral(ObjectLiteral* expr) {
1324 ASSERT(av_.IsEmpty());
1325 BitVector result(av_.length());
1326 for (int i = 0; i < expr->properties()->length(); i++) {
1327 Visit(expr->properties()->at(i)->value());
1328 result.Union(av_);
1329 av_.Clear();
1330 }
1331 av_.CopyFrom(result);
1332 }
1333
1334
1335 void AssignedVariablesAnalyzer::VisitArrayLiteral(ArrayLiteral* expr) {
1336 ASSERT(av_.IsEmpty());
1337 BitVector result(av_.length());
1338 for (int i = 0; i < expr->values()->length(); i++) {
1339 Visit(expr->values()->at(i));
1340 result.Union(av_);
1341 av_.Clear();
1342 }
1343 av_.CopyFrom(result);
1344 }
1345
1346
1347 void AssignedVariablesAnalyzer::VisitCatchExtensionObject(
1348 CatchExtensionObject* expr) {
1349 ASSERT(av_.IsEmpty());
1350 Visit(expr->key());
1351 ProcessExpression(expr->value());
1352 }
1353
1354
1355 void AssignedVariablesAnalyzer::VisitAssignment(Assignment* expr) {
1356 ASSERT(av_.IsEmpty());
1357
1358 Visit(expr->target());
1359
1360 ProcessExpression(expr->value());
1361
1362 Variable* var = expr->target()->AsVariableProxy()->AsVariable();
1363 if (var != NULL) RecordAssignedVar(var);
1364
1365 // If we have a variable as a receiver in a property store, check if
1366 // we can mark it as trivial.
1367 if (expr->target()->AsProperty() != NULL) {
1368 MarkIfTrivial(expr->target()->AsProperty()->obj());
1369 }
1370 }
1371
1372
1373 void AssignedVariablesAnalyzer::VisitThrow(Throw* expr) {
1374 ASSERT(av_.IsEmpty());
1375 Visit(expr->exception());
1376 }
1377
1378
1379 void AssignedVariablesAnalyzer::VisitProperty(Property* expr) {
1380 ASSERT(av_.IsEmpty());
1381 Visit(expr->obj());
1382 ProcessExpression(expr->key());
1383
1384 // In case we have a variable as a receiver, check if we can mark
1385 // it as trivial.
1386 MarkIfTrivial(expr->obj());
1387 }
1388
1389
1390 void AssignedVariablesAnalyzer::VisitCall(Call* expr) {
1391 ASSERT(av_.IsEmpty());
1392 Visit(expr->expression());
1393 BitVector result(av_);
1394 for (int i = 0; i < expr->arguments()->length(); i++) {
1395 av_.Clear();
1396 Visit(expr->arguments()->at(i));
1397 result.Union(av_);
1398 }
1399 av_.CopyFrom(result);
1400 }
1401
1402
1403 void AssignedVariablesAnalyzer::VisitCallNew(CallNew* expr) {
1404 ASSERT(av_.IsEmpty());
1405 Visit(expr->expression());
1406 BitVector result(av_);
1407 for (int i = 0; i < expr->arguments()->length(); i++) {
1408 av_.Clear();
1409 Visit(expr->arguments()->at(i));
1410 result.Union(av_);
1411 }
1412 av_.CopyFrom(result);
1413 }
1414
1415
1416 void AssignedVariablesAnalyzer::VisitCallRuntime(CallRuntime* expr) {
1417 ASSERT(av_.IsEmpty());
1418 BitVector result(av_);
1419 for (int i = 0; i < expr->arguments()->length(); i++) {
1420 av_.Clear();
1421 Visit(expr->arguments()->at(i));
1422 result.Union(av_);
1423 }
1424 av_.CopyFrom(result);
1425 }
1426
1427
1428 void AssignedVariablesAnalyzer::VisitUnaryOperation(UnaryOperation* expr) {
1429 ASSERT(av_.IsEmpty());
1430 Visit(expr->expression());
1431 }
1432
1433
1434 void AssignedVariablesAnalyzer::VisitCountOperation(CountOperation* expr) {
1435 ASSERT(av_.IsEmpty());
1436
1437 Visit(expr->expression());
1438
1439 Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
1440 if (var != NULL) RecordAssignedVar(var);
1441 }
1442
1443
1444 void AssignedVariablesAnalyzer::VisitBinaryOperation(BinaryOperation* expr) {
1445 ASSERT(av_.IsEmpty());
1446 Visit(expr->left());
1447
1448 ProcessExpression(expr->right());
1449
1450 // In case we have a variable on the left side, check if we can mark
1451 // it as trivial.
1452 MarkIfTrivial(expr->left());
1453 }
1454
1455
1456 void AssignedVariablesAnalyzer::VisitCompareOperation(CompareOperation* expr) {
1457 ASSERT(av_.IsEmpty());
1458 Visit(expr->left());
1459
1460 ProcessExpression(expr->right());
1461
1462 // In case we have a variable on the left side, check if we can mark
1463 // it as trivial.
1464 MarkIfTrivial(expr->left());
1465 }
1466
1467
1468 void AssignedVariablesAnalyzer::VisitThisFunction(ThisFunction* expr) {
1469 // Nothing to do.
1470 ASSERT(av_.IsEmpty());
1471 }
1472
1473
1474 void AssignedVariablesAnalyzer::VisitDeclaration(Declaration* decl) {
1475 UNREACHABLE();
1476 }
1477
1478
1038 #ifdef DEBUG 1479 #ifdef DEBUG
1039 1480
1040 // Print a textual representation of an instruction in a flow graph. Using 1481 // Print a textual representation of an instruction in a flow graph. Using
1041 // the AstVisitor is overkill because there is no recursion here. It is 1482 // the AstVisitor is overkill because there is no recursion here. It is
1042 // only used for printing in debug mode. 1483 // only used for printing in debug mode.
1043 class TextInstructionPrinter: public AstVisitor { 1484 class TextInstructionPrinter: public AstVisitor {
1044 public: 1485 public:
1045 TextInstructionPrinter() {} 1486 TextInstructionPrinter() {}
1046 1487
1047 private: 1488 private:
(...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after
1390 for (int i = postorder->length() - 1; i >= 0; i--) { 1831 for (int i = postorder->length() - 1; i >= 0; i--) {
1391 postorder->at(i)->PrintText(); 1832 postorder->at(i)->PrintText();
1392 } 1833 }
1393 } 1834 }
1394 1835
1395 1836
1396 #endif // defined(DEBUG) 1837 #endif // defined(DEBUG)
1397 1838
1398 1839
1399 } } // namespace v8::internal 1840 } } // 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