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

Side by Side Diff: src/typing.cc

Issue 19054006: Implement simple effect typing for variables (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Comments Created 7 years, 5 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/typing.h ('k') | src/zone.h » ('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 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
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
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
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
OLDNEW
« no previous file with comments | « src/typing.h ('k') | src/zone.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698