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