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

Side by Side Diff: src/rewriter.cc

Issue 8835: Track whether a node or variable are likely to be a Smi value. Propagate that... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 12 years, 1 month 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/rewriter.h ('k') | src/variables.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 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 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 16 matching lines...) Expand all
27 27
28 #include "v8.h" 28 #include "v8.h"
29 29
30 #include "ast.h" 30 #include "ast.h"
31 #include "scopes.h" 31 #include "scopes.h"
32 #include "rewriter.h" 32 #include "rewriter.h"
33 33
34 namespace v8 { namespace internal { 34 namespace v8 { namespace internal {
35 35
36 36
37 class AstOptimizer: public Visitor {
38 public:
39 explicit AstOptimizer() {
40 }
41
42 void Optimize(ZoneList<Statement*>* statements);
43
44 private:
45 // Helpers
46 void OptimizeArguments(ZoneList<Expression*>* arguments);
47
48 // Node visitors.
49 #define DEF_VISIT(type) \
50 virtual void Visit##type(type* node);
51 NODE_LIST(DEF_VISIT)
52 #undef DEF_VISIT
53
54 DISALLOW_COPY_AND_ASSIGN(AstOptimizer);
55 };
56
57
58 void AstOptimizer::Optimize(ZoneList<Statement*>* statements) {
59 int len = statements->length();
60 for (int i = 0; i < len; i++) {
61 Visit(statements->at(i));
62 }
63 }
64
65
66 void AstOptimizer::OptimizeArguments(ZoneList<Expression*>* arguments) {
67 for (int i = 0; i < arguments->length(); i++) {
68 Visit(arguments->at(i));
69 }
70 }
71
72
73 void AstOptimizer::VisitBlock(Block* node) {
74 Optimize(node->statements());
75 }
76
77
78 void AstOptimizer::VisitExpressionStatement(ExpressionStatement* node) {
79 Visit(node->expression());
80 }
81
82
83 void AstOptimizer::VisitIfStatement(IfStatement* node) {
84 Visit(node->condition());
85 Visit(node->then_statement());
86 if (node->HasElseStatement()) {
87 Visit(node->else_statement());
88 }
89 }
90
91
92
93
94 void AstOptimizer::VisitLoopStatement(LoopStatement* node) {
95 if (node->init() != NULL) {
96 Visit(node->init());
97 }
98 if (node->cond() != NULL) {
99 Visit(node->cond());
100 }
101 if (node->body() != NULL) {
102 Visit(node->body());
103 }
104 if (node->next() != NULL) {
105 Visit(node->next());
106 }
107 }
108
109
110 void AstOptimizer::VisitForInStatement(ForInStatement* node) {
111 Visit(node->each());
112 Visit(node->enumerable());
113 Visit(node->body());
114 }
115
116
117 void AstOptimizer::VisitTryCatch(TryCatch* node) {
118 Visit(node->try_block());
119 Visit(node->catch_var());
120 Visit(node->catch_block());
121 }
122
123
124 void AstOptimizer::VisitTryFinally(TryFinally* node) {
125 Visit(node->try_block());
126 Visit(node->finally_block());
127 }
128
129
130 void AstOptimizer::VisitSwitchStatement(SwitchStatement* node) {
131 Visit(node->tag());
132 for (int i = 0; i < node->cases()->length(); i++) {
133 CaseClause* clause = node->cases()->at(i);
134 if (!clause->is_default()) {
135 Visit(clause->label());
136 }
137 Optimize(clause->statements());
138 }
139 }
140
141
142 void AstOptimizer::VisitContinueStatement(ContinueStatement* node) {
143 USE(node);
144 }
145
146
147 void AstOptimizer::VisitBreakStatement(BreakStatement* node) {
148 USE(node);
149 }
150
151
152 void AstOptimizer::VisitDeclaration(Declaration* node) {
153 // Will not be reached by the current optimizations.
154 USE(node);
155 }
156
157
158 void AstOptimizer::VisitEmptyStatement(EmptyStatement* node) {
159 USE(node);
160 }
161
162
163 void AstOptimizer::VisitReturnStatement(ReturnStatement* node) {
164 Visit(node->expression());
165 }
166
167
168 void AstOptimizer::VisitWithEnterStatement(WithEnterStatement* node) {
169 Visit(node->expression());
170 }
171
172
173 void AstOptimizer::VisitWithExitStatement(WithExitStatement* node) {
174 USE(node);
175 }
176
177
178 void AstOptimizer::VisitDebuggerStatement(DebuggerStatement* node) {
179 USE(node);
180 }
181
182
183 void AstOptimizer::VisitFunctionLiteral(FunctionLiteral* node) {
184 USE(node);
185 }
186
187
188 void AstOptimizer::VisitFunctionBoilerplateLiteral(
189 FunctionBoilerplateLiteral* node) {
190 USE(node);
191 }
192
193
194 void AstOptimizer::VisitConditional(Conditional* node) {
195 Visit(node->condition());
196 Visit(node->then_expression());
197 Visit(node->else_expression());
198 }
199
200
201 void AstOptimizer::VisitSlot(Slot* node) {
202 USE(node);
203 }
204
205
206 void AstOptimizer::VisitVariableProxy(VariableProxy* node) {
207 Variable* var = node->AsVariable();
208 if (var != NULL) {
209 if (var->type()->IsKnown()) {
210 node->type()->CopyFrom(var->type());
211 } else if (node->type()->IsLikelySmi()) {
212 var->type()->SetAsLikelySmi();
213 }
214 }
215 }
216
217
218 void AstOptimizer::VisitLiteral(Literal* node) {
219 Handle<Object> literal = node->handle();
220 if (literal->IsSmi()) {
221 node->type()->SetAsLikelySmi();
222 }
223 }
224
225
226 void AstOptimizer::VisitRegExpLiteral(RegExpLiteral* node) {
227 USE(node);
228 }
229
230
231 void AstOptimizer::VisitArrayLiteral(ArrayLiteral* node) {
232 for (int i = 0; i < node->values()->length(); i++) {
233 Visit(node->values()->at(i));
234 }
235 }
236
237
238 void AstOptimizer::VisitObjectLiteral(ObjectLiteral* node) {
239 for (int i = 0; i < node->properties()->length(); i++) {
240 Visit(node->properties()->at(i)->key());
241 Visit(node->properties()->at(i)->value());
242 }
243 }
244
245
246 void AstOptimizer::VisitAssignment(Assignment* node) {
247 switch (node->op()) {
248 case Token::INIT_VAR:
249 case Token::INIT_CONST:
250 case Token::ASSIGN:
251 // No type can be infered from the general assignment.
252 break;
253 case Token::ASSIGN_BIT_OR:
254 case Token::ASSIGN_BIT_XOR:
255 case Token::ASSIGN_BIT_AND:
256 case Token::ASSIGN_SHL:
257 case Token::ASSIGN_SAR:
258 case Token::ASSIGN_SHR:
259 node->type()->SetAsLikelySmiIfUnknown();
260 node->target()->type()->SetAsLikelySmiIfUnknown();
261 node->value()->type()->SetAsLikelySmiIfUnknown();
262 break;
263 case Token::ASSIGN_ADD:
264 case Token::ASSIGN_SUB:
265 case Token::ASSIGN_MUL:
266 case Token::ASSIGN_DIV:
267 case Token::ASSIGN_MOD:
268 if (node->type()->IsLikelySmi()) {
269 node->target()->type()->SetAsLikelySmiIfUnknown();
270 node->value()->type()->SetAsLikelySmiIfUnknown();
271 }
272 break;
273 default:
274 UNREACHABLE();
275 break;
276 }
277
278 Visit(node->target());
279 Visit(node->value());
280
281 switch (node->op()) {
282 case Token::INIT_VAR:
283 case Token::INIT_CONST:
284 case Token::ASSIGN:
285 // Pure assigment copies the type from the value.
286 node->type()->CopyFrom(node->value()->type());
287 break;
288 case Token::ASSIGN_BIT_OR:
289 case Token::ASSIGN_BIT_XOR:
290 case Token::ASSIGN_BIT_AND:
291 case Token::ASSIGN_SHL:
292 case Token::ASSIGN_SAR:
293 case Token::ASSIGN_SHR:
294 // Should have been setup above already.
295 break;
296 case Token::ASSIGN_ADD:
297 case Token::ASSIGN_SUB:
298 case Token::ASSIGN_MUL:
299 case Token::ASSIGN_DIV:
300 case Token::ASSIGN_MOD:
301 if (node->type()->IsUnknown()) {
302 if (node->target()->type()->IsLikelySmi() ||
303 node->value()->type()->IsLikelySmi()) {
304 node->type()->SetAsLikelySmi();
305 }
306 }
307 break;
308 default:
309 UNREACHABLE();
310 break;
311 }
312
313 // Since this is an assignment. We have to propagate this node's type to the
314 // variable.
315 VariableProxy* proxy = node->target()->AsVariableProxy();
316 if (proxy != NULL) {
317 Variable* var = proxy->AsVariable();
318 if (var != NULL) {
319 StaticType* var_type = var->type();
320 if (var_type->IsUnknown()) {
321 var_type->CopyFrom(node->type());
322 } else if (var_type->IsLikelySmi()) {
323 // We do not reset likely types to Unknown.
324 }
325 }
326 }
327 }
328
329
330 void AstOptimizer::VisitThrow(Throw* node) {
331 Visit(node->exception());
332 }
333
334
335 void AstOptimizer::VisitProperty(Property* node) {
336 Visit(node->obj());
337 Visit(node->key());
338 }
339
340
341 void AstOptimizer::VisitCall(Call* node) {
342 Visit(node->expression());
343 OptimizeArguments(node->arguments());
344 }
345
346
347 void AstOptimizer::VisitCallNew(CallNew* node) {
348 Visit(node->expression());
349 OptimizeArguments(node->arguments());
350 }
351
352
353 void AstOptimizer::VisitCallRuntime(CallRuntime* node) {
354 OptimizeArguments(node->arguments());
355 }
356
357
358 void AstOptimizer::VisitUnaryOperation(UnaryOperation* node) {
359 Visit(node->expression());
360 }
361
362
363 void AstOptimizer::VisitCountOperation(CountOperation* node) {
364 // Count operations assume that they work on Smis.
365 node->type()->SetAsLikelySmiIfUnknown();
366 node->expression()->type()->SetAsLikelySmiIfUnknown();
367 Visit(node->expression());
368 }
369
370
371 void AstOptimizer::VisitBinaryOperation(BinaryOperation* node) {
372 // Depending on the operation we can propagate this node's type down the
373 // AST nodes.
374 switch (node->op()) {
375 case Token::COMMA:
376 case Token::OR:
377 case Token::AND:
378 break;
379 case Token::BIT_OR:
380 case Token::BIT_XOR:
381 case Token::BIT_AND:
382 case Token::SHL:
383 case Token::SAR:
384 case Token::SHR:
385 node->type()->SetAsLikelySmiIfUnknown();
386 node->left()->type()->SetAsLikelySmiIfUnknown();
387 node->right()->type()->SetAsLikelySmiIfUnknown();
388 break;
389 case Token::ADD:
390 case Token::SUB:
391 case Token::MUL:
392 case Token::DIV:
393 case Token::MOD:
394 if (node->type()->IsLikelySmi()) {
395 node->left()->type()->SetAsLikelySmiIfUnknown();
396 node->right()->type()->SetAsLikelySmiIfUnknown();
397 }
398 break;
399 default:
400 UNREACHABLE();
401 break;
402 }
403
404 Visit(node->left());
405 Visit(node->right());
406
407 // After visiting the operand nodes we have to check if this node's type
408 // can be updated. If it does, then we can push that information down
409 // towards the leafs again if the new information is an upgrade over the
410 // previous type of the operand nodes.
411 if (node->type()->IsUnknown()) {
412 if (node->left()->type()->IsLikelySmi() ||
413 node->right()->type()->IsLikelySmi()) {
414 node->type()->SetAsLikelySmi();
415 }
416 if (node->type()->IsLikelySmi()) {
417 // The type of this node changed to LIKELY_SMI. Propagate this knowlege
418 // down through the nodes.
419 if (node->left()->type()->IsUnknown()) {
420 node->left()->type()->SetAsLikelySmi();
421 Visit(node->left());
422 }
423 if (node->right()->type()->IsUnknown()) {
424 node->right()->type()->SetAsLikelySmi();
425 Visit(node->right());
426 }
427 }
428 }
429 }
430
431
432 void AstOptimizer::VisitCompareOperation(CompareOperation* node) {
433 if (node->type()->IsKnown()) {
434 // Propagate useful information down towards the leafs.
435 node->left()->type()->SetAsLikelySmiIfUnknown();
436 node->right()->type()->SetAsLikelySmiIfUnknown();
437 }
438
439 Visit(node->left());
440 Visit(node->right());
441
442 // After visiting the operand nodes we have to check if this node's type
443 // can be updated. If it does, then we can push that information down
444 // towards the leafs again if the new information is an upgrade over the
445 // previous type of the operand nodes.
446 if (node->type()->IsUnknown()) {
447 if (node->left()->type()->IsLikelySmi() ||
448 node->right()->type()->IsLikelySmi()) {
449 node->type()->SetAsLikelySmi();
450 }
451 if (node->type()->IsLikelySmi()) {
452 // The type of this node changed to LIKELY_SMI. Propagate this knowlege
453 // down through the nodes.
454 if (node->left()->type()->IsUnknown()) {
455 node->left()->type()->SetAsLikelySmi();
456 Visit(node->left());
457 }
458 if (node->right()->type()->IsUnknown()) {
459 node->right()->type()->SetAsLikelySmi();
460 Visit(node->right());
461 }
462 }
463 }
464 }
465
466
467 void AstOptimizer::VisitThisFunction(ThisFunction* node) {
468 USE(node);
469 }
470
471
37 class Processor: public Visitor { 472 class Processor: public Visitor {
38 public: 473 public:
39 explicit Processor(VariableProxy* result) 474 explicit Processor(VariableProxy* result)
40 : result_(result), 475 : result_(result),
41 result_assigned_(false), 476 result_assigned_(false),
42 is_set_(false), 477 is_set_(false),
43 in_try_(false) { 478 in_try_(false) {
44 } 479 }
45 480
46 void Process(ZoneList<Statement*>* statements); 481 void Process(ZoneList<Statement*>* statements);
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after
319 VariableProxy* result = scope->NewTemporary(Factory::result_symbol()); 754 VariableProxy* result = scope->NewTemporary(Factory::result_symbol());
320 Processor processor(result); 755 Processor processor(result);
321 processor.Process(body); 756 processor.Process(body);
322 if (processor.HasStackOverflow()) return false; 757 if (processor.HasStackOverflow()) return false;
323 758
324 if (processor.result_assigned()) body->Add(new ReturnStatement(result)); 759 if (processor.result_assigned()) body->Add(new ReturnStatement(result));
325 return true; 760 return true;
326 } 761 }
327 762
328 763
764 void Rewriter::Optimize(FunctionLiteral* function) {
765 ZoneList<Statement*>* body = function->body();
766 if (body->is_empty()) return;
767
768 if (FLAG_optimize_ast) {
769 Scope* scope = function->scope();
770 if (!scope->is_global_scope()) {
771 AstOptimizer optimizer;
772 optimizer.Optimize(body);
773 }
774 }
775 }
776
777
329 } } // namespace v8::internal 778 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/rewriter.h ('k') | src/variables.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698