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

Side by Side Diff: src/typing.cc

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