OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 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 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
56 current_index_++; | 56 current_index_++; |
57 if (Done()) return; | 57 if (Done()) return; |
58 val = target_->data_[current_index_]; | 58 val = target_->data_[current_index_]; |
59 current_ = current_index_ << 5; | 59 current_ = current_index_ << 5; |
60 } | 60 } |
61 val = SkipZeroBytes(val); | 61 val = SkipZeroBytes(val); |
62 val = SkipZeroBits(val); | 62 val = SkipZeroBits(val); |
63 current_value_ = val >> 1; | 63 current_value_ = val >> 1; |
64 } | 64 } |
65 | 65 |
66 | |
67 bool AssignedVariablesAnalyzer::Analyze(CompilationInfo* info) { | |
68 Scope* scope = info->scope(); | |
69 int size = scope->num_parameters() + scope->num_stack_slots(); | |
70 if (size == 0) return true; | |
71 AssignedVariablesAnalyzer analyzer(info, size); | |
72 return analyzer.Analyze(); | |
73 } | |
74 | |
75 | |
76 AssignedVariablesAnalyzer::AssignedVariablesAnalyzer(CompilationInfo* info, | |
77 int size) | |
78 : info_(info), av_(size) { | |
79 } | |
80 | |
81 | |
82 bool AssignedVariablesAnalyzer::Analyze() { | |
83 ASSERT(av_.length() > 0); | |
84 VisitStatements(info_->function()->body()); | |
85 return !HasStackOverflow(); | |
86 } | |
87 | |
88 | |
89 Variable* AssignedVariablesAnalyzer::FindSmiLoopVariable(ForStatement* stmt) { | |
90 // The loop must have all necessary parts. | |
91 if (stmt->init() == NULL || stmt->cond() == NULL || stmt->next() == NULL) { | |
92 return NULL; | |
93 } | |
94 // The initialization statement has to be a simple assignment. | |
95 Assignment* init = stmt->init()->StatementAsSimpleAssignment(); | |
96 if (init == NULL) return NULL; | |
97 | |
98 // We only deal with local variables. | |
99 Variable* loop_var = init->target()->AsVariableProxy()->AsVariable(); | |
100 if (loop_var == NULL || !loop_var->IsStackAllocated()) return NULL; | |
101 | |
102 // Don't try to get clever with const or dynamic variables. | |
103 if (loop_var->mode() != Variable::VAR) return NULL; | |
104 | |
105 // The initial value has to be a smi. | |
106 Literal* init_lit = init->value()->AsLiteral(); | |
107 if (init_lit == NULL || !init_lit->handle()->IsSmi()) return NULL; | |
108 int init_value = Smi::cast(*init_lit->handle())->value(); | |
109 | |
110 // The condition must be a compare of variable with <, <=, >, or >=. | |
111 CompareOperation* cond = stmt->cond()->AsCompareOperation(); | |
112 if (cond == NULL) return NULL; | |
113 if (cond->op() != Token::LT | |
114 && cond->op() != Token::LTE | |
115 && cond->op() != Token::GT | |
116 && cond->op() != Token::GTE) return NULL; | |
117 | |
118 // The lhs must be the same variable as in the init expression. | |
119 if (cond->left()->AsVariableProxy()->AsVariable() != loop_var) return NULL; | |
120 | |
121 // The rhs must be a smi. | |
122 Literal* term_lit = cond->right()->AsLiteral(); | |
123 if (term_lit == NULL || !term_lit->handle()->IsSmi()) return NULL; | |
124 int term_value = Smi::cast(*term_lit->handle())->value(); | |
125 | |
126 // The count operation updates the same variable as in the init expression. | |
127 CountOperation* update = stmt->next()->StatementAsCountOperation(); | |
128 if (update == NULL) return NULL; | |
129 if (update->expression()->AsVariableProxy()->AsVariable() != loop_var) { | |
130 return NULL; | |
131 } | |
132 | |
133 // The direction of the count operation must agree with the start and the end | |
134 // value. We currently do not allow the initial value to be the same as the | |
135 // terminal value. This _would_ be ok as long as the loop body never executes | |
136 // or executes exactly one time. | |
137 if (init_value == term_value) return NULL; | |
138 if (init_value < term_value && update->op() != Token::INC) return NULL; | |
139 if (init_value > term_value && update->op() != Token::DEC) return NULL; | |
140 | |
141 // Check that the update operation cannot overflow the smi range. This can | |
142 // occur in the two cases where the loop bound is equal to the largest or | |
143 // smallest smi. | |
144 if (update->op() == Token::INC && term_value == Smi::kMaxValue) return NULL; | |
145 if (update->op() == Token::DEC && term_value == Smi::kMinValue) return NULL; | |
146 | |
147 // Found a smi loop variable. | |
148 return loop_var; | |
149 } | |
150 | |
151 int AssignedVariablesAnalyzer::BitIndex(Variable* var) { | |
152 ASSERT(var != NULL); | |
153 ASSERT(var->IsStackAllocated()); | |
154 Slot* slot = var->AsSlot(); | |
155 if (slot->type() == Slot::PARAMETER) { | |
156 return slot->index(); | |
157 } else { | |
158 return info_->scope()->num_parameters() + slot->index(); | |
159 } | |
160 } | |
161 | |
162 | |
163 void AssignedVariablesAnalyzer::RecordAssignedVar(Variable* var) { | |
164 ASSERT(var != NULL); | |
165 if (var->IsStackAllocated()) { | |
166 av_.Add(BitIndex(var)); | |
167 } | |
168 } | |
169 | |
170 | |
171 void AssignedVariablesAnalyzer::MarkIfTrivial(Expression* expr) { | |
172 Variable* var = expr->AsVariableProxy()->AsVariable(); | |
173 if (var != NULL && | |
174 var->IsStackAllocated() && | |
175 !var->is_arguments() && | |
176 var->mode() != Variable::CONST && | |
177 (var->is_this() || !av_.Contains(BitIndex(var)))) { | |
178 expr->AsVariableProxy()->MarkAsTrivial(); | |
179 } | |
180 } | |
181 | |
182 | |
183 void AssignedVariablesAnalyzer::ProcessExpression(Expression* expr) { | |
184 BitVector saved_av(av_); | |
185 av_.Clear(); | |
186 Visit(expr); | |
187 av_.Union(saved_av); | |
188 } | |
189 | |
190 void AssignedVariablesAnalyzer::VisitBlock(Block* stmt) { | |
191 VisitStatements(stmt->statements()); | |
192 } | |
193 | |
194 | |
195 void AssignedVariablesAnalyzer::VisitExpressionStatement( | |
196 ExpressionStatement* stmt) { | |
197 ProcessExpression(stmt->expression()); | |
198 } | |
199 | |
200 | |
201 void AssignedVariablesAnalyzer::VisitEmptyStatement(EmptyStatement* stmt) { | |
202 // Do nothing. | |
203 } | |
204 | |
205 | |
206 void AssignedVariablesAnalyzer::VisitIfStatement(IfStatement* stmt) { | |
207 ProcessExpression(stmt->condition()); | |
208 Visit(stmt->then_statement()); | |
209 Visit(stmt->else_statement()); | |
210 } | |
211 | |
212 | |
213 void AssignedVariablesAnalyzer::VisitContinueStatement( | |
214 ContinueStatement* stmt) { | |
215 // Nothing to do. | |
216 } | |
217 | |
218 | |
219 void AssignedVariablesAnalyzer::VisitBreakStatement(BreakStatement* stmt) { | |
220 // Nothing to do. | |
221 } | |
222 | |
223 | |
224 void AssignedVariablesAnalyzer::VisitReturnStatement(ReturnStatement* stmt) { | |
225 ProcessExpression(stmt->expression()); | |
226 } | |
227 | |
228 | |
229 void AssignedVariablesAnalyzer::VisitWithEnterStatement( | |
230 WithEnterStatement* stmt) { | |
231 ProcessExpression(stmt->expression()); | |
232 } | |
233 | |
234 | |
235 void AssignedVariablesAnalyzer::VisitWithExitStatement( | |
236 WithExitStatement* stmt) { | |
237 // Nothing to do. | |
238 } | |
239 | |
240 | |
241 void AssignedVariablesAnalyzer::VisitSwitchStatement(SwitchStatement* stmt) { | |
242 BitVector result(av_); | |
243 av_.Clear(); | |
244 Visit(stmt->tag()); | |
245 result.Union(av_); | |
246 for (int i = 0; i < stmt->cases()->length(); i++) { | |
247 CaseClause* clause = stmt->cases()->at(i); | |
248 if (!clause->is_default()) { | |
249 av_.Clear(); | |
250 Visit(clause->label()); | |
251 result.Union(av_); | |
252 } | |
253 VisitStatements(clause->statements()); | |
254 } | |
255 av_.Union(result); | |
256 } | |
257 | |
258 | |
259 void AssignedVariablesAnalyzer::VisitDoWhileStatement(DoWhileStatement* stmt) { | |
260 ProcessExpression(stmt->cond()); | |
261 Visit(stmt->body()); | |
262 } | |
263 | |
264 | |
265 void AssignedVariablesAnalyzer::VisitWhileStatement(WhileStatement* stmt) { | |
266 ProcessExpression(stmt->cond()); | |
267 Visit(stmt->body()); | |
268 } | |
269 | |
270 | |
271 void AssignedVariablesAnalyzer::VisitForStatement(ForStatement* stmt) { | |
272 if (stmt->init() != NULL) Visit(stmt->init()); | |
273 if (stmt->cond() != NULL) ProcessExpression(stmt->cond()); | |
274 if (stmt->next() != NULL) Visit(stmt->next()); | |
275 | |
276 // Process loop body. After visiting the loop body av_ contains | |
277 // the assigned variables of the loop body. | |
278 BitVector saved_av(av_); | |
279 av_.Clear(); | |
280 Visit(stmt->body()); | |
281 | |
282 Variable* var = FindSmiLoopVariable(stmt); | |
283 if (var != NULL && !av_.Contains(BitIndex(var))) { | |
284 stmt->set_loop_variable(var); | |
285 } | |
286 av_.Union(saved_av); | |
287 } | |
288 | |
289 | |
290 void AssignedVariablesAnalyzer::VisitForInStatement(ForInStatement* stmt) { | |
291 ProcessExpression(stmt->each()); | |
292 ProcessExpression(stmt->enumerable()); | |
293 Visit(stmt->body()); | |
294 } | |
295 | |
296 | |
297 void AssignedVariablesAnalyzer::VisitTryCatchStatement( | |
298 TryCatchStatement* stmt) { | |
299 Visit(stmt->try_block()); | |
300 Visit(stmt->catch_block()); | |
301 } | |
302 | |
303 | |
304 void AssignedVariablesAnalyzer::VisitTryFinallyStatement( | |
305 TryFinallyStatement* stmt) { | |
306 Visit(stmt->try_block()); | |
307 Visit(stmt->finally_block()); | |
308 } | |
309 | |
310 | |
311 void AssignedVariablesAnalyzer::VisitDebuggerStatement( | |
312 DebuggerStatement* stmt) { | |
313 // Nothing to do. | |
314 } | |
315 | |
316 | |
317 void AssignedVariablesAnalyzer::VisitFunctionLiteral(FunctionLiteral* expr) { | |
318 // Nothing to do. | |
319 ASSERT(av_.IsEmpty()); | |
320 } | |
321 | |
322 | |
323 void AssignedVariablesAnalyzer::VisitSharedFunctionInfoLiteral( | |
324 SharedFunctionInfoLiteral* expr) { | |
325 // Nothing to do. | |
326 ASSERT(av_.IsEmpty()); | |
327 } | |
328 | |
329 | |
330 void AssignedVariablesAnalyzer::VisitConditional(Conditional* expr) { | |
331 ASSERT(av_.IsEmpty()); | |
332 | |
333 Visit(expr->condition()); | |
334 | |
335 BitVector result(av_); | |
336 av_.Clear(); | |
337 Visit(expr->then_expression()); | |
338 result.Union(av_); | |
339 | |
340 av_.Clear(); | |
341 Visit(expr->else_expression()); | |
342 av_.Union(result); | |
343 } | |
344 | |
345 | |
346 void AssignedVariablesAnalyzer::VisitVariableProxy(VariableProxy* expr) { | |
347 // Nothing to do. | |
348 ASSERT(av_.IsEmpty()); | |
349 } | |
350 | |
351 | |
352 void AssignedVariablesAnalyzer::VisitLiteral(Literal* expr) { | |
353 // Nothing to do. | |
354 ASSERT(av_.IsEmpty()); | |
355 } | |
356 | |
357 | |
358 void AssignedVariablesAnalyzer::VisitRegExpLiteral(RegExpLiteral* expr) { | |
359 // Nothing to do. | |
360 ASSERT(av_.IsEmpty()); | |
361 } | |
362 | |
363 | |
364 void AssignedVariablesAnalyzer::VisitObjectLiteral(ObjectLiteral* expr) { | |
365 ASSERT(av_.IsEmpty()); | |
366 BitVector result(av_.length()); | |
367 for (int i = 0; i < expr->properties()->length(); i++) { | |
368 Visit(expr->properties()->at(i)->value()); | |
369 result.Union(av_); | |
370 av_.Clear(); | |
371 } | |
372 av_ = result; | |
373 } | |
374 | |
375 | |
376 void AssignedVariablesAnalyzer::VisitArrayLiteral(ArrayLiteral* expr) { | |
377 ASSERT(av_.IsEmpty()); | |
378 BitVector result(av_.length()); | |
379 for (int i = 0; i < expr->values()->length(); i++) { | |
380 Visit(expr->values()->at(i)); | |
381 result.Union(av_); | |
382 av_.Clear(); | |
383 } | |
384 av_ = result; | |
385 } | |
386 | |
387 | |
388 void AssignedVariablesAnalyzer::VisitCatchExtensionObject( | |
389 CatchExtensionObject* expr) { | |
390 ASSERT(av_.IsEmpty()); | |
391 Visit(expr->key()); | |
392 ProcessExpression(expr->value()); | |
393 } | |
394 | |
395 | |
396 void AssignedVariablesAnalyzer::VisitAssignment(Assignment* expr) { | |
397 ASSERT(av_.IsEmpty()); | |
398 | |
399 // There are three kinds of assignments: variable assignments, property | |
400 // assignments, and reference errors (invalid left-hand sides). | |
401 Variable* var = expr->target()->AsVariableProxy()->AsVariable(); | |
402 Property* prop = expr->target()->AsProperty(); | |
403 ASSERT(var == NULL || prop == NULL); | |
404 | |
405 if (var != NULL) { | |
406 MarkIfTrivial(expr->value()); | |
407 Visit(expr->value()); | |
408 if (expr->is_compound()) { | |
409 // Left-hand side occurs also as an rvalue. | |
410 MarkIfTrivial(expr->target()); | |
411 ProcessExpression(expr->target()); | |
412 } | |
413 RecordAssignedVar(var); | |
414 | |
415 } else if (prop != NULL) { | |
416 MarkIfTrivial(expr->value()); | |
417 Visit(expr->value()); | |
418 if (!prop->key()->IsPropertyName()) { | |
419 MarkIfTrivial(prop->key()); | |
420 ProcessExpression(prop->key()); | |
421 } | |
422 MarkIfTrivial(prop->obj()); | |
423 ProcessExpression(prop->obj()); | |
424 | |
425 } else { | |
426 Visit(expr->target()); | |
427 } | |
428 } | |
429 | |
430 | |
431 void AssignedVariablesAnalyzer::VisitThrow(Throw* expr) { | |
432 ASSERT(av_.IsEmpty()); | |
433 Visit(expr->exception()); | |
434 } | |
435 | |
436 | |
437 void AssignedVariablesAnalyzer::VisitProperty(Property* expr) { | |
438 ASSERT(av_.IsEmpty()); | |
439 if (!expr->key()->IsPropertyName()) { | |
440 MarkIfTrivial(expr->key()); | |
441 Visit(expr->key()); | |
442 } | |
443 MarkIfTrivial(expr->obj()); | |
444 ProcessExpression(expr->obj()); | |
445 } | |
446 | |
447 | |
448 void AssignedVariablesAnalyzer::VisitCall(Call* expr) { | |
449 ASSERT(av_.IsEmpty()); | |
450 Visit(expr->expression()); | |
451 BitVector result(av_); | |
452 for (int i = 0; i < expr->arguments()->length(); i++) { | |
453 av_.Clear(); | |
454 Visit(expr->arguments()->at(i)); | |
455 result.Union(av_); | |
456 } | |
457 av_ = result; | |
458 } | |
459 | |
460 | |
461 void AssignedVariablesAnalyzer::VisitCallNew(CallNew* expr) { | |
462 ASSERT(av_.IsEmpty()); | |
463 Visit(expr->expression()); | |
464 BitVector result(av_); | |
465 for (int i = 0; i < expr->arguments()->length(); i++) { | |
466 av_.Clear(); | |
467 Visit(expr->arguments()->at(i)); | |
468 result.Union(av_); | |
469 } | |
470 av_ = result; | |
471 } | |
472 | |
473 | |
474 void AssignedVariablesAnalyzer::VisitCallRuntime(CallRuntime* expr) { | |
475 ASSERT(av_.IsEmpty()); | |
476 BitVector result(av_); | |
477 for (int i = 0; i < expr->arguments()->length(); i++) { | |
478 av_.Clear(); | |
479 Visit(expr->arguments()->at(i)); | |
480 result.Union(av_); | |
481 } | |
482 av_ = result; | |
483 } | |
484 | |
485 | |
486 void AssignedVariablesAnalyzer::VisitUnaryOperation(UnaryOperation* expr) { | |
487 ASSERT(av_.IsEmpty()); | |
488 MarkIfTrivial(expr->expression()); | |
489 Visit(expr->expression()); | |
490 } | |
491 | |
492 | |
493 void AssignedVariablesAnalyzer::VisitCountOperation(CountOperation* expr) { | |
494 ASSERT(av_.IsEmpty()); | |
495 if (expr->is_prefix()) MarkIfTrivial(expr->expression()); | |
496 Visit(expr->expression()); | |
497 | |
498 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); | |
499 if (var != NULL) RecordAssignedVar(var); | |
500 } | |
501 | |
502 | |
503 void AssignedVariablesAnalyzer::VisitBinaryOperation(BinaryOperation* expr) { | |
504 ASSERT(av_.IsEmpty()); | |
505 MarkIfTrivial(expr->right()); | |
506 Visit(expr->right()); | |
507 MarkIfTrivial(expr->left()); | |
508 ProcessExpression(expr->left()); | |
509 } | |
510 | |
511 | |
512 void AssignedVariablesAnalyzer::VisitCompareOperation(CompareOperation* expr) { | |
513 ASSERT(av_.IsEmpty()); | |
514 MarkIfTrivial(expr->right()); | |
515 Visit(expr->right()); | |
516 MarkIfTrivial(expr->left()); | |
517 ProcessExpression(expr->left()); | |
518 } | |
519 | |
520 | |
521 void AssignedVariablesAnalyzer::VisitCompareToNull(CompareToNull* expr) { | |
522 ASSERT(av_.IsEmpty()); | |
523 MarkIfTrivial(expr->expression()); | |
524 Visit(expr->expression()); | |
525 } | |
526 | |
527 | |
528 void AssignedVariablesAnalyzer::VisitThisFunction(ThisFunction* expr) { | |
529 // Nothing to do. | |
530 ASSERT(av_.IsEmpty()); | |
531 } | |
532 | |
533 | |
534 void AssignedVariablesAnalyzer::VisitDeclaration(Declaration* decl) { | |
535 UNREACHABLE(); | |
536 } | |
537 | |
538 | |
539 } } // namespace v8::internal | 66 } } // namespace v8::internal |
OLD | NEW |