blob: 4e7620acf702769e13f3d060571c762f61db2e6b [file] [log] [blame]
Leon Clarke4515c472010-02-03 11:58:03 +00001// Copyright 2010 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include "v8.h"
29
30#include "data-flow.h"
Steve Block6ded16b2010-05-10 14:33:55 +010031#include "scopes.h"
Leon Clarke4515c472010-02-03 11:58:03 +000032
33namespace v8 {
34namespace internal {
35
36
Steve Block6ded16b2010-05-10 14:33:55 +010037#ifdef DEBUG
38void BitVector::Print() {
39 bool first = true;
40 PrintF("{");
41 for (int i = 0; i < length(); i++) {
42 if (Contains(i)) {
43 if (!first) PrintF(",");
44 first = false;
45 PrintF("%d");
46 }
47 }
48 PrintF("}");
49}
50#endif
51
52
Andrei Popescu31002712010-02-23 13:46:05 +000053void AstLabeler::Label(CompilationInfo* info) {
54 info_ = info;
55 VisitStatements(info_->function()->body());
Leon Clarke4515c472010-02-03 11:58:03 +000056}
57
58
59void AstLabeler::VisitStatements(ZoneList<Statement*>* stmts) {
60 for (int i = 0, len = stmts->length(); i < len; i++) {
61 Visit(stmts->at(i));
62 }
63}
64
65
66void AstLabeler::VisitDeclarations(ZoneList<Declaration*>* decls) {
67 UNREACHABLE();
68}
69
70
71void AstLabeler::VisitBlock(Block* stmt) {
72 VisitStatements(stmt->statements());
73}
74
75
76void AstLabeler::VisitExpressionStatement(
77 ExpressionStatement* stmt) {
78 Visit(stmt->expression());
79}
80
81
82void AstLabeler::VisitEmptyStatement(EmptyStatement* stmt) {
83 // Do nothing.
84}
85
86
87void AstLabeler::VisitIfStatement(IfStatement* stmt) {
88 UNREACHABLE();
89}
90
91
92void AstLabeler::VisitContinueStatement(ContinueStatement* stmt) {
93 UNREACHABLE();
94}
95
96
97void AstLabeler::VisitBreakStatement(BreakStatement* stmt) {
98 UNREACHABLE();
99}
100
101
102void AstLabeler::VisitReturnStatement(ReturnStatement* stmt) {
103 UNREACHABLE();
104}
105
106
107void AstLabeler::VisitWithEnterStatement(
108 WithEnterStatement* stmt) {
109 UNREACHABLE();
110}
111
112
113void AstLabeler::VisitWithExitStatement(WithExitStatement* stmt) {
114 UNREACHABLE();
115}
116
117
118void AstLabeler::VisitSwitchStatement(SwitchStatement* stmt) {
119 UNREACHABLE();
120}
121
122
123void AstLabeler::VisitDoWhileStatement(DoWhileStatement* stmt) {
124 UNREACHABLE();
125}
126
127
128void AstLabeler::VisitWhileStatement(WhileStatement* stmt) {
129 UNREACHABLE();
130}
131
132
133void AstLabeler::VisitForStatement(ForStatement* stmt) {
134 UNREACHABLE();
135}
136
137
138void AstLabeler::VisitForInStatement(ForInStatement* stmt) {
139 UNREACHABLE();
140}
141
142
143void AstLabeler::VisitTryCatchStatement(TryCatchStatement* stmt) {
144 UNREACHABLE();
145}
146
147
148void AstLabeler::VisitTryFinallyStatement(
149 TryFinallyStatement* stmt) {
150 UNREACHABLE();
151}
152
153
154void AstLabeler::VisitDebuggerStatement(
155 DebuggerStatement* stmt) {
156 UNREACHABLE();
157}
158
159
160void AstLabeler::VisitFunctionLiteral(FunctionLiteral* expr) {
161 UNREACHABLE();
162}
163
164
Steve Block6ded16b2010-05-10 14:33:55 +0100165void AstLabeler::VisitSharedFunctionInfoLiteral(
166 SharedFunctionInfoLiteral* expr) {
Leon Clarke4515c472010-02-03 11:58:03 +0000167 UNREACHABLE();
168}
169
170
171void AstLabeler::VisitConditional(Conditional* expr) {
172 UNREACHABLE();
173}
174
175
176void AstLabeler::VisitSlot(Slot* expr) {
177 UNREACHABLE();
178}
179
180
181void AstLabeler::VisitVariableProxy(VariableProxy* expr) {
182 expr->set_num(next_number_++);
Andrei Popescu31002712010-02-23 13:46:05 +0000183 Variable* var = expr->var();
184 if (var->is_global() && !var->is_this()) {
185 info_->set_has_globals(true);
186 }
Leon Clarke4515c472010-02-03 11:58:03 +0000187}
188
189
190void AstLabeler::VisitLiteral(Literal* expr) {
191 UNREACHABLE();
192}
193
194
195void AstLabeler::VisitRegExpLiteral(RegExpLiteral* expr) {
196 UNREACHABLE();
197}
198
199
200void AstLabeler::VisitObjectLiteral(ObjectLiteral* expr) {
201 UNREACHABLE();
202}
203
204
205void AstLabeler::VisitArrayLiteral(ArrayLiteral* expr) {
206 UNREACHABLE();
207}
208
209
210void AstLabeler::VisitCatchExtensionObject(
211 CatchExtensionObject* expr) {
212 UNREACHABLE();
213}
214
215
216void AstLabeler::VisitAssignment(Assignment* expr) {
217 Property* prop = expr->target()->AsProperty();
218 ASSERT(prop != NULL);
Andrei Popescu402d9372010-02-26 13:31:12 +0000219 ASSERT(prop->key()->IsPropertyName());
220 VariableProxy* proxy = prop->obj()->AsVariableProxy();
221 USE(proxy);
222 ASSERT(proxy != NULL && proxy->var()->is_this());
223 info()->set_has_this_properties(true);
Steve Block6ded16b2010-05-10 14:33:55 +0100224
225 prop->obj()->set_num(AstNode::kNoNumber);
226 prop->key()->set_num(AstNode::kNoNumber);
Leon Clarke4515c472010-02-03 11:58:03 +0000227 Visit(expr->value());
228 expr->set_num(next_number_++);
229}
230
231
232void AstLabeler::VisitThrow(Throw* expr) {
233 UNREACHABLE();
234}
235
236
237void AstLabeler::VisitProperty(Property* expr) {
Andrei Popescu402d9372010-02-26 13:31:12 +0000238 ASSERT(expr->key()->IsPropertyName());
239 VariableProxy* proxy = expr->obj()->AsVariableProxy();
240 USE(proxy);
241 ASSERT(proxy != NULL && proxy->var()->is_this());
242 info()->set_has_this_properties(true);
Steve Block6ded16b2010-05-10 14:33:55 +0100243
244 expr->obj()->set_num(AstNode::kNoNumber);
245 expr->key()->set_num(AstNode::kNoNumber);
Andrei Popescu402d9372010-02-26 13:31:12 +0000246 expr->set_num(next_number_++);
Leon Clarke4515c472010-02-03 11:58:03 +0000247}
248
249
250void AstLabeler::VisitCall(Call* expr) {
251 UNREACHABLE();
252}
253
254
255void AstLabeler::VisitCallNew(CallNew* expr) {
256 UNREACHABLE();
257}
258
259
260void AstLabeler::VisitCallRuntime(CallRuntime* expr) {
261 UNREACHABLE();
262}
263
264
265void AstLabeler::VisitUnaryOperation(UnaryOperation* expr) {
266 UNREACHABLE();
267}
268
269
270void AstLabeler::VisitCountOperation(CountOperation* expr) {
271 UNREACHABLE();
272}
273
274
275void AstLabeler::VisitBinaryOperation(BinaryOperation* expr) {
276 Visit(expr->left());
277 Visit(expr->right());
278 expr->set_num(next_number_++);
279}
280
281
282void AstLabeler::VisitCompareOperation(CompareOperation* expr) {
283 UNREACHABLE();
284}
285
286
287void AstLabeler::VisitThisFunction(ThisFunction* expr) {
288 UNREACHABLE();
289}
290
291
292void AstLabeler::VisitDeclaration(Declaration* decl) {
293 UNREACHABLE();
294}
295
Andrei Popescu402d9372010-02-26 13:31:12 +0000296
Steve Block6ded16b2010-05-10 14:33:55 +0100297AssignedVariablesAnalyzer::AssignedVariablesAnalyzer(FunctionLiteral* fun)
298 : fun_(fun),
299 av_(fun->scope()->num_parameters() + fun->scope()->num_stack_slots()) {}
300
301
302void AssignedVariablesAnalyzer::Analyze() {
303 ASSERT(av_.length() > 0);
304 VisitStatements(fun_->body());
Andrei Popescu402d9372010-02-26 13:31:12 +0000305}
306
307
Steve Block6ded16b2010-05-10 14:33:55 +0100308Variable* AssignedVariablesAnalyzer::FindSmiLoopVariable(ForStatement* stmt) {
309 // The loop must have all necessary parts.
310 if (stmt->init() == NULL || stmt->cond() == NULL || stmt->next() == NULL) {
311 return NULL;
312 }
313 // The initialization statement has to be a simple assignment.
314 Assignment* init = stmt->init()->StatementAsSimpleAssignment();
315 if (init == NULL) return NULL;
Andrei Popescu402d9372010-02-26 13:31:12 +0000316
Steve Block6ded16b2010-05-10 14:33:55 +0100317 // We only deal with local variables.
318 Variable* loop_var = init->target()->AsVariableProxy()->AsVariable();
319 if (loop_var == NULL || !loop_var->IsStackAllocated()) return NULL;
320
321 // The initial value has to be a smi.
322 Literal* init_lit = init->value()->AsLiteral();
323 if (init_lit == NULL || !init_lit->handle()->IsSmi()) return NULL;
324 int init_value = Smi::cast(*init_lit->handle())->value();
325
326 // The condition must be a compare of variable with <, <=, >, or >=.
327 CompareOperation* cond = stmt->cond()->AsCompareOperation();
328 if (cond == NULL) return NULL;
329 if (cond->op() != Token::LT
330 && cond->op() != Token::LTE
331 && cond->op() != Token::GT
332 && cond->op() != Token::GTE) return NULL;
333
334 // The lhs must be the same variable as in the init expression.
335 if (cond->left()->AsVariableProxy()->AsVariable() != loop_var) return NULL;
336
337 // The rhs must be a smi.
338 Literal* term_lit = cond->right()->AsLiteral();
339 if (term_lit == NULL || !term_lit->handle()->IsSmi()) return NULL;
340 int term_value = Smi::cast(*term_lit->handle())->value();
341
342 // The count operation updates the same variable as in the init expression.
343 CountOperation* update = stmt->next()->StatementAsCountOperation();
344 if (update == NULL) return NULL;
345 if (update->expression()->AsVariableProxy()->AsVariable() != loop_var) {
346 return NULL;
347 }
348
349 // The direction of the count operation must agree with the start and the end
350 // value. We currently do not allow the initial value to be the same as the
351 // terminal value. This _would_ be ok as long as the loop body never executes
352 // or executes exactly one time.
353 if (init_value == term_value) return NULL;
354 if (init_value < term_value && update->op() != Token::INC) return NULL;
355 if (init_value > term_value && update->op() != Token::DEC) return NULL;
356
357 // Check that the update operation cannot overflow the smi range. This can
358 // occur in the two cases where the loop bound is equal to the largest or
359 // smallest smi.
360 if (update->op() == Token::INC && term_value == Smi::kMaxValue) return NULL;
361 if (update->op() == Token::DEC && term_value == Smi::kMinValue) return NULL;
362
363 // Found a smi loop variable.
364 return loop_var;
365}
366
367int AssignedVariablesAnalyzer::BitIndex(Variable* var) {
368 ASSERT(var != NULL);
369 ASSERT(var->IsStackAllocated());
370 Slot* slot = var->slot();
371 if (slot->type() == Slot::PARAMETER) {
372 return slot->index();
373 } else {
374 return fun_->scope()->num_parameters() + slot->index();
Andrei Popescu402d9372010-02-26 13:31:12 +0000375 }
376}
377
378
Steve Block6ded16b2010-05-10 14:33:55 +0100379void AssignedVariablesAnalyzer::RecordAssignedVar(Variable* var) {
380 ASSERT(var != NULL);
381 if (var->IsStackAllocated()) {
382 av_.Add(BitIndex(var));
Andrei Popescu402d9372010-02-26 13:31:12 +0000383 }
384}
385
386
Steve Block6ded16b2010-05-10 14:33:55 +0100387void AssignedVariablesAnalyzer::MarkIfTrivial(Expression* expr) {
388 Variable* var = expr->AsVariableProxy()->AsVariable();
389 if (var != NULL &&
390 var->IsStackAllocated() &&
391 !var->is_arguments() &&
392 var->mode() != Variable::CONST &&
393 (var->is_this() || !av_.Contains(BitIndex(var)))) {
394 expr->AsVariableProxy()->set_is_trivial(true);
Andrei Popescu402d9372010-02-26 13:31:12 +0000395 }
396}
397
398
Steve Block6ded16b2010-05-10 14:33:55 +0100399void AssignedVariablesAnalyzer::ProcessExpression(Expression* expr) {
400 BitVector saved_av(av_);
401 av_.Clear();
402 Visit(expr);
403 av_.Union(saved_av);
Andrei Popescu402d9372010-02-26 13:31:12 +0000404}
405
Steve Block6ded16b2010-05-10 14:33:55 +0100406void AssignedVariablesAnalyzer::VisitBlock(Block* stmt) {
Andrei Popescu402d9372010-02-26 13:31:12 +0000407 VisitStatements(stmt->statements());
408}
409
410
Steve Block6ded16b2010-05-10 14:33:55 +0100411void AssignedVariablesAnalyzer::VisitExpressionStatement(
Andrei Popescu402d9372010-02-26 13:31:12 +0000412 ExpressionStatement* stmt) {
Steve Block6ded16b2010-05-10 14:33:55 +0100413 ProcessExpression(stmt->expression());
Andrei Popescu402d9372010-02-26 13:31:12 +0000414}
415
416
Steve Block6ded16b2010-05-10 14:33:55 +0100417void AssignedVariablesAnalyzer::VisitEmptyStatement(EmptyStatement* stmt) {
Andrei Popescu402d9372010-02-26 13:31:12 +0000418 // Do nothing.
419}
420
421
Steve Block6ded16b2010-05-10 14:33:55 +0100422void AssignedVariablesAnalyzer::VisitIfStatement(IfStatement* stmt) {
423 ProcessExpression(stmt->condition());
424 Visit(stmt->then_statement());
425 Visit(stmt->else_statement());
Andrei Popescu402d9372010-02-26 13:31:12 +0000426}
427
428
Steve Block6ded16b2010-05-10 14:33:55 +0100429void AssignedVariablesAnalyzer::VisitContinueStatement(
430 ContinueStatement* stmt) {
431 // Nothing to do.
Andrei Popescu402d9372010-02-26 13:31:12 +0000432}
433
434
Steve Block6ded16b2010-05-10 14:33:55 +0100435void AssignedVariablesAnalyzer::VisitBreakStatement(BreakStatement* stmt) {
436 // Nothing to do.
Andrei Popescu402d9372010-02-26 13:31:12 +0000437}
438
439
Steve Block6ded16b2010-05-10 14:33:55 +0100440void AssignedVariablesAnalyzer::VisitReturnStatement(ReturnStatement* stmt) {
441 ProcessExpression(stmt->expression());
Andrei Popescu402d9372010-02-26 13:31:12 +0000442}
443
444
Steve Block6ded16b2010-05-10 14:33:55 +0100445void AssignedVariablesAnalyzer::VisitWithEnterStatement(
Andrei Popescu402d9372010-02-26 13:31:12 +0000446 WithEnterStatement* stmt) {
Steve Block6ded16b2010-05-10 14:33:55 +0100447 ProcessExpression(stmt->expression());
Andrei Popescu402d9372010-02-26 13:31:12 +0000448}
449
450
Steve Block6ded16b2010-05-10 14:33:55 +0100451void AssignedVariablesAnalyzer::VisitWithExitStatement(
452 WithExitStatement* stmt) {
453 // Nothing to do.
Andrei Popescu402d9372010-02-26 13:31:12 +0000454}
455
456
Steve Block6ded16b2010-05-10 14:33:55 +0100457void AssignedVariablesAnalyzer::VisitSwitchStatement(SwitchStatement* stmt) {
458 BitVector result(av_);
459 av_.Clear();
460 Visit(stmt->tag());
461 result.Union(av_);
462 for (int i = 0; i < stmt->cases()->length(); i++) {
463 CaseClause* clause = stmt->cases()->at(i);
464 if (!clause->is_default()) {
465 av_.Clear();
466 Visit(clause->label());
467 result.Union(av_);
468 }
469 VisitStatements(clause->statements());
470 }
471 av_.Union(result);
Andrei Popescu402d9372010-02-26 13:31:12 +0000472}
473
474
Steve Block6ded16b2010-05-10 14:33:55 +0100475void AssignedVariablesAnalyzer::VisitDoWhileStatement(DoWhileStatement* stmt) {
476 ProcessExpression(stmt->cond());
477 Visit(stmt->body());
Andrei Popescu402d9372010-02-26 13:31:12 +0000478}
479
480
Steve Block6ded16b2010-05-10 14:33:55 +0100481void AssignedVariablesAnalyzer::VisitWhileStatement(WhileStatement* stmt) {
482 ProcessExpression(stmt->cond());
483 Visit(stmt->body());
Andrei Popescu402d9372010-02-26 13:31:12 +0000484}
485
486
Steve Block6ded16b2010-05-10 14:33:55 +0100487void AssignedVariablesAnalyzer::VisitForStatement(ForStatement* stmt) {
488 if (stmt->init() != NULL) Visit(stmt->init());
489
490 if (stmt->cond() != NULL) ProcessExpression(stmt->cond());
491
492 if (stmt->next() != NULL) Visit(stmt->next());
493
494 // Process loop body. After visiting the loop body av_ contains
495 // the assigned variables of the loop body.
496 BitVector saved_av(av_);
497 av_.Clear();
498 Visit(stmt->body());
499
500 Variable* var = FindSmiLoopVariable(stmt);
501 if (var != NULL && !av_.Contains(BitIndex(var))) {
502 stmt->set_loop_variable(var);
503 }
504
505 av_.Union(saved_av);
Andrei Popescu402d9372010-02-26 13:31:12 +0000506}
507
508
Steve Block6ded16b2010-05-10 14:33:55 +0100509void AssignedVariablesAnalyzer::VisitForInStatement(ForInStatement* stmt) {
510 ProcessExpression(stmt->each());
511 ProcessExpression(stmt->enumerable());
512 Visit(stmt->body());
Andrei Popescu402d9372010-02-26 13:31:12 +0000513}
514
515
Steve Block6ded16b2010-05-10 14:33:55 +0100516void AssignedVariablesAnalyzer::VisitTryCatchStatement(
517 TryCatchStatement* stmt) {
518 Visit(stmt->try_block());
519 Visit(stmt->catch_block());
Andrei Popescu402d9372010-02-26 13:31:12 +0000520}
521
522
Steve Block6ded16b2010-05-10 14:33:55 +0100523void AssignedVariablesAnalyzer::VisitTryFinallyStatement(
Andrei Popescu402d9372010-02-26 13:31:12 +0000524 TryFinallyStatement* stmt) {
Steve Block6ded16b2010-05-10 14:33:55 +0100525 Visit(stmt->try_block());
526 Visit(stmt->finally_block());
Andrei Popescu402d9372010-02-26 13:31:12 +0000527}
528
529
Steve Block6ded16b2010-05-10 14:33:55 +0100530void AssignedVariablesAnalyzer::VisitDebuggerStatement(
Andrei Popescu402d9372010-02-26 13:31:12 +0000531 DebuggerStatement* stmt) {
Steve Block6ded16b2010-05-10 14:33:55 +0100532 // Nothing to do.
533}
534
535
536void AssignedVariablesAnalyzer::VisitFunctionLiteral(FunctionLiteral* expr) {
537 // Nothing to do.
538 ASSERT(av_.IsEmpty());
539}
540
541
542void AssignedVariablesAnalyzer::VisitSharedFunctionInfoLiteral(
543 SharedFunctionInfoLiteral* expr) {
544 // Nothing to do.
545 ASSERT(av_.IsEmpty());
546}
547
548
549void AssignedVariablesAnalyzer::VisitConditional(Conditional* expr) {
550 ASSERT(av_.IsEmpty());
551
552 Visit(expr->condition());
553
554 BitVector result(av_);
555 av_.Clear();
556 Visit(expr->then_expression());
557 result.Union(av_);
558
559 av_.Clear();
560 Visit(expr->else_expression());
561 av_.Union(result);
562}
563
564
565void AssignedVariablesAnalyzer::VisitSlot(Slot* expr) {
Andrei Popescu402d9372010-02-26 13:31:12 +0000566 UNREACHABLE();
567}
568
569
Steve Block6ded16b2010-05-10 14:33:55 +0100570void AssignedVariablesAnalyzer::VisitVariableProxy(VariableProxy* expr) {
571 // Nothing to do.
572 ASSERT(av_.IsEmpty());
Andrei Popescu402d9372010-02-26 13:31:12 +0000573}
574
575
Steve Block6ded16b2010-05-10 14:33:55 +0100576void AssignedVariablesAnalyzer::VisitLiteral(Literal* expr) {
577 // Nothing to do.
578 ASSERT(av_.IsEmpty());
Andrei Popescu402d9372010-02-26 13:31:12 +0000579}
580
581
Steve Block6ded16b2010-05-10 14:33:55 +0100582void AssignedVariablesAnalyzer::VisitRegExpLiteral(RegExpLiteral* expr) {
583 // Nothing to do.
584 ASSERT(av_.IsEmpty());
Andrei Popescu402d9372010-02-26 13:31:12 +0000585}
586
587
Steve Block6ded16b2010-05-10 14:33:55 +0100588void AssignedVariablesAnalyzer::VisitObjectLiteral(ObjectLiteral* expr) {
589 ASSERT(av_.IsEmpty());
590 BitVector result(av_.length());
591 for (int i = 0; i < expr->properties()->length(); i++) {
592 Visit(expr->properties()->at(i)->value());
593 result.Union(av_);
594 av_.Clear();
595 }
596 av_ = result;
Andrei Popescu402d9372010-02-26 13:31:12 +0000597}
598
599
Steve Block6ded16b2010-05-10 14:33:55 +0100600void AssignedVariablesAnalyzer::VisitArrayLiteral(ArrayLiteral* expr) {
601 ASSERT(av_.IsEmpty());
602 BitVector result(av_.length());
603 for (int i = 0; i < expr->values()->length(); i++) {
604 Visit(expr->values()->at(i));
605 result.Union(av_);
606 av_.Clear();
607 }
608 av_ = result;
Andrei Popescu402d9372010-02-26 13:31:12 +0000609}
610
611
Steve Block6ded16b2010-05-10 14:33:55 +0100612void AssignedVariablesAnalyzer::VisitCatchExtensionObject(
Andrei Popescu402d9372010-02-26 13:31:12 +0000613 CatchExtensionObject* expr) {
Steve Block6ded16b2010-05-10 14:33:55 +0100614 ASSERT(av_.IsEmpty());
615 Visit(expr->key());
616 ProcessExpression(expr->value());
Andrei Popescu402d9372010-02-26 13:31:12 +0000617}
618
619
Steve Block6ded16b2010-05-10 14:33:55 +0100620void AssignedVariablesAnalyzer::VisitAssignment(Assignment* expr) {
621 ASSERT(av_.IsEmpty());
622
623 // There are three kinds of assignments: variable assignments, property
624 // assignments, and reference errors (invalid left-hand sides).
625 Variable* var = expr->target()->AsVariableProxy()->AsVariable();
Andrei Popescu402d9372010-02-26 13:31:12 +0000626 Property* prop = expr->target()->AsProperty();
Steve Block6ded16b2010-05-10 14:33:55 +0100627 ASSERT(var == NULL || prop == NULL);
Andrei Popescu402d9372010-02-26 13:31:12 +0000628
Steve Block6ded16b2010-05-10 14:33:55 +0100629 if (var != NULL) {
630 MarkIfTrivial(expr->value());
631 Visit(expr->value());
632 if (expr->is_compound()) {
633 // Left-hand side occurs also as an rvalue.
634 MarkIfTrivial(expr->target());
635 ProcessExpression(expr->target());
636 }
637 RecordAssignedVar(var);
Andrei Popescu402d9372010-02-26 13:31:12 +0000638
Steve Block6ded16b2010-05-10 14:33:55 +0100639 } else if (prop != NULL) {
640 MarkIfTrivial(expr->value());
641 Visit(expr->value());
642 if (!prop->key()->IsPropertyName()) {
643 MarkIfTrivial(prop->key());
644 ProcessExpression(prop->key());
645 }
646 MarkIfTrivial(prop->obj());
647 ProcessExpression(prop->obj());
648
649 } else {
650 Visit(expr->target());
651 }
Andrei Popescu402d9372010-02-26 13:31:12 +0000652}
653
654
Steve Block6ded16b2010-05-10 14:33:55 +0100655void AssignedVariablesAnalyzer::VisitThrow(Throw* expr) {
656 ASSERT(av_.IsEmpty());
657 Visit(expr->exception());
Andrei Popescu402d9372010-02-26 13:31:12 +0000658}
659
660
Steve Block6ded16b2010-05-10 14:33:55 +0100661void AssignedVariablesAnalyzer::VisitProperty(Property* expr) {
662 ASSERT(av_.IsEmpty());
663 if (!expr->key()->IsPropertyName()) {
664 MarkIfTrivial(expr->key());
665 Visit(expr->key());
666 }
667 MarkIfTrivial(expr->obj());
668 ProcessExpression(expr->obj());
Andrei Popescu402d9372010-02-26 13:31:12 +0000669}
670
671
Steve Block6ded16b2010-05-10 14:33:55 +0100672void AssignedVariablesAnalyzer::VisitCall(Call* expr) {
673 ASSERT(av_.IsEmpty());
674 Visit(expr->expression());
675 BitVector result(av_);
676 for (int i = 0; i < expr->arguments()->length(); i++) {
677 av_.Clear();
678 Visit(expr->arguments()->at(i));
679 result.Union(av_);
680 }
681 av_ = result;
Andrei Popescu402d9372010-02-26 13:31:12 +0000682}
683
684
Steve Block6ded16b2010-05-10 14:33:55 +0100685void AssignedVariablesAnalyzer::VisitCallNew(CallNew* expr) {
686 ASSERT(av_.IsEmpty());
687 Visit(expr->expression());
688 BitVector result(av_);
689 for (int i = 0; i < expr->arguments()->length(); i++) {
690 av_.Clear();
691 Visit(expr->arguments()->at(i));
692 result.Union(av_);
693 }
694 av_ = result;
Andrei Popescu402d9372010-02-26 13:31:12 +0000695}
696
697
Steve Block6ded16b2010-05-10 14:33:55 +0100698void AssignedVariablesAnalyzer::VisitCallRuntime(CallRuntime* expr) {
699 ASSERT(av_.IsEmpty());
700 BitVector result(av_);
701 for (int i = 0; i < expr->arguments()->length(); i++) {
702 av_.Clear();
703 Visit(expr->arguments()->at(i));
704 result.Union(av_);
705 }
706 av_ = result;
Andrei Popescu402d9372010-02-26 13:31:12 +0000707}
708
709
Steve Block6ded16b2010-05-10 14:33:55 +0100710void AssignedVariablesAnalyzer::VisitUnaryOperation(UnaryOperation* expr) {
711 ASSERT(av_.IsEmpty());
712 Visit(expr->expression());
Andrei Popescu402d9372010-02-26 13:31:12 +0000713}
714
715
Steve Block6ded16b2010-05-10 14:33:55 +0100716void AssignedVariablesAnalyzer::VisitCountOperation(CountOperation* expr) {
717 ASSERT(av_.IsEmpty());
718
719 Visit(expr->expression());
720
721 Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
722 if (var != NULL) RecordAssignedVar(var);
Andrei Popescu402d9372010-02-26 13:31:12 +0000723}
724
725
Steve Block6ded16b2010-05-10 14:33:55 +0100726void AssignedVariablesAnalyzer::VisitBinaryOperation(BinaryOperation* expr) {
727 ASSERT(av_.IsEmpty());
728 MarkIfTrivial(expr->right());
Andrei Popescu402d9372010-02-26 13:31:12 +0000729 Visit(expr->right());
Steve Block6ded16b2010-05-10 14:33:55 +0100730 MarkIfTrivial(expr->left());
731 ProcessExpression(expr->left());
Andrei Popescu402d9372010-02-26 13:31:12 +0000732}
733
734
Steve Block6ded16b2010-05-10 14:33:55 +0100735void AssignedVariablesAnalyzer::VisitCompareOperation(CompareOperation* expr) {
736 ASSERT(av_.IsEmpty());
737 MarkIfTrivial(expr->right());
738 Visit(expr->right());
739 MarkIfTrivial(expr->left());
740 ProcessExpression(expr->left());
Andrei Popescu402d9372010-02-26 13:31:12 +0000741}
742
743
Steve Block6ded16b2010-05-10 14:33:55 +0100744void AssignedVariablesAnalyzer::VisitThisFunction(ThisFunction* expr) {
745 // Nothing to do.
746 ASSERT(av_.IsEmpty());
747}
748
749
750void AssignedVariablesAnalyzer::VisitDeclaration(Declaration* decl) {
Andrei Popescu402d9372010-02-26 13:31:12 +0000751 UNREACHABLE();
752}
753
754
Leon Clarke4515c472010-02-03 11:58:03 +0000755} } // namespace v8::internal