OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 22 matching lines...) Expand all Loading... |
33 namespace v8 { | 33 namespace v8 { |
34 namespace internal { | 34 namespace internal { |
35 | 35 |
36 | 36 |
37 AstTyper::AstTyper(CompilationInfo* info) | 37 AstTyper::AstTyper(CompilationInfo* info) |
38 : info_(info), | 38 : info_(info), |
39 oracle_( | 39 oracle_( |
40 Handle<Code>(info->closure()->shared()->code()), | 40 Handle<Code>(info->closure()->shared()->code()), |
41 Handle<Context>(info->closure()->context()->native_context()), | 41 Handle<Context>(info->closure()->context()->native_context()), |
42 info->isolate(), | 42 info->isolate(), |
43 info->zone()) { | 43 info->zone()), |
| 44 store_(info->zone()) { |
44 InitializeAstVisitor(); | 45 InitializeAstVisitor(); |
45 } | 46 } |
46 | 47 |
47 | 48 |
48 #define RECURSE(call) \ | 49 #define RECURSE(call) \ |
49 do { \ | 50 do { \ |
50 ASSERT(!visitor->HasStackOverflow()); \ | 51 ASSERT(!visitor->HasStackOverflow()); \ |
51 call; \ | 52 call; \ |
52 if (visitor->HasStackOverflow()) return; \ | 53 if (visitor->HasStackOverflow()) return; \ |
53 } while (false) | 54 } while (false) |
(...skipping 18 matching lines...) Expand all Loading... |
72 ASSERT(!HasStackOverflow()); \ | 73 ASSERT(!HasStackOverflow()); \ |
73 call; \ | 74 call; \ |
74 if (HasStackOverflow()) return; \ | 75 if (HasStackOverflow()) return; \ |
75 } while (false) | 76 } while (false) |
76 | 77 |
77 | 78 |
78 void AstTyper::VisitStatements(ZoneList<Statement*>* stmts) { | 79 void AstTyper::VisitStatements(ZoneList<Statement*>* stmts) { |
79 for (int i = 0; i < stmts->length(); ++i) { | 80 for (int i = 0; i < stmts->length(); ++i) { |
80 Statement* stmt = stmts->at(i); | 81 Statement* stmt = stmts->at(i); |
81 RECURSE(Visit(stmt)); | 82 RECURSE(Visit(stmt)); |
| 83 if (stmt->IsJump()) break; |
82 } | 84 } |
83 } | 85 } |
84 | 86 |
85 | 87 |
86 void AstTyper::VisitBlock(Block* stmt) { | 88 void AstTyper::VisitBlock(Block* stmt) { |
87 RECURSE(VisitStatements(stmt->statements())); | 89 RECURSE(VisitStatements(stmt->statements())); |
| 90 if (stmt->labels() != NULL) { |
| 91 store_.Forget(); // Control may transfer here via 'break l'. |
| 92 } |
88 } | 93 } |
89 | 94 |
90 | 95 |
91 void AstTyper::VisitExpressionStatement(ExpressionStatement* stmt) { | 96 void AstTyper::VisitExpressionStatement(ExpressionStatement* stmt) { |
92 RECURSE(Visit(stmt->expression())); | 97 RECURSE(Visit(stmt->expression())); |
93 } | 98 } |
94 | 99 |
95 | 100 |
96 void AstTyper::VisitEmptyStatement(EmptyStatement* stmt) { | 101 void AstTyper::VisitEmptyStatement(EmptyStatement* stmt) { |
97 } | 102 } |
98 | 103 |
99 | 104 |
100 void AstTyper::VisitIfStatement(IfStatement* stmt) { | 105 void AstTyper::VisitIfStatement(IfStatement* stmt) { |
101 RECURSE(Visit(stmt->condition())); | 106 // Collect type feedback. |
102 RECURSE(Visit(stmt->then_statement())); | |
103 RECURSE(Visit(stmt->else_statement())); | |
104 | |
105 if (!stmt->condition()->ToBooleanIsTrue() && | 107 if (!stmt->condition()->ToBooleanIsTrue() && |
106 !stmt->condition()->ToBooleanIsFalse()) { | 108 !stmt->condition()->ToBooleanIsFalse()) { |
107 stmt->condition()->RecordToBooleanTypeFeedback(oracle()); | 109 stmt->condition()->RecordToBooleanTypeFeedback(oracle()); |
108 } | 110 } |
| 111 |
| 112 RECURSE(Visit(stmt->condition())); |
| 113 Effects then_effects = EnterEffects(); |
| 114 RECURSE(Visit(stmt->then_statement())); |
| 115 ExitEffects(); |
| 116 Effects else_effects = EnterEffects(); |
| 117 RECURSE(Visit(stmt->else_statement())); |
| 118 ExitEffects(); |
| 119 then_effects.Alt(else_effects); |
| 120 store_.Seq(then_effects); |
109 } | 121 } |
110 | 122 |
111 | 123 |
112 void AstTyper::VisitContinueStatement(ContinueStatement* stmt) { | 124 void AstTyper::VisitContinueStatement(ContinueStatement* stmt) { |
| 125 // TODO(rossberg): is it worth having a non-termination effect? |
113 } | 126 } |
114 | 127 |
115 | 128 |
116 void AstTyper::VisitBreakStatement(BreakStatement* stmt) { | 129 void AstTyper::VisitBreakStatement(BreakStatement* stmt) { |
| 130 // TODO(rossberg): is it worth having a non-termination effect? |
117 } | 131 } |
118 | 132 |
119 | 133 |
120 void AstTyper::VisitReturnStatement(ReturnStatement* stmt) { | 134 void AstTyper::VisitReturnStatement(ReturnStatement* stmt) { |
121 RECURSE(Visit(stmt->expression())); | 135 // Collect type feedback. |
122 | |
123 // TODO(rossberg): we only need this for inlining into test contexts... | 136 // TODO(rossberg): we only need this for inlining into test contexts... |
124 stmt->expression()->RecordToBooleanTypeFeedback(oracle()); | 137 stmt->expression()->RecordToBooleanTypeFeedback(oracle()); |
| 138 |
| 139 RECURSE(Visit(stmt->expression())); |
| 140 // TODO(rossberg): is it worth having a non-termination effect? |
125 } | 141 } |
126 | 142 |
127 | 143 |
128 void AstTyper::VisitWithStatement(WithStatement* stmt) { | 144 void AstTyper::VisitWithStatement(WithStatement* stmt) { |
129 RECURSE(stmt->expression()); | 145 RECURSE(stmt->expression()); |
130 RECURSE(stmt->statement()); | 146 RECURSE(stmt->statement()); |
131 } | 147 } |
132 | 148 |
133 | 149 |
134 void AstTyper::VisitSwitchStatement(SwitchStatement* stmt) { | 150 void AstTyper::VisitSwitchStatement(SwitchStatement* stmt) { |
135 RECURSE(Visit(stmt->tag())); | 151 RECURSE(Visit(stmt->tag())); |
| 152 |
136 ZoneList<CaseClause*>* clauses = stmt->cases(); | 153 ZoneList<CaseClause*>* clauses = stmt->cases(); |
137 SwitchStatement::SwitchType switch_type = stmt->switch_type(); | 154 SwitchStatement::SwitchType switch_type = stmt->switch_type(); |
| 155 Effects local_effects(zone()); |
| 156 bool complex_effects = false; // True for label effects or fall-through. |
| 157 |
138 for (int i = 0; i < clauses->length(); ++i) { | 158 for (int i = 0; i < clauses->length(); ++i) { |
139 CaseClause* clause = clauses->at(i); | 159 CaseClause* clause = clauses->at(i); |
| 160 Effects clause_effects = EnterEffects(); |
| 161 |
140 if (!clause->is_default()) { | 162 if (!clause->is_default()) { |
141 Expression* label = clause->label(); | 163 Expression* label = clause->label(); |
142 RECURSE(Visit(label)); | |
143 | |
144 SwitchStatement::SwitchType label_switch_type = | 164 SwitchStatement::SwitchType label_switch_type = |
145 label->IsSmiLiteral() ? SwitchStatement::SMI_SWITCH : | 165 label->IsSmiLiteral() ? SwitchStatement::SMI_SWITCH : |
146 label->IsStringLiteral() ? SwitchStatement::STRING_SWITCH : | 166 label->IsStringLiteral() ? SwitchStatement::STRING_SWITCH : |
147 SwitchStatement::GENERIC_SWITCH; | 167 SwitchStatement::GENERIC_SWITCH; |
148 if (switch_type == SwitchStatement::UNKNOWN_SWITCH) | 168 if (switch_type == SwitchStatement::UNKNOWN_SWITCH) |
149 switch_type = label_switch_type; | 169 switch_type = label_switch_type; |
150 else if (switch_type != label_switch_type) | 170 else if (switch_type != label_switch_type) |
151 switch_type = SwitchStatement::GENERIC_SWITCH; | 171 switch_type = SwitchStatement::GENERIC_SWITCH; |
| 172 |
| 173 RECURSE(Visit(label)); |
| 174 if (!clause_effects.IsEmpty()) complex_effects = true; |
152 } | 175 } |
153 RECURSE(VisitStatements(clause->statements())); | 176 |
| 177 ZoneList<Statement*>* stmts = clause->statements(); |
| 178 RECURSE(VisitStatements(stmts)); |
| 179 ExitEffects(); |
| 180 if (stmts->is_empty() || stmts->last()->IsJump()) { |
| 181 local_effects.Alt(clause_effects); |
| 182 } else { |
| 183 complex_effects = true; |
| 184 } |
154 } | 185 } |
| 186 |
| 187 if (complex_effects) { |
| 188 store_.Forget(); // Reached this in unknown state. |
| 189 } else { |
| 190 store_.Seq(local_effects); |
| 191 } |
| 192 |
155 if (switch_type == SwitchStatement::UNKNOWN_SWITCH) | 193 if (switch_type == SwitchStatement::UNKNOWN_SWITCH) |
156 switch_type = SwitchStatement::GENERIC_SWITCH; | 194 switch_type = SwitchStatement::GENERIC_SWITCH; |
157 stmt->set_switch_type(switch_type); | 195 stmt->set_switch_type(switch_type); |
158 | 196 |
| 197 // Collect type feedback. |
159 // TODO(rossberg): can we eliminate this special case and extra loop? | 198 // TODO(rossberg): can we eliminate this special case and extra loop? |
160 if (switch_type == SwitchStatement::SMI_SWITCH) { | 199 if (switch_type == SwitchStatement::SMI_SWITCH) { |
161 for (int i = 0; i < clauses->length(); ++i) { | 200 for (int i = 0; i < clauses->length(); ++i) { |
162 CaseClause* clause = clauses->at(i); | 201 CaseClause* clause = clauses->at(i); |
163 if (!clause->is_default()) | 202 if (!clause->is_default()) |
164 clause->RecordTypeFeedback(oracle()); | 203 clause->RecordTypeFeedback(oracle()); |
165 } | 204 } |
166 } | 205 } |
167 } | 206 } |
168 | 207 |
169 | 208 |
170 void AstTyper::VisitDoWhileStatement(DoWhileStatement* stmt) { | 209 void AstTyper::VisitDoWhileStatement(DoWhileStatement* stmt) { |
171 RECURSE(Visit(stmt->body())); | 210 // Collect type feedback. |
172 RECURSE(Visit(stmt->cond())); | |
173 | |
174 if (!stmt->cond()->ToBooleanIsTrue()) { | 211 if (!stmt->cond()->ToBooleanIsTrue()) { |
175 stmt->cond()->RecordToBooleanTypeFeedback(oracle()); | 212 stmt->cond()->RecordToBooleanTypeFeedback(oracle()); |
176 } | 213 } |
| 214 |
| 215 // TODO(rossberg): refine the unconditional Forget (here and elsewhere) by |
| 216 // computing the set of variables assigned in only some of the origins of the |
| 217 // control transfer (such as the loop body here). |
| 218 store_.Forget(); // Control may transfer here via looping or 'continue'. |
| 219 RECURSE(Visit(stmt->body())); |
| 220 RECURSE(Visit(stmt->cond())); |
| 221 store_.Forget(); // Control may transfer here via 'break'. |
177 } | 222 } |
178 | 223 |
179 | 224 |
180 void AstTyper::VisitWhileStatement(WhileStatement* stmt) { | 225 void AstTyper::VisitWhileStatement(WhileStatement* stmt) { |
181 RECURSE(Visit(stmt->cond())); | 226 // Collect type feedback. |
182 RECURSE(Visit(stmt->body())); | |
183 | |
184 if (!stmt->cond()->ToBooleanIsTrue()) { | 227 if (!stmt->cond()->ToBooleanIsTrue()) { |
185 stmt->cond()->RecordToBooleanTypeFeedback(oracle()); | 228 stmt->cond()->RecordToBooleanTypeFeedback(oracle()); |
186 } | 229 } |
| 230 |
| 231 store_.Forget(); // Control may transfer here via looping or 'continue'. |
| 232 RECURSE(Visit(stmt->cond())); |
| 233 RECURSE(Visit(stmt->body())); |
| 234 store_.Forget(); // Control may transfer here via termination or 'break'. |
187 } | 235 } |
188 | 236 |
189 | 237 |
190 void AstTyper::VisitForStatement(ForStatement* stmt) { | 238 void AstTyper::VisitForStatement(ForStatement* stmt) { |
191 if (stmt->init() != NULL) { | 239 if (stmt->init() != NULL) { |
192 RECURSE(Visit(stmt->init())); | 240 RECURSE(Visit(stmt->init())); |
193 } | 241 } |
| 242 store_.Forget(); // Control may transfer here via looping. |
194 if (stmt->cond() != NULL) { | 243 if (stmt->cond() != NULL) { |
| 244 // Collect type feedback. |
| 245 stmt->cond()->RecordToBooleanTypeFeedback(oracle()); |
| 246 |
195 RECURSE(Visit(stmt->cond())); | 247 RECURSE(Visit(stmt->cond())); |
196 | |
197 stmt->cond()->RecordToBooleanTypeFeedback(oracle()); | |
198 } | 248 } |
199 RECURSE(Visit(stmt->body())); | 249 RECURSE(Visit(stmt->body())); |
| 250 store_.Forget(); // Control may transfer here via 'continue'. |
200 if (stmt->next() != NULL) { | 251 if (stmt->next() != NULL) { |
201 RECURSE(Visit(stmt->next())); | 252 RECURSE(Visit(stmt->next())); |
202 } | 253 } |
| 254 store_.Forget(); // Control may transfer here via termination or 'break'. |
203 } | 255 } |
204 | 256 |
205 | 257 |
206 void AstTyper::VisitForInStatement(ForInStatement* stmt) { | 258 void AstTyper::VisitForInStatement(ForInStatement* stmt) { |
| 259 // Collect type feedback. |
| 260 stmt->RecordTypeFeedback(oracle()); |
| 261 |
207 RECURSE(Visit(stmt->enumerable())); | 262 RECURSE(Visit(stmt->enumerable())); |
| 263 store_.Forget(); // Control may transfer here via looping or 'continue'. |
208 RECURSE(Visit(stmt->body())); | 264 RECURSE(Visit(stmt->body())); |
209 | 265 store_.Forget(); // Control may transfer here via 'break'. |
210 stmt->RecordTypeFeedback(oracle()); | |
211 } | 266 } |
212 | 267 |
213 | 268 |
214 void AstTyper::VisitForOfStatement(ForOfStatement* stmt) { | 269 void AstTyper::VisitForOfStatement(ForOfStatement* stmt) { |
215 RECURSE(Visit(stmt->iterable())); | 270 RECURSE(Visit(stmt->iterable())); |
| 271 store_.Forget(); // Control may transfer here via looping or 'continue'. |
216 RECURSE(Visit(stmt->body())); | 272 RECURSE(Visit(stmt->body())); |
| 273 store_.Forget(); // Control may transfer here via 'break'. |
217 } | 274 } |
218 | 275 |
219 | 276 |
220 void AstTyper::VisitTryCatchStatement(TryCatchStatement* stmt) { | 277 void AstTyper::VisitTryCatchStatement(TryCatchStatement* stmt) { |
| 278 Effects try_effects = EnterEffects(); |
221 RECURSE(Visit(stmt->try_block())); | 279 RECURSE(Visit(stmt->try_block())); |
| 280 ExitEffects(); |
| 281 Effects catch_effects = EnterEffects(); |
| 282 store_.Forget(); // Control may transfer here via 'throw'. |
222 RECURSE(Visit(stmt->catch_block())); | 283 RECURSE(Visit(stmt->catch_block())); |
| 284 ExitEffects(); |
| 285 try_effects.Alt(catch_effects); |
| 286 store_.Seq(try_effects); |
| 287 // At this point, only variables that were reassigned in the catch block are |
| 288 // still remembered. |
223 } | 289 } |
224 | 290 |
225 | 291 |
226 void AstTyper::VisitTryFinallyStatement(TryFinallyStatement* stmt) { | 292 void AstTyper::VisitTryFinallyStatement(TryFinallyStatement* stmt) { |
227 RECURSE(Visit(stmt->try_block())); | 293 RECURSE(Visit(stmt->try_block())); |
| 294 store_.Forget(); // Control may transfer here via 'throw'. |
228 RECURSE(Visit(stmt->finally_block())); | 295 RECURSE(Visit(stmt->finally_block())); |
229 } | 296 } |
230 | 297 |
231 | 298 |
232 void AstTyper::VisitDebuggerStatement(DebuggerStatement* stmt) { | 299 void AstTyper::VisitDebuggerStatement(DebuggerStatement* stmt) { |
| 300 store_.Forget(); // May do whatever. |
233 } | 301 } |
234 | 302 |
235 | 303 |
236 void AstTyper::VisitFunctionLiteral(FunctionLiteral* expr) { | 304 void AstTyper::VisitFunctionLiteral(FunctionLiteral* expr) { |
237 } | 305 } |
238 | 306 |
239 | 307 |
240 void AstTyper::VisitSharedFunctionInfoLiteral(SharedFunctionInfoLiteral* expr) { | 308 void AstTyper::VisitSharedFunctionInfoLiteral(SharedFunctionInfoLiteral* expr) { |
241 } | 309 } |
242 | 310 |
243 | 311 |
244 void AstTyper::VisitConditional(Conditional* expr) { | 312 void AstTyper::VisitConditional(Conditional* expr) { |
| 313 // Collect type feedback. |
| 314 expr->condition()->RecordToBooleanTypeFeedback(oracle()); |
| 315 |
245 RECURSE(Visit(expr->condition())); | 316 RECURSE(Visit(expr->condition())); |
| 317 Effects then_effects = EnterEffects(); |
246 RECURSE(Visit(expr->then_expression())); | 318 RECURSE(Visit(expr->then_expression())); |
| 319 ExitEffects(); |
| 320 Effects else_effects = EnterEffects(); |
247 RECURSE(Visit(expr->else_expression())); | 321 RECURSE(Visit(expr->else_expression())); |
248 | 322 ExitEffects(); |
249 expr->condition()->RecordToBooleanTypeFeedback(oracle()); | 323 then_effects.Alt(else_effects); |
| 324 store_.Seq(then_effects); |
250 | 325 |
251 NarrowType(expr, Bounds::Either( | 326 NarrowType(expr, Bounds::Either( |
252 expr->then_expression()->bounds(), | 327 expr->then_expression()->bounds(), |
253 expr->else_expression()->bounds(), isolate_)); | 328 expr->else_expression()->bounds(), isolate_)); |
254 } | 329 } |
255 | 330 |
256 | 331 |
257 void AstTyper::VisitVariableProxy(VariableProxy* expr) { | 332 void AstTyper::VisitVariableProxy(VariableProxy* expr) { |
258 // TODO(rossberg): typing of variables | 333 Variable* var = expr->var(); |
| 334 if (var->IsStackAllocated()) { |
| 335 NarrowType(expr, store_.LookupBounds(variable_index(var))); |
| 336 } |
259 } | 337 } |
260 | 338 |
261 | 339 |
262 void AstTyper::VisitLiteral(Literal* expr) { | 340 void AstTyper::VisitLiteral(Literal* expr) { |
263 Type* type = Type::Constant(expr->value(), isolate_); | 341 Type* type = Type::Constant(expr->value(), isolate_); |
264 NarrowType(expr, Bounds(type, isolate_)); | 342 NarrowType(expr, Bounds(type, isolate_)); |
265 } | 343 } |
266 | 344 |
267 | 345 |
268 void AstTyper::VisitRegExpLiteral(RegExpLiteral* expr) { | 346 void AstTyper::VisitRegExpLiteral(RegExpLiteral* expr) { |
269 NarrowType(expr, Bounds(Type::RegExp(), isolate_)); | 347 NarrowType(expr, Bounds(Type::RegExp(), isolate_)); |
270 } | 348 } |
271 | 349 |
272 | 350 |
273 void AstTyper::VisitObjectLiteral(ObjectLiteral* expr) { | 351 void AstTyper::VisitObjectLiteral(ObjectLiteral* expr) { |
274 ZoneList<ObjectLiteral::Property*>* properties = expr->properties(); | 352 ZoneList<ObjectLiteral::Property*>* properties = expr->properties(); |
275 for (int i = 0; i < properties->length(); ++i) { | 353 for (int i = 0; i < properties->length(); ++i) { |
276 ObjectLiteral::Property* prop = properties->at(i); | 354 ObjectLiteral::Property* prop = properties->at(i); |
277 RECURSE(Visit(prop->value())); | |
278 | 355 |
| 356 // Collect type feedback. |
279 if ((prop->kind() == ObjectLiteral::Property::MATERIALIZED_LITERAL && | 357 if ((prop->kind() == ObjectLiteral::Property::MATERIALIZED_LITERAL && |
280 !CompileTimeValue::IsCompileTimeValue(prop->value())) || | 358 !CompileTimeValue::IsCompileTimeValue(prop->value())) || |
281 prop->kind() == ObjectLiteral::Property::COMPUTED) { | 359 prop->kind() == ObjectLiteral::Property::COMPUTED) { |
282 if (prop->key()->value()->IsInternalizedString() && prop->emit_store()) { | 360 if (prop->key()->value()->IsInternalizedString() && prop->emit_store()) { |
283 prop->RecordTypeFeedback(oracle()); | 361 prop->RecordTypeFeedback(oracle()); |
284 } | 362 } |
285 } | 363 } |
| 364 |
| 365 RECURSE(Visit(prop->value())); |
286 } | 366 } |
287 | 367 |
288 NarrowType(expr, Bounds(Type::Object(), isolate_)); | 368 NarrowType(expr, Bounds(Type::Object(), isolate_)); |
289 } | 369 } |
290 | 370 |
291 | 371 |
292 void AstTyper::VisitArrayLiteral(ArrayLiteral* expr) { | 372 void AstTyper::VisitArrayLiteral(ArrayLiteral* expr) { |
293 ZoneList<Expression*>* values = expr->values(); | 373 ZoneList<Expression*>* values = expr->values(); |
294 for (int i = 0; i < values->length(); ++i) { | 374 for (int i = 0; i < values->length(); ++i) { |
295 Expression* value = values->at(i); | 375 Expression* value = values->at(i); |
296 RECURSE(Visit(value)); | 376 RECURSE(Visit(value)); |
297 } | 377 } |
298 | 378 |
299 NarrowType(expr, Bounds(Type::Array(), isolate_)); | 379 NarrowType(expr, Bounds(Type::Array(), isolate_)); |
300 } | 380 } |
301 | 381 |
302 | 382 |
303 void AstTyper::VisitAssignment(Assignment* expr) { | 383 void AstTyper::VisitAssignment(Assignment* expr) { |
304 // TODO(rossberg): Can we clean this up? | 384 // TODO(rossberg): Can we clean this up? |
305 if (expr->is_compound()) { | 385 if (expr->is_compound()) { |
306 RECURSE(Visit(expr->binary_operation())); | 386 // Collect type feedback. |
307 | |
308 Expression* target = expr->target(); | 387 Expression* target = expr->target(); |
309 Property* prop = target->AsProperty(); | 388 Property* prop = target->AsProperty(); |
310 if (prop != NULL) { | 389 if (prop != NULL) { |
311 prop->RecordTypeFeedback(oracle(), zone()); | 390 prop->RecordTypeFeedback(oracle(), zone()); |
312 if (!prop->key()->IsPropertyName()) { // i.e., keyed | 391 if (!prop->key()->IsPropertyName()) { // i.e., keyed |
313 expr->RecordTypeFeedback(oracle(), zone()); | 392 expr->RecordTypeFeedback(oracle(), zone()); |
314 } | 393 } |
315 } | 394 } |
316 | 395 |
| 396 RECURSE(Visit(expr->binary_operation())); |
| 397 |
317 NarrowType(expr, expr->binary_operation()->bounds()); | 398 NarrowType(expr, expr->binary_operation()->bounds()); |
318 } else { | 399 } else { |
| 400 // Collect type feedback. |
| 401 if (expr->target()->IsProperty()) { |
| 402 expr->RecordTypeFeedback(oracle(), zone()); |
| 403 } |
| 404 |
319 RECURSE(Visit(expr->target())); | 405 RECURSE(Visit(expr->target())); |
320 RECURSE(Visit(expr->value())); | 406 RECURSE(Visit(expr->value())); |
321 | 407 |
322 if (expr->target()->AsProperty()) { | |
323 expr->RecordTypeFeedback(oracle(), zone()); | |
324 } | |
325 | |
326 NarrowType(expr, expr->value()->bounds()); | 408 NarrowType(expr, expr->value()->bounds()); |
327 } | 409 } |
328 // TODO(rossberg): handle target variables | 410 |
| 411 VariableProxy* proxy = expr->target()->AsVariableProxy(); |
| 412 if (proxy != NULL && proxy->var()->IsStackAllocated()) { |
| 413 store_.Seq(variable_index(proxy->var()), Effect(expr->bounds())); |
| 414 } |
329 } | 415 } |
330 | 416 |
331 | 417 |
332 void AstTyper::VisitYield(Yield* expr) { | 418 void AstTyper::VisitYield(Yield* expr) { |
333 RECURSE(Visit(expr->generator_object())); | 419 RECURSE(Visit(expr->generator_object())); |
334 RECURSE(Visit(expr->expression())); | 420 RECURSE(Visit(expr->expression())); |
335 | 421 |
336 // We don't know anything about the type. | 422 // We don't know anything about the result type. |
337 } | 423 } |
338 | 424 |
339 | 425 |
340 void AstTyper::VisitThrow(Throw* expr) { | 426 void AstTyper::VisitThrow(Throw* expr) { |
341 RECURSE(Visit(expr->exception())); | 427 RECURSE(Visit(expr->exception())); |
| 428 // TODO(rossberg): is it worth having a non-termination effect? |
342 | 429 |
343 NarrowType(expr, Bounds(Type::None(), isolate_)); | 430 NarrowType(expr, Bounds(Type::None(), isolate_)); |
344 } | 431 } |
345 | 432 |
346 | 433 |
347 void AstTyper::VisitProperty(Property* expr) { | 434 void AstTyper::VisitProperty(Property* expr) { |
| 435 // Collect type feedback. |
| 436 expr->RecordTypeFeedback(oracle(), zone()); |
| 437 |
348 RECURSE(Visit(expr->obj())); | 438 RECURSE(Visit(expr->obj())); |
349 RECURSE(Visit(expr->key())); | 439 RECURSE(Visit(expr->key())); |
350 | 440 |
351 expr->RecordTypeFeedback(oracle(), zone()); | 441 // We don't know anything about the result type. |
352 | |
353 // We don't know anything about the type. | |
354 } | 442 } |
355 | 443 |
356 | 444 |
357 void AstTyper::VisitCall(Call* expr) { | 445 void AstTyper::VisitCall(Call* expr) { |
358 RECURSE(Visit(expr->expression())); | 446 // Collect type feedback. |
359 ZoneList<Expression*>* args = expr->arguments(); | |
360 for (int i = 0; i < args->length(); ++i) { | |
361 Expression* arg = args->at(i); | |
362 RECURSE(Visit(arg)); | |
363 } | |
364 | |
365 Expression* callee = expr->expression(); | 447 Expression* callee = expr->expression(); |
366 Property* prop = callee->AsProperty(); | 448 Property* prop = callee->AsProperty(); |
367 if (prop != NULL) { | 449 if (prop != NULL) { |
368 if (prop->key()->IsPropertyName()) | 450 if (prop->key()->IsPropertyName()) |
369 expr->RecordTypeFeedback(oracle(), CALL_AS_METHOD); | 451 expr->RecordTypeFeedback(oracle(), CALL_AS_METHOD); |
370 } else { | 452 } else { |
371 expr->RecordTypeFeedback(oracle(), CALL_AS_FUNCTION); | 453 expr->RecordTypeFeedback(oracle(), CALL_AS_FUNCTION); |
372 } | 454 } |
373 | 455 |
374 // We don't know anything about the type. | 456 RECURSE(Visit(expr->expression())); |
| 457 ZoneList<Expression*>* args = expr->arguments(); |
| 458 for (int i = 0; i < args->length(); ++i) { |
| 459 Expression* arg = args->at(i); |
| 460 RECURSE(Visit(arg)); |
| 461 } |
| 462 |
| 463 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
| 464 if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) { |
| 465 store_.Forget(); // Eval could do whatever to local variables. |
| 466 } |
| 467 |
| 468 // We don't know anything about the result type. |
375 } | 469 } |
376 | 470 |
377 | 471 |
378 void AstTyper::VisitCallNew(CallNew* expr) { | 472 void AstTyper::VisitCallNew(CallNew* expr) { |
| 473 // Collect type feedback. |
| 474 expr->RecordTypeFeedback(oracle()); |
| 475 |
379 RECURSE(Visit(expr->expression())); | 476 RECURSE(Visit(expr->expression())); |
380 ZoneList<Expression*>* args = expr->arguments(); | 477 ZoneList<Expression*>* args = expr->arguments(); |
381 for (int i = 0; i < args->length(); ++i) { | 478 for (int i = 0; i < args->length(); ++i) { |
382 Expression* arg = args->at(i); | 479 Expression* arg = args->at(i); |
383 RECURSE(Visit(arg)); | 480 RECURSE(Visit(arg)); |
384 } | 481 } |
385 | 482 |
386 expr->RecordTypeFeedback(oracle()); | 483 // We don't know anything about the result type. |
387 | |
388 // We don't know anything about the type. | |
389 } | 484 } |
390 | 485 |
391 | 486 |
392 void AstTyper::VisitCallRuntime(CallRuntime* expr) { | 487 void AstTyper::VisitCallRuntime(CallRuntime* expr) { |
393 ZoneList<Expression*>* args = expr->arguments(); | 488 ZoneList<Expression*>* args = expr->arguments(); |
394 for (int i = 0; i < args->length(); ++i) { | 489 for (int i = 0; i < args->length(); ++i) { |
395 Expression* arg = args->at(i); | 490 Expression* arg = args->at(i); |
396 RECURSE(Visit(arg)); | 491 RECURSE(Visit(arg)); |
397 } | 492 } |
398 | 493 |
399 // We don't know anything about the type. | 494 // We don't know anything about the result type. |
400 } | 495 } |
401 | 496 |
402 | 497 |
403 void AstTyper::VisitUnaryOperation(UnaryOperation* expr) { | 498 void AstTyper::VisitUnaryOperation(UnaryOperation* expr) { |
404 RECURSE(Visit(expr->expression())); | |
405 | |
406 // Collect type feedback. | 499 // Collect type feedback. |
407 Handle<Type> op_type = oracle()->UnaryType(expr->UnaryOperationFeedbackId()); | 500 Handle<Type> op_type = oracle()->UnaryType(expr->UnaryOperationFeedbackId()); |
408 NarrowLowerType(expr->expression(), op_type); | 501 NarrowLowerType(expr->expression(), op_type); |
409 if (expr->op() == Token::NOT) { | 502 if (expr->op() == Token::NOT) { |
410 // TODO(rossberg): only do in test or value context. | 503 // TODO(rossberg): only do in test or value context. |
411 expr->expression()->RecordToBooleanTypeFeedback(oracle()); | 504 expr->expression()->RecordToBooleanTypeFeedback(oracle()); |
412 } | 505 } |
413 | 506 |
| 507 RECURSE(Visit(expr->expression())); |
| 508 |
414 switch (expr->op()) { | 509 switch (expr->op()) { |
415 case Token::NOT: | 510 case Token::NOT: |
416 case Token::DELETE: | 511 case Token::DELETE: |
417 NarrowType(expr, Bounds(Type::Boolean(), isolate_)); | 512 NarrowType(expr, Bounds(Type::Boolean(), isolate_)); |
418 break; | 513 break; |
419 case Token::VOID: | 514 case Token::VOID: |
420 NarrowType(expr, Bounds(Type::Undefined(), isolate_)); | 515 NarrowType(expr, Bounds(Type::Undefined(), isolate_)); |
421 break; | 516 break; |
422 case Token::BIT_NOT: | 517 case Token::BIT_NOT: |
423 NarrowType(expr, Bounds(Type::Smi(), Type::Signed32(), isolate_)); | 518 NarrowType(expr, Bounds(Type::Smi(), Type::Signed32(), isolate_)); |
424 break; | 519 break; |
425 case Token::TYPEOF: | 520 case Token::TYPEOF: |
426 NarrowType(expr, Bounds(Type::InternalizedString(), isolate_)); | 521 NarrowType(expr, Bounds(Type::InternalizedString(), isolate_)); |
427 break; | 522 break; |
428 default: | 523 default: |
429 UNREACHABLE(); | 524 UNREACHABLE(); |
430 } | 525 } |
431 } | 526 } |
432 | 527 |
433 | 528 |
434 void AstTyper::VisitCountOperation(CountOperation* expr) { | 529 void AstTyper::VisitCountOperation(CountOperation* expr) { |
435 RECURSE(Visit(expr->expression())); | 530 // Collect type feedback. |
436 | |
437 expr->RecordTypeFeedback(oracle(), zone()); | 531 expr->RecordTypeFeedback(oracle(), zone()); |
438 Property* prop = expr->expression()->AsProperty(); | 532 Property* prop = expr->expression()->AsProperty(); |
439 if (prop != NULL) { | 533 if (prop != NULL) { |
440 prop->RecordTypeFeedback(oracle(), zone()); | 534 prop->RecordTypeFeedback(oracle(), zone()); |
441 } | 535 } |
442 | 536 |
| 537 RECURSE(Visit(expr->expression())); |
| 538 |
443 NarrowType(expr, Bounds(Type::Smi(), Type::Number(), isolate_)); | 539 NarrowType(expr, Bounds(Type::Smi(), Type::Number(), isolate_)); |
| 540 |
| 541 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
| 542 if (proxy != NULL && proxy->var()->IsStackAllocated()) { |
| 543 store_.Seq(variable_index(proxy->var()), Effect(expr->bounds())); |
| 544 } |
444 } | 545 } |
445 | 546 |
446 | 547 |
447 void AstTyper::VisitBinaryOperation(BinaryOperation* expr) { | 548 void AstTyper::VisitBinaryOperation(BinaryOperation* expr) { |
448 RECURSE(Visit(expr->left())); | |
449 RECURSE(Visit(expr->right())); | |
450 | |
451 // Collect type feedback. | 549 // Collect type feedback. |
452 Handle<Type> type, left_type, right_type; | 550 Handle<Type> type, left_type, right_type; |
453 Maybe<int> fixed_right_arg; | 551 Maybe<int> fixed_right_arg; |
454 oracle()->BinaryType(expr->BinaryOperationFeedbackId(), | 552 oracle()->BinaryType(expr->BinaryOperationFeedbackId(), |
455 &left_type, &right_type, &type, &fixed_right_arg); | 553 &left_type, &right_type, &type, &fixed_right_arg); |
456 NarrowLowerType(expr, type); | 554 NarrowLowerType(expr, type); |
457 NarrowLowerType(expr->left(), left_type); | 555 NarrowLowerType(expr->left(), left_type); |
458 NarrowLowerType(expr->right(), right_type); | 556 NarrowLowerType(expr->right(), right_type); |
459 expr->set_fixed_right_arg(fixed_right_arg); | 557 expr->set_fixed_right_arg(fixed_right_arg); |
460 if (expr->op() == Token::OR || expr->op() == Token::AND) { | 558 if (expr->op() == Token::OR || expr->op() == Token::AND) { |
461 expr->left()->RecordToBooleanTypeFeedback(oracle()); | 559 expr->left()->RecordToBooleanTypeFeedback(oracle()); |
462 } | 560 } |
463 | 561 |
464 switch (expr->op()) { | 562 switch (expr->op()) { |
465 case Token::COMMA: | 563 case Token::COMMA: |
| 564 RECURSE(Visit(expr->left())); |
| 565 RECURSE(Visit(expr->right())); |
466 NarrowType(expr, expr->right()->bounds()); | 566 NarrowType(expr, expr->right()->bounds()); |
467 break; | 567 break; |
468 case Token::OR: | 568 case Token::OR: |
469 case Token::AND: | 569 case Token::AND: { |
| 570 Effects left_effects = EnterEffects(); |
| 571 RECURSE(Visit(expr->left())); |
| 572 ExitEffects(); |
| 573 Effects right_effects = EnterEffects(); |
| 574 RECURSE(Visit(expr->right())); |
| 575 ExitEffects(); |
| 576 left_effects.Alt(right_effects); |
| 577 store_.Seq(left_effects); |
| 578 |
470 NarrowType(expr, Bounds::Either( | 579 NarrowType(expr, Bounds::Either( |
471 expr->left()->bounds(), expr->right()->bounds(), isolate_)); | 580 expr->left()->bounds(), expr->right()->bounds(), isolate_)); |
472 break; | 581 break; |
| 582 } |
473 case Token::BIT_OR: | 583 case Token::BIT_OR: |
474 case Token::BIT_AND: { | 584 case Token::BIT_AND: { |
| 585 RECURSE(Visit(expr->left())); |
| 586 RECURSE(Visit(expr->right())); |
475 Type* upper = Type::Union( | 587 Type* upper = Type::Union( |
476 expr->left()->bounds().upper, expr->right()->bounds().upper); | 588 expr->left()->bounds().upper, expr->right()->bounds().upper); |
477 if (!upper->Is(Type::Signed32())) upper = Type::Signed32(); | 589 if (!upper->Is(Type::Signed32())) upper = Type::Signed32(); |
478 NarrowType(expr, Bounds(Type::Smi(), upper, isolate_)); | 590 NarrowType(expr, Bounds(Type::Smi(), upper, isolate_)); |
479 break; | 591 break; |
480 } | 592 } |
481 case Token::BIT_XOR: | 593 case Token::BIT_XOR: |
482 case Token::SHL: | 594 case Token::SHL: |
483 case Token::SAR: | 595 case Token::SAR: |
| 596 RECURSE(Visit(expr->left())); |
| 597 RECURSE(Visit(expr->right())); |
484 NarrowType(expr, Bounds(Type::Smi(), Type::Signed32(), isolate_)); | 598 NarrowType(expr, Bounds(Type::Smi(), Type::Signed32(), isolate_)); |
485 break; | 599 break; |
486 case Token::SHR: | 600 case Token::SHR: |
| 601 RECURSE(Visit(expr->left())); |
| 602 RECURSE(Visit(expr->right())); |
487 NarrowType(expr, Bounds(Type::Smi(), Type::Unsigned32(), isolate_)); | 603 NarrowType(expr, Bounds(Type::Smi(), Type::Unsigned32(), isolate_)); |
488 break; | 604 break; |
489 case Token::ADD: { | 605 case Token::ADD: { |
| 606 RECURSE(Visit(expr->left())); |
| 607 RECURSE(Visit(expr->right())); |
490 Bounds l = expr->left()->bounds(); | 608 Bounds l = expr->left()->bounds(); |
491 Bounds r = expr->right()->bounds(); | 609 Bounds r = expr->right()->bounds(); |
492 Type* lower = | 610 Type* lower = |
493 l.lower->Is(Type::Number()) && r.lower->Is(Type::Number()) ? | 611 l.lower->Is(Type::Number()) && r.lower->Is(Type::Number()) ? |
494 Type::Smi() : | 612 Type::Smi() : |
495 l.lower->Is(Type::String()) || r.lower->Is(Type::String()) ? | 613 l.lower->Is(Type::String()) || r.lower->Is(Type::String()) ? |
496 Type::String() : Type::None(); | 614 Type::String() : Type::None(); |
497 Type* upper = | 615 Type* upper = |
498 l.upper->Is(Type::Number()) && r.upper->Is(Type::Number()) ? | 616 l.upper->Is(Type::Number()) && r.upper->Is(Type::Number()) ? |
499 Type::Number() : | 617 Type::Number() : |
500 l.upper->Is(Type::String()) || r.upper->Is(Type::String()) ? | 618 l.upper->Is(Type::String()) || r.upper->Is(Type::String()) ? |
501 Type::String() : Type::NumberOrString(); | 619 Type::String() : Type::NumberOrString(); |
502 NarrowType(expr, Bounds(lower, upper, isolate_)); | 620 NarrowType(expr, Bounds(lower, upper, isolate_)); |
503 break; | 621 break; |
504 } | 622 } |
505 case Token::SUB: | 623 case Token::SUB: |
506 case Token::MUL: | 624 case Token::MUL: |
507 case Token::DIV: | 625 case Token::DIV: |
508 case Token::MOD: | 626 case Token::MOD: |
| 627 RECURSE(Visit(expr->left())); |
| 628 RECURSE(Visit(expr->right())); |
509 NarrowType(expr, Bounds(Type::Smi(), Type::Number(), isolate_)); | 629 NarrowType(expr, Bounds(Type::Smi(), Type::Number(), isolate_)); |
510 break; | 630 break; |
511 default: | 631 default: |
512 UNREACHABLE(); | 632 UNREACHABLE(); |
513 } | 633 } |
514 } | 634 } |
515 | 635 |
516 | 636 |
517 void AstTyper::VisitCompareOperation(CompareOperation* expr) { | 637 void AstTyper::VisitCompareOperation(CompareOperation* expr) { |
518 RECURSE(Visit(expr->left())); | |
519 RECURSE(Visit(expr->right())); | |
520 | |
521 // Collect type feedback. | 638 // Collect type feedback. |
522 Handle<Type> left_type, right_type, combined_type; | 639 Handle<Type> left_type, right_type, combined_type; |
523 oracle()->CompareType(expr->CompareOperationFeedbackId(), | 640 oracle()->CompareType(expr->CompareOperationFeedbackId(), |
524 &left_type, &right_type, &combined_type); | 641 &left_type, &right_type, &combined_type); |
525 NarrowLowerType(expr->left(), left_type); | 642 NarrowLowerType(expr->left(), left_type); |
526 NarrowLowerType(expr->right(), right_type); | 643 NarrowLowerType(expr->right(), right_type); |
527 expr->set_combined_type(combined_type); | 644 expr->set_combined_type(combined_type); |
528 | 645 |
| 646 RECURSE(Visit(expr->left())); |
| 647 RECURSE(Visit(expr->right())); |
| 648 |
529 NarrowType(expr, Bounds(Type::Boolean(), isolate_)); | 649 NarrowType(expr, Bounds(Type::Boolean(), isolate_)); |
530 } | 650 } |
531 | 651 |
532 | 652 |
533 void AstTyper::VisitThisFunction(ThisFunction* expr) { | 653 void AstTyper::VisitThisFunction(ThisFunction* expr) { |
534 } | 654 } |
535 | 655 |
536 | 656 |
537 void AstTyper::VisitDeclarations(ZoneList<Declaration*>* decls) { | 657 void AstTyper::VisitDeclarations(ZoneList<Declaration*>* decls) { |
538 for (int i = 0; i < decls->length(); ++i) { | 658 for (int i = 0; i < decls->length(); ++i) { |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
582 void AstTyper::VisitModuleUrl(ModuleUrl* module) { | 702 void AstTyper::VisitModuleUrl(ModuleUrl* module) { |
583 } | 703 } |
584 | 704 |
585 | 705 |
586 void AstTyper::VisitModuleStatement(ModuleStatement* stmt) { | 706 void AstTyper::VisitModuleStatement(ModuleStatement* stmt) { |
587 RECURSE(Visit(stmt->body())); | 707 RECURSE(Visit(stmt->body())); |
588 } | 708 } |
589 | 709 |
590 | 710 |
591 } } // namespace v8::internal | 711 } } // namespace v8::internal |
OLD | NEW |