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

Side by Side Diff: src/typing.cc

Issue 22144006: Un-revert "Implement simple effect typing for variables" and "Handle switch effects" (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: fix building with clang Created 7 years, 4 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 18 matching lines...) Expand all
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
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
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