The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.

Please select the desired protocol below to get the URL.

This URL has Read-Only access.

Statistics
| Branch: | Revision:

main_repo / deps / v8 / src / rewriter.cc @ 40c0f755

History | View | Annotate | Download (20.7 KB)

1
// Copyright 2006-2008 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 "ast.h"
31
#include "func-name-inferrer.h"
32
#include "scopes.h"
33
#include "rewriter.h"
34

    
35
namespace v8 { namespace internal {
36

    
37

    
38
class AstOptimizer: public AstVisitor {
39
 public:
40
  explicit AstOptimizer() {}
41
  explicit AstOptimizer(Handle<String> enclosing_name) {
42
    func_name_inferrer_.PushEnclosingName(enclosing_name);
43
  }
44

    
45
  void Optimize(ZoneList<Statement*>* statements);
46

    
47
 private:
48
  // Used for loop condition analysis.  Cleared before visiting a loop
49
  // condition, set when a function literal is visited.
50
  bool has_function_literal_;
51
  // Helper object for function name inferring.
52
  FuncNameInferrer func_name_inferrer_;
53

    
54
  // Helpers
55
  void OptimizeArguments(ZoneList<Expression*>* arguments);
56

    
57
  // Node visitors.
58
#define DEF_VISIT(type) \
59
  virtual void Visit##type(type* node);
60
  NODE_LIST(DEF_VISIT)
61
#undef DEF_VISIT
62

    
63
  DISALLOW_COPY_AND_ASSIGN(AstOptimizer);
64
};
65

    
66

    
67
void AstOptimizer::Optimize(ZoneList<Statement*>* statements) {
68
  int len = statements->length();
69
  for (int i = 0; i < len; i++) {
70
    Visit(statements->at(i));
71
  }
72
}
73

    
74

    
75
void AstOptimizer::OptimizeArguments(ZoneList<Expression*>* arguments) {
76
  for (int i = 0; i < arguments->length(); i++) {
77
    Visit(arguments->at(i));
78
  }
79
}
80

    
81

    
82
void AstOptimizer::VisitBlock(Block* node) {
83
  Optimize(node->statements());
84
}
85

    
86

    
87
void AstOptimizer::VisitExpressionStatement(ExpressionStatement* node) {
88
  Visit(node->expression());
89
}
90

    
91

    
92
void AstOptimizer::VisitIfStatement(IfStatement* node) {
93
  Visit(node->condition());
94
  Visit(node->then_statement());
95
  if (node->HasElseStatement()) {
96
    Visit(node->else_statement());
97
  }
98
}
99

    
100

    
101
void AstOptimizer::VisitLoopStatement(LoopStatement* node) {
102
  if (node->init() != NULL) {
103
    Visit(node->init());
104
  }
105
  if (node->cond() != NULL) {
106
    has_function_literal_ = false;
107
    Visit(node->cond());
108
    node->may_have_function_literal_ = has_function_literal_;
109
  }
110
  if (node->body() != NULL) {
111
    Visit(node->body());
112
  }
113
  if (node->next() != NULL) {
114
    Visit(node->next());
115
  }
116
}
117

    
118

    
119
void AstOptimizer::VisitForInStatement(ForInStatement* node) {
120
  Visit(node->each());
121
  Visit(node->enumerable());
122
  Visit(node->body());
123
}
124

    
125

    
126
void AstOptimizer::VisitTryCatch(TryCatch* node) {
127
  Visit(node->try_block());
128
  Visit(node->catch_var());
129
  Visit(node->catch_block());
130
}
131

    
132

    
133
void AstOptimizer::VisitTryFinally(TryFinally* node) {
134
  Visit(node->try_block());
135
  Visit(node->finally_block());
136
}
137

    
138

    
139
void AstOptimizer::VisitSwitchStatement(SwitchStatement* node) {
140
  Visit(node->tag());
141
  for (int i = 0; i < node->cases()->length(); i++) {
142
    CaseClause* clause = node->cases()->at(i);
143
    if (!clause->is_default()) {
144
      Visit(clause->label());
145
    }
146
    Optimize(clause->statements());
147
  }
148
}
149

    
150

    
151
void AstOptimizer::VisitContinueStatement(ContinueStatement* node) {
152
  USE(node);
153
}
154

    
155

    
156
void AstOptimizer::VisitBreakStatement(BreakStatement* node) {
157
  USE(node);
158
}
159

    
160

    
161
void AstOptimizer::VisitDeclaration(Declaration* node) {
162
  // Will not be reached by the current optimizations.
163
  USE(node);
164
}
165

    
166

    
167
void AstOptimizer::VisitEmptyStatement(EmptyStatement* node) {
168
  USE(node);
169
}
170

    
171

    
172
void AstOptimizer::VisitReturnStatement(ReturnStatement* node) {
173
  Visit(node->expression());
174
}
175

    
176

    
177
void AstOptimizer::VisitWithEnterStatement(WithEnterStatement* node) {
178
  Visit(node->expression());
179
}
180

    
181

    
182
void AstOptimizer::VisitWithExitStatement(WithExitStatement* node) {
183
  USE(node);
184
}
185

    
186

    
187
void AstOptimizer::VisitDebuggerStatement(DebuggerStatement* node) {
188
  USE(node);
189
}
190

    
191

    
192
void AstOptimizer::VisitFunctionLiteral(FunctionLiteral* node) {
193
  has_function_literal_ = true;
194

    
195
  if (node->name()->length() == 0) {
196
    // Anonymous function.
197
    func_name_inferrer_.SetFuncToInfer(node);
198
  }
199
}
200

    
201

    
202
void AstOptimizer::VisitFunctionBoilerplateLiteral(
203
    FunctionBoilerplateLiteral* node) {
204
  USE(node);
205
}
206

    
207

    
208
void AstOptimizer::VisitConditional(Conditional* node) {
209
  Visit(node->condition());
210
  Visit(node->then_expression());
211
  Visit(node->else_expression());
212
}
213

    
214

    
215
void AstOptimizer::VisitSlot(Slot* node) {
216
  USE(node);
217
}
218

    
219

    
220
void AstOptimizer::VisitVariableProxy(VariableProxy* node) {
221
  Variable* var = node->AsVariable();
222
  if (var != NULL) {
223
    if (var->type()->IsKnown()) {
224
      node->type()->CopyFrom(var->type());
225
    } else if (node->type()->IsLikelySmi()) {
226
      var->type()->SetAsLikelySmi();
227
    }
228

    
229
    if (!var->is_this() &&
230
        !Heap::result_symbol()->Equals(*var->name())) {
231
      func_name_inferrer_.PushName(var->name());
232
    }
233
  }
234
}
235

    
236

    
237
void AstOptimizer::VisitLiteral(Literal* node) {
238
  Handle<Object> literal = node->handle();
239
  if (literal->IsSmi()) {
240
    node->type()->SetAsLikelySmi();
241
  } else if (literal->IsString()) {
242
    Handle<String> lit_str(Handle<String>::cast(literal));
243
    if (!Heap::prototype_symbol()->Equals(*lit_str)) {
244
      func_name_inferrer_.PushName(lit_str);
245
    }
246
  }
247
}
248

    
249

    
250
void AstOptimizer::VisitRegExpLiteral(RegExpLiteral* node) {
251
  USE(node);
252
}
253

    
254

    
255
void AstOptimizer::VisitArrayLiteral(ArrayLiteral* node) {
256
  for (int i = 0; i < node->values()->length(); i++) {
257
    Visit(node->values()->at(i));
258
  }
259
}
260

    
261
void AstOptimizer::VisitObjectLiteral(ObjectLiteral* node) {
262
  for (int i = 0; i < node->properties()->length(); i++) {
263
    ScopedFuncNameInferrer scoped_fni(&func_name_inferrer_);
264
    scoped_fni.Enter();
265
    Visit(node->properties()->at(i)->key());
266
    Visit(node->properties()->at(i)->value());
267
  }
268
}
269

    
270

    
271
void AstOptimizer::VisitCatchExtensionObject(CatchExtensionObject* node) {
272
  Visit(node->key());
273
  Visit(node->value());
274
}
275

    
276

    
277
void AstOptimizer::VisitAssignment(Assignment* node) {
278
  ScopedFuncNameInferrer scoped_fni(&func_name_inferrer_);
279
  switch (node->op()) {
280
    case Token::INIT_VAR:
281
    case Token::INIT_CONST:
282
    case Token::ASSIGN:
283
      // No type can be infered from the general assignment.
284

    
285
      if (node->value()->AsFunctionLiteral() != NULL ||
286
          node->value()->AsObjectLiteral() != NULL) {
287
        scoped_fni.Enter();
288
      }
289
      break;
290
    case Token::ASSIGN_BIT_OR:
291
    case Token::ASSIGN_BIT_XOR:
292
    case Token::ASSIGN_BIT_AND:
293
    case Token::ASSIGN_SHL:
294
    case Token::ASSIGN_SAR:
295
    case Token::ASSIGN_SHR:
296
      node->type()->SetAsLikelySmiIfUnknown();
297
      node->target()->type()->SetAsLikelySmiIfUnknown();
298
      node->value()->type()->SetAsLikelySmiIfUnknown();
299
      break;
300
    case Token::ASSIGN_ADD:
301
    case Token::ASSIGN_SUB:
302
    case Token::ASSIGN_MUL:
303
    case Token::ASSIGN_DIV:
304
    case Token::ASSIGN_MOD:
305
      if (node->type()->IsLikelySmi()) {
306
        node->target()->type()->SetAsLikelySmiIfUnknown();
307
        node->value()->type()->SetAsLikelySmiIfUnknown();
308
      }
309
      break;
310
    default:
311
      UNREACHABLE();
312
      break;
313
  }
314

    
315
  Visit(node->target());
316
  Visit(node->value());
317

    
318
  switch (node->op()) {
319
    case Token::INIT_VAR:
320
    case Token::INIT_CONST:
321
    case Token::ASSIGN:
322
      // Pure assignment copies the type from the value.
323
      node->type()->CopyFrom(node->value()->type());
324
      break;
325
    case Token::ASSIGN_BIT_OR:
326
    case Token::ASSIGN_BIT_XOR:
327
    case Token::ASSIGN_BIT_AND:
328
    case Token::ASSIGN_SHL:
329
    case Token::ASSIGN_SAR:
330
    case Token::ASSIGN_SHR:
331
      // Should have been setup above already.
332
      break;
333
    case Token::ASSIGN_ADD:
334
    case Token::ASSIGN_SUB:
335
    case Token::ASSIGN_MUL:
336
    case Token::ASSIGN_DIV:
337
    case Token::ASSIGN_MOD:
338
      if (node->type()->IsUnknown()) {
339
        if (node->target()->type()->IsLikelySmi() ||
340
            node->value()->type()->IsLikelySmi()) {
341
          node->type()->SetAsLikelySmi();
342
        }
343
      }
344
      break;
345
    default:
346
      UNREACHABLE();
347
      break;
348
  }
349

    
350
  // Since this is an assignment. We have to propagate this node's type to the
351
  // variable.
352
  VariableProxy* proxy = node->target()->AsVariableProxy();
353
  if (proxy != NULL) {
354
    Variable* var = proxy->AsVariable();
355
    if (var != NULL) {
356
      SmiAnalysis* var_type = var->type();
357
      if (var_type->IsUnknown()) {
358
        var_type->CopyFrom(node->type());
359
      } else if (var_type->IsLikelySmi()) {
360
        // We do not reset likely types to Unknown.
361
      }
362
    }
363
  }
364
}
365

    
366

    
367
void AstOptimizer::VisitThrow(Throw* node) {
368
  Visit(node->exception());
369
}
370

    
371

    
372
void AstOptimizer::VisitProperty(Property* node) {
373
  Visit(node->obj());
374
  Visit(node->key());
375
}
376

    
377

    
378
void AstOptimizer::VisitCall(Call* node) {
379
  Visit(node->expression());
380
  OptimizeArguments(node->arguments());
381
}
382

    
383

    
384
void AstOptimizer::VisitCallEval(CallEval* node) {
385
  Visit(node->expression());
386
  OptimizeArguments(node->arguments());
387
}
388

    
389

    
390
void AstOptimizer::VisitCallNew(CallNew* node) {
391
  Visit(node->expression());
392
  OptimizeArguments(node->arguments());
393
}
394

    
395

    
396
void AstOptimizer::VisitCallRuntime(CallRuntime* node) {
397
  ScopedFuncNameInferrer scoped_fni(&func_name_inferrer_);
398
  if (Factory::InitializeVarGlobal_symbol()->Equals(*node->name()) &&
399
      node->arguments()->length() >= 2 &&
400
      node->arguments()->at(1)->AsFunctionLiteral() != NULL) {
401
      scoped_fni.Enter();
402
  }
403
  OptimizeArguments(node->arguments());
404
}
405

    
406

    
407
void AstOptimizer::VisitUnaryOperation(UnaryOperation* node) {
408
  Visit(node->expression());
409
}
410

    
411

    
412
void AstOptimizer::VisitCountOperation(CountOperation* node) {
413
  // Count operations assume that they work on Smis.
414
  node->type()->SetAsLikelySmiIfUnknown();
415
  node->expression()->type()->SetAsLikelySmiIfUnknown();
416
  Visit(node->expression());
417
}
418

    
419

    
420
void AstOptimizer::VisitBinaryOperation(BinaryOperation* node) {
421
  // Depending on the operation we can propagate this node's type down the
422
  // AST nodes.
423
  switch (node->op()) {
424
    case Token::COMMA:
425
    case Token::OR:
426
    case Token::AND:
427
      break;
428
    case Token::BIT_OR:
429
    case Token::BIT_XOR:
430
    case Token::BIT_AND:
431
    case Token::SHL:
432
    case Token::SAR:
433
    case Token::SHR:
434
      node->type()->SetAsLikelySmiIfUnknown();
435
      node->left()->type()->SetAsLikelySmiIfUnknown();
436
      node->right()->type()->SetAsLikelySmiIfUnknown();
437
      break;
438
    case Token::ADD:
439
    case Token::SUB:
440
    case Token::MUL:
441
    case Token::DIV:
442
    case Token::MOD:
443
      if (node->type()->IsLikelySmi()) {
444
        node->left()->type()->SetAsLikelySmiIfUnknown();
445
        node->right()->type()->SetAsLikelySmiIfUnknown();
446
      }
447
      break;
448
    default:
449
      UNREACHABLE();
450
      break;
451
  }
452

    
453
  Visit(node->left());
454
  Visit(node->right());
455

    
456
  // After visiting the operand nodes we have to check if this node's type
457
  // can be updated. If it does, then we can push that information down
458
  // towards the leafs again if the new information is an upgrade over the
459
  // previous type of the operand nodes.
460
  if (node->type()->IsUnknown()) {
461
    if (node->left()->type()->IsLikelySmi() ||
462
        node->right()->type()->IsLikelySmi()) {
463
      node->type()->SetAsLikelySmi();
464
    }
465
    if (node->type()->IsLikelySmi()) {
466
      // The type of this node changed to LIKELY_SMI. Propagate this knowledge
467
      // down through the nodes.
468
      if (node->left()->type()->IsUnknown()) {
469
        node->left()->type()->SetAsLikelySmi();
470
        Visit(node->left());
471
      }
472
      if (node->right()->type()->IsUnknown()) {
473
        node->right()->type()->SetAsLikelySmi();
474
        Visit(node->right());
475
      }
476
    }
477
  }
478
}
479

    
480

    
481
void AstOptimizer::VisitCompareOperation(CompareOperation* node) {
482
  if (node->type()->IsKnown()) {
483
    // Propagate useful information down towards the leafs.
484
    node->left()->type()->SetAsLikelySmiIfUnknown();
485
    node->right()->type()->SetAsLikelySmiIfUnknown();
486
  }
487

    
488
  Visit(node->left());
489
  Visit(node->right());
490

    
491
  // After visiting the operand nodes we have to check if this node's type
492
  // can be updated. If it does, then we can push that information down
493
  // towards the leafs again if the new information is an upgrade over the
494
  // previous type of the operand nodes.
495
  if (node->type()->IsUnknown()) {
496
    if (node->left()->type()->IsLikelySmi() ||
497
        node->right()->type()->IsLikelySmi()) {
498
      node->type()->SetAsLikelySmi();
499
    }
500
    if (node->type()->IsLikelySmi()) {
501
      // The type of this node changed to LIKELY_SMI. Propagate this knowledge
502
      // down through the nodes.
503
      if (node->left()->type()->IsUnknown()) {
504
        node->left()->type()->SetAsLikelySmi();
505
        Visit(node->left());
506
      }
507
      if (node->right()->type()->IsUnknown()) {
508
        node->right()->type()->SetAsLikelySmi();
509
        Visit(node->right());
510
      }
511
    }
512
  }
513
}
514

    
515

    
516
void AstOptimizer::VisitThisFunction(ThisFunction* node) {
517
  USE(node);
518
}
519

    
520

    
521
class Processor: public AstVisitor {
522
 public:
523
  explicit Processor(VariableProxy* result)
524
      : result_(result),
525
        result_assigned_(false),
526
        is_set_(false),
527
        in_try_(false) {
528
  }
529

    
530
  void Process(ZoneList<Statement*>* statements);
531
  bool result_assigned() const  { return result_assigned_; }
532

    
533
 private:
534
  VariableProxy* result_;
535

    
536
  // We are not tracking result usage via the result_'s use
537
  // counts (we leave the accurate computation to the
538
  // usage analyzer). Instead we simple remember if
539
  // there was ever an assignment to result_.
540
  bool result_assigned_;
541

    
542
  // To avoid storing to .result all the time, we eliminate some of
543
  // the stores by keeping track of whether or not we're sure .result
544
  // will be overwritten anyway. This is a bit more tricky than what I
545
  // was hoping for
546
  bool is_set_;
547
  bool in_try_;
548

    
549
  Expression* SetResult(Expression* value) {
550
    result_assigned_ = true;
551
    return new Assignment(Token::ASSIGN, result_, value,
552
                          RelocInfo::kNoPosition);
553
  }
554

    
555
  // Node visitors.
556
#define DEF_VISIT(type) \
557
  virtual void Visit##type(type* node);
558
  NODE_LIST(DEF_VISIT)
559
#undef DEF_VISIT
560
};
561

    
562

    
563
void Processor::Process(ZoneList<Statement*>* statements) {
564
  for (int i = statements->length() - 1; i >= 0; --i) {
565
    Visit(statements->at(i));
566
  }
567
}
568

    
569

    
570
void Processor::VisitBlock(Block* node) {
571
  // An initializer block is the rewritten form of a variable declaration
572
  // with initialization expressions. The initializer block contains the
573
  // list of assignments corresponding to the initialization expressions.
574
  // While unclear from the spec (ECMA-262, 3rd., 12.2), the value of
575
  // a variable declaration with initialization expression is 'undefined'
576
  // with some JS VMs: For instance, using smjs, print(eval('var x = 7'))
577
  // returns 'undefined'. To obtain the same behavior with v8, we need
578
  // to prevent rewriting in that case.
579
  if (!node->is_initializer_block()) Process(node->statements());
580
}
581

    
582

    
583
void Processor::VisitExpressionStatement(ExpressionStatement* node) {
584
  // Rewrite : <x>; -> .result = <x>;
585
  if (!is_set_) {
586
    node->set_expression(SetResult(node->expression()));
587
    if (!in_try_) is_set_ = true;
588
  }
589
}
590

    
591

    
592
void Processor::VisitIfStatement(IfStatement* node) {
593
  // Rewrite both then and else parts (reversed).
594
  bool save = is_set_;
595
  Visit(node->else_statement());
596
  bool set_after_then = is_set_;
597
  is_set_ = save;
598
  Visit(node->then_statement());
599
  is_set_ = is_set_ && set_after_then;
600
}
601

    
602

    
603

    
604

    
605
void Processor::VisitLoopStatement(LoopStatement* node) {
606
  // Rewrite loop body statement.
607
  bool set_after_loop = is_set_;
608
  Visit(node->body());
609
  is_set_ = is_set_ && set_after_loop;
610
}
611

    
612

    
613
void Processor::VisitForInStatement(ForInStatement* node) {
614
  // Rewrite for-in body statement.
615
  bool set_after_for = is_set_;
616
  Visit(node->body());
617
  is_set_ = is_set_ && set_after_for;
618
}
619

    
620

    
621
void Processor::VisitTryCatch(TryCatch* node) {
622
  // Rewrite both try and catch blocks (reversed order).
623
  bool set_after_catch = is_set_;
624
  Visit(node->catch_block());
625
  is_set_ = is_set_ && set_after_catch;
626
  bool save = in_try_;
627
  in_try_ = true;
628
  Visit(node->try_block());
629
  in_try_ = save;
630
}
631

    
632

    
633
void Processor::VisitTryFinally(TryFinally* node) {
634
  // Rewrite both try and finally block (reversed order).
635
  Visit(node->finally_block());
636
  bool save = in_try_;
637
  in_try_ = true;
638
  Visit(node->try_block());
639
  in_try_ = save;
640
}
641

    
642

    
643
void Processor::VisitSwitchStatement(SwitchStatement* node) {
644
  // Rewrite statements in all case clauses in reversed order.
645
  ZoneList<CaseClause*>* clauses = node->cases();
646
  bool set_after_switch = is_set_;
647
  for (int i = clauses->length() - 1; i >= 0; --i) {
648
    CaseClause* clause = clauses->at(i);
649
    Process(clause->statements());
650
  }
651
  is_set_ = is_set_ && set_after_switch;
652
}
653

    
654

    
655
void Processor::VisitContinueStatement(ContinueStatement* node) {
656
  is_set_ = false;
657
}
658

    
659

    
660
void Processor::VisitBreakStatement(BreakStatement* node) {
661
  is_set_ = false;
662
}
663

    
664

    
665
// Do nothing:
666
void Processor::VisitDeclaration(Declaration* node) {}
667
void Processor::VisitEmptyStatement(EmptyStatement* node) {}
668
void Processor::VisitReturnStatement(ReturnStatement* node) {}
669
void Processor::VisitWithEnterStatement(WithEnterStatement* node) {}
670
void Processor::VisitWithExitStatement(WithExitStatement* node) {}
671
void Processor::VisitDebuggerStatement(DebuggerStatement* node) {}
672

    
673

    
674
// Expressions are never visited yet.
675
void Processor::VisitFunctionLiteral(FunctionLiteral* node) {
676
  USE(node);
677
  UNREACHABLE();
678
}
679

    
680

    
681
void Processor::VisitFunctionBoilerplateLiteral(
682
    FunctionBoilerplateLiteral* node) {
683
  USE(node);
684
  UNREACHABLE();
685
}
686

    
687

    
688
void Processor::VisitConditional(Conditional* node) {
689
  USE(node);
690
  UNREACHABLE();
691
}
692

    
693

    
694
void Processor::VisitSlot(Slot* node) {
695
  USE(node);
696
  UNREACHABLE();
697
}
698

    
699

    
700
void Processor::VisitVariableProxy(VariableProxy* node) {
701
  USE(node);
702
  UNREACHABLE();
703
}
704

    
705

    
706
void Processor::VisitLiteral(Literal* node) {
707
  USE(node);
708
  UNREACHABLE();
709
}
710

    
711

    
712
void Processor::VisitRegExpLiteral(RegExpLiteral* node) {
713
  USE(node);
714
  UNREACHABLE();
715
}
716

    
717

    
718
void Processor::VisitArrayLiteral(ArrayLiteral* node) {
719
  USE(node);
720
  UNREACHABLE();
721
}
722

    
723

    
724
void Processor::VisitObjectLiteral(ObjectLiteral* node) {
725
  USE(node);
726
  UNREACHABLE();
727
}
728

    
729

    
730
void Processor::VisitCatchExtensionObject(CatchExtensionObject* node) {
731
  USE(node);
732
  UNREACHABLE();
733
}
734

    
735

    
736
void Processor::VisitAssignment(Assignment* node) {
737
  USE(node);
738
  UNREACHABLE();
739
}
740

    
741

    
742
void Processor::VisitThrow(Throw* node) {
743
  USE(node);
744
  UNREACHABLE();
745
}
746

    
747

    
748
void Processor::VisitProperty(Property* node) {
749
  USE(node);
750
  UNREACHABLE();
751
}
752

    
753

    
754
void Processor::VisitCall(Call* node) {
755
  USE(node);
756
  UNREACHABLE();
757
}
758

    
759

    
760
void Processor::VisitCallEval(CallEval* node) {
761
  USE(node);
762
  UNREACHABLE();
763
}
764

    
765

    
766
void Processor::VisitCallNew(CallNew* node) {
767
  USE(node);
768
  UNREACHABLE();
769
}
770

    
771

    
772
void Processor::VisitCallRuntime(CallRuntime* node) {
773
  USE(node);
774
  UNREACHABLE();
775
}
776

    
777

    
778
void Processor::VisitUnaryOperation(UnaryOperation* node) {
779
  USE(node);
780
  UNREACHABLE();
781
}
782

    
783

    
784
void Processor::VisitCountOperation(CountOperation* node) {
785
  USE(node);
786
  UNREACHABLE();
787
}
788

    
789

    
790
void Processor::VisitBinaryOperation(BinaryOperation* node) {
791
  USE(node);
792
  UNREACHABLE();
793
}
794

    
795

    
796
void Processor::VisitCompareOperation(CompareOperation* node) {
797
  USE(node);
798
  UNREACHABLE();
799
}
800

    
801

    
802
void Processor::VisitThisFunction(ThisFunction* node) {
803
  USE(node);
804
  UNREACHABLE();
805
}
806

    
807

    
808
bool Rewriter::Process(FunctionLiteral* function) {
809
  Scope* scope = function->scope();
810
  if (scope->is_function_scope()) return true;
811

    
812
  ZoneList<Statement*>* body = function->body();
813
  if (body->is_empty()) return true;
814

    
815
  VariableProxy* result = scope->NewTemporary(Factory::result_symbol());
816
  Processor processor(result);
817
  processor.Process(body);
818
  if (processor.HasStackOverflow()) return false;
819

    
820
  if (processor.result_assigned()) body->Add(new ReturnStatement(result));
821
  return true;
822
}
823

    
824

    
825
bool Rewriter::Optimize(FunctionLiteral* function) {
826
  ZoneList<Statement*>* body = function->body();
827

    
828
  if (FLAG_optimize_ast && !body->is_empty()) {
829
    AstOptimizer optimizer(function->name());
830
    optimizer.Optimize(body);
831
    if (optimizer.HasStackOverflow()) {
832
      return false;
833
    }
834
  }
835
  return true;
836
}
837

    
838

    
839
} }  // namespace v8::internal