f5a2e0fcad519346d694953ed461cc7514548d40
[platform/upstream/nodejs.git] / deps / v8 / src / compiler / ast-graph-builder.cc
1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "src/compiler/ast-graph-builder.h"
6
7 #include "src/compiler.h"
8 #include "src/compiler/ast-loop-assignment-analyzer.h"
9 #include "src/compiler/control-builders.h"
10 #include "src/compiler/linkage.h"
11 #include "src/compiler/machine-operator.h"
12 #include "src/compiler/node-matchers.h"
13 #include "src/compiler/node-properties.h"
14 #include "src/compiler/operator-properties.h"
15 #include "src/full-codegen.h"
16 #include "src/parser.h"
17 #include "src/scopes.h"
18
19 namespace v8 {
20 namespace internal {
21 namespace compiler {
22
23
24 // Each expression in the AST is evaluated in a specific context. This context
25 // decides how the evaluation result is passed up the visitor.
26 class AstGraphBuilder::AstContext BASE_EMBEDDED {
27  public:
28   bool IsEffect() const { return kind_ == Expression::kEffect; }
29   bool IsValue() const { return kind_ == Expression::kValue; }
30   bool IsTest() const { return kind_ == Expression::kTest; }
31
32   // Determines how to combine the frame state with the value
33   // that is about to be plugged into this AstContext.
34   OutputFrameStateCombine GetStateCombine() {
35     return IsEffect() ? OutputFrameStateCombine::Ignore()
36                       : OutputFrameStateCombine::Push();
37   }
38
39   // Plug a node into this expression context.  Call this function in tail
40   // position in the Visit functions for expressions.
41   virtual void ProduceValue(Node* value) = 0;
42
43   // Unplugs a node from this expression context.  Call this to retrieve the
44   // result of another Visit function that already plugged the context.
45   virtual Node* ConsumeValue() = 0;
46
47   // Shortcut for "context->ProduceValue(context->ConsumeValue())".
48   void ReplaceValue() { ProduceValue(ConsumeValue()); }
49
50  protected:
51   AstContext(AstGraphBuilder* owner, Expression::Context kind);
52   virtual ~AstContext();
53
54   AstGraphBuilder* owner() const { return owner_; }
55   Environment* environment() const { return owner_->environment(); }
56
57 // We want to be able to assert, in a context-specific way, that the stack
58 // height makes sense when the context is filled.
59 #ifdef DEBUG
60   int original_height_;
61 #endif
62
63  private:
64   Expression::Context kind_;
65   AstGraphBuilder* owner_;
66   AstContext* outer_;
67 };
68
69
70 // Context to evaluate expression for its side effects only.
71 class AstGraphBuilder::AstEffectContext FINAL : public AstContext {
72  public:
73   explicit AstEffectContext(AstGraphBuilder* owner)
74       : AstContext(owner, Expression::kEffect) {}
75   ~AstEffectContext() FINAL;
76   void ProduceValue(Node* value) FINAL;
77   Node* ConsumeValue() FINAL;
78 };
79
80
81 // Context to evaluate expression for its value (and side effects).
82 class AstGraphBuilder::AstValueContext FINAL : public AstContext {
83  public:
84   explicit AstValueContext(AstGraphBuilder* owner)
85       : AstContext(owner, Expression::kValue) {}
86   ~AstValueContext() FINAL;
87   void ProduceValue(Node* value) FINAL;
88   Node* ConsumeValue() FINAL;
89 };
90
91
92 // Context to evaluate expression for a condition value (and side effects).
93 class AstGraphBuilder::AstTestContext FINAL : public AstContext {
94  public:
95   explicit AstTestContext(AstGraphBuilder* owner)
96       : AstContext(owner, Expression::kTest) {}
97   ~AstTestContext() FINAL;
98   void ProduceValue(Node* value) FINAL;
99   Node* ConsumeValue() FINAL;
100 };
101
102
103 // Scoped class tracking context objects created by the visitor. Represents
104 // mutations of the context chain within the function body and allows to
105 // change the current {scope} and {context} during visitation.
106 class AstGraphBuilder::ContextScope BASE_EMBEDDED {
107  public:
108   ContextScope(AstGraphBuilder* builder, Scope* scope, Node* context)
109       : builder_(builder),
110         outer_(builder->execution_context()),
111         scope_(scope),
112         depth_(builder_->environment()->ContextStackDepth()) {
113     builder_->environment()->PushContext(context);  // Push.
114     builder_->set_execution_context(this);
115   }
116
117   ~ContextScope() {
118     builder_->set_execution_context(outer_);  // Pop.
119     builder_->environment()->PopContext();
120     CHECK_EQ(depth_, builder_->environment()->ContextStackDepth());
121   }
122
123   // Current scope during visitation.
124   Scope* scope() const { return scope_; }
125
126  private:
127   AstGraphBuilder* builder_;
128   ContextScope* outer_;
129   Scope* scope_;
130   int depth_;
131 };
132
133
134 // Scoped class tracking control statements entered by the visitor. There are
135 // different types of statements participating in this stack to properly track
136 // local as well as non-local control flow:
137 //  - IterationStatement : Allows proper 'break' and 'continue' behavior.
138 //  - BreakableStatement : Allows 'break' from block and switch statements.
139 //  - TryCatchStatement  : Intercepts 'throw' and implicit exceptional edges.
140 //  - TryFinallyStatement: Intercepts 'break', 'continue', 'throw' and 'return'.
141 class AstGraphBuilder::ControlScope BASE_EMBEDDED {
142  public:
143   ControlScope(AstGraphBuilder* builder, int stack_delta)
144       : builder_(builder),
145         outer_(builder->execution_control()),
146         stack_delta_(stack_delta) {
147     builder_->set_execution_control(this);  // Push.
148   }
149
150   virtual ~ControlScope() {
151     builder_->set_execution_control(outer_);  // Pop.
152   }
153
154   // Either 'break' or 'continue' to the target statement.
155   void BreakTo(BreakableStatement* target);
156   void ContinueTo(BreakableStatement* target);
157
158   // Either 'return' or 'throw' the given value.
159   void ReturnValue(Node* return_value);
160   void ThrowValue(Node* exception_value);
161
162   class DeferredCommands;
163
164  protected:
165   enum Command { CMD_BREAK, CMD_CONTINUE, CMD_RETURN, CMD_THROW };
166
167   // Performs one of the above commands on this stack of control scopes. This
168   // walks through the stack giving each scope a chance to execute or defer the
169   // given command by overriding the {Execute} method appropriately. Note that
170   // this also drops extra operands from the environment for each skipped scope.
171   void PerformCommand(Command cmd, Statement* target, Node* value);
172
173   // Interface to execute a given command in this scope. Returning {true} here
174   // indicates successful execution whereas {false} requests to skip scope.
175   virtual bool Execute(Command cmd, Statement* target, Node* value) {
176     // For function-level control.
177     switch (cmd) {
178       case CMD_THROW:
179         builder()->BuildThrow(value);
180         return true;
181       case CMD_RETURN:
182         builder()->BuildReturn(value);
183         return true;
184       case CMD_BREAK:
185       case CMD_CONTINUE:
186         break;
187     }
188     return false;
189   }
190
191   Environment* environment() { return builder_->environment(); }
192   AstGraphBuilder* builder() const { return builder_; }
193   int stack_delta() const { return stack_delta_; }
194
195  private:
196   AstGraphBuilder* builder_;
197   ControlScope* outer_;
198   int stack_delta_;
199 };
200
201
202 // Helper class for a try-finally control scope. It can record intercepted
203 // control-flow commands that cause entry into a finally-block, and re-apply
204 // them after again leaving that block. Special tokens are used to identify
205 // paths going through the finally-block to dispatch after leaving the block.
206 class AstGraphBuilder::ControlScope::DeferredCommands : public ZoneObject {
207  public:
208   explicit DeferredCommands(AstGraphBuilder* owner)
209       : owner_(owner), deferred_(owner->zone()) {}
210
211   // One recorded control-flow command.
212   struct Entry {
213     Command command;       // The command type being applied on this path.
214     Statement* statement;  // The target statement for the command or {NULL}.
215     Node* value;           // The passed value node for the command or {NULL}.
216     Node* token;           // A token identifying this particular path.
217   };
218
219   // Records a control-flow command while entering the finally-block. This also
220   // generates a new dispatch token that identifies one particular path.
221   Node* RecordCommand(Command cmd, Statement* stmt, Node* value) {
222     Node* token = NewPathTokenForDeferredCommand();
223     deferred_.push_back({cmd, stmt, value, token});
224     return token;
225   }
226
227   // Returns the dispatch token to be used to identify the implicit fall-through
228   // path at the end of a try-block into the corresponding finally-block.
229   Node* GetFallThroughToken() { return NewPathTokenForImplicitFallThrough(); }
230
231   // Applies all recorded control-flow commands after the finally-block again.
232   // This generates a dynamic dispatch on the token from the entry point.
233   void ApplyDeferredCommands(Node* token) {
234     SwitchBuilder dispatch(owner_, static_cast<int>(deferred_.size()));
235     dispatch.BeginSwitch();
236     for (size_t i = 0; i < deferred_.size(); ++i) {
237       Node* condition = NewPathDispatchCondition(token, deferred_[i].token);
238       dispatch.BeginLabel(static_cast<int>(i), condition);
239       dispatch.EndLabel();
240     }
241     for (size_t i = 0; i < deferred_.size(); ++i) {
242       dispatch.BeginCase(static_cast<int>(i));
243       owner_->execution_control()->PerformCommand(
244           deferred_[i].command, deferred_[i].statement, deferred_[i].value);
245       dispatch.EndCase();
246     }
247     dispatch.EndSwitch();
248   }
249
250  protected:
251   Node* NewPathTokenForDeferredCommand() {
252     return owner_->jsgraph()->Constant(static_cast<int>(deferred_.size()));
253   }
254   Node* NewPathTokenForImplicitFallThrough() {
255     return owner_->jsgraph()->Constant(-1);
256   }
257   Node* NewPathDispatchCondition(Node* t1, Node* t2) {
258     // TODO(mstarzinger): This should be machine()->WordEqual(), but our Phi
259     // nodes all have kRepTagged|kTypeAny, which causes representation mismatch.
260     return owner_->NewNode(owner_->javascript()->StrictEqual(), t1, t2);
261   }
262
263  private:
264   AstGraphBuilder* owner_;
265   ZoneVector<Entry> deferred_;
266 };
267
268
269 // Control scope implementation for a BreakableStatement.
270 class AstGraphBuilder::ControlScopeForBreakable : public ControlScope {
271  public:
272   ControlScopeForBreakable(AstGraphBuilder* owner, BreakableStatement* target,
273                            ControlBuilder* control)
274       : ControlScope(owner, 0), target_(target), control_(control) {}
275
276  protected:
277   virtual bool Execute(Command cmd, Statement* target, Node* value) OVERRIDE {
278     if (target != target_) return false;  // We are not the command target.
279     switch (cmd) {
280       case CMD_BREAK:
281         control_->Break();
282         return true;
283       case CMD_CONTINUE:
284       case CMD_THROW:
285       case CMD_RETURN:
286         break;
287     }
288     return false;
289   }
290
291  private:
292   BreakableStatement* target_;
293   ControlBuilder* control_;
294 };
295
296
297 // Control scope implementation for an IterationStatement.
298 class AstGraphBuilder::ControlScopeForIteration : public ControlScope {
299  public:
300   ControlScopeForIteration(AstGraphBuilder* owner, IterationStatement* target,
301                            LoopBuilder* control, int stack_delta)
302       : ControlScope(owner, stack_delta), target_(target), control_(control) {}
303
304  protected:
305   virtual bool Execute(Command cmd, Statement* target, Node* value) OVERRIDE {
306     if (target != target_) return false;  // We are not the command target.
307     switch (cmd) {
308       case CMD_BREAK:
309         control_->Break();
310         return true;
311       case CMD_CONTINUE:
312         control_->Continue();
313         return true;
314       case CMD_THROW:
315       case CMD_RETURN:
316         break;
317     }
318     return false;
319   }
320
321  private:
322   BreakableStatement* target_;
323   LoopBuilder* control_;
324 };
325
326
327 // Control scope implementation for a TryCatchStatement.
328 class AstGraphBuilder::ControlScopeForCatch : public ControlScope {
329  public:
330   ControlScopeForCatch(AstGraphBuilder* owner, TryCatchBuilder* control)
331       : ControlScope(owner, 0), control_(control) {}
332
333  protected:
334   virtual bool Execute(Command cmd, Statement* target, Node* value) OVERRIDE {
335     switch (cmd) {
336       case CMD_THROW:
337         control_->Throw(value);
338         return true;
339       case CMD_BREAK:
340       case CMD_CONTINUE:
341       case CMD_RETURN:
342         break;
343     }
344     return false;
345   }
346
347  private:
348   TryCatchBuilder* control_;
349 };
350
351
352 // Control scope implementation for a TryFinallyStatement.
353 class AstGraphBuilder::ControlScopeForFinally : public ControlScope {
354  public:
355   ControlScopeForFinally(AstGraphBuilder* owner, DeferredCommands* commands,
356                          TryFinallyBuilder* control)
357       : ControlScope(owner, 0), commands_(commands), control_(control) {}
358
359  protected:
360   virtual bool Execute(Command cmd, Statement* target, Node* value) OVERRIDE {
361     Node* token = commands_->RecordCommand(cmd, target, value);
362     control_->LeaveTry(token);
363     return true;
364   }
365
366  private:
367   DeferredCommands* commands_;
368   TryFinallyBuilder* control_;
369 };
370
371
372 AstGraphBuilder::AstGraphBuilder(Zone* local_zone, CompilationInfo* info,
373                                  JSGraph* jsgraph, LoopAssignmentAnalysis* loop)
374     : local_zone_(local_zone),
375       info_(info),
376       jsgraph_(jsgraph),
377       environment_(nullptr),
378       ast_context_(nullptr),
379       globals_(0, local_zone),
380       execution_control_(nullptr),
381       execution_context_(nullptr),
382       input_buffer_size_(0),
383       input_buffer_(nullptr),
384       exit_control_(nullptr),
385       loop_assignment_analysis_(loop) {
386   InitializeAstVisitor(info->isolate(), local_zone);
387 }
388
389
390 Node* AstGraphBuilder::GetFunctionClosure() {
391   if (!function_closure_.is_set()) {
392     const Operator* op =
393         common()->Parameter(Linkage::kJSFunctionCallClosureParamIndex);
394     Node* node = NewNode(op, graph()->start());
395     function_closure_.set(node);
396   }
397   return function_closure_.get();
398 }
399
400
401 void AstGraphBuilder::CreateFunctionContext(bool constant_context) {
402   function_context_.set(constant_context
403                             ? jsgraph()->HeapConstant(info()->context())
404                             : NewOuterContextParam());
405 }
406
407
408 Node* AstGraphBuilder::NewOuterContextParam() {
409   // Parameter (arity + 1) is special for the outer context of the function
410   const Operator* op = common()->Parameter(info()->num_parameters() + 1);
411   return NewNode(op, graph()->start());
412 }
413
414
415 Node* AstGraphBuilder::NewCurrentContextOsrValue() {
416   // TODO(titzer): use a real OSR value here; a parameter works by accident.
417   // Parameter (arity + 1) is special for the outer context of the function
418   const Operator* op = common()->Parameter(info()->num_parameters() + 1);
419   return NewNode(op, graph()->start());
420 }
421
422
423 bool AstGraphBuilder::CreateGraph(bool constant_context) {
424   Scope* scope = info()->scope();
425   DCHECK(graph() != NULL);
426
427   // Set up the basic structure of the graph.
428   int parameter_count = info()->num_parameters();
429   graph()->SetStart(graph()->NewNode(common()->Start(parameter_count)));
430
431   // Initialize control scope.
432   ControlScope control(this, 0);
433
434   // Initialize the top-level environment.
435   Environment env(this, scope, graph()->start());
436   set_environment(&env);
437
438   if (info()->is_osr()) {
439     // Use OSR normal entry as the start of the top-level environment.
440     // It will be replaced with {Dead} after typing and optimizations.
441     NewNode(common()->OsrNormalEntry());
442   }
443
444   // Initialize the incoming context.
445   CreateFunctionContext(constant_context);
446   ContextScope incoming(this, scope, function_context_.get());
447
448   // Build receiver check for sloppy mode if necessary.
449   // TODO(mstarzinger/verwaest): Should this be moved back into the CallIC?
450   Node* original_receiver = env.Lookup(scope->receiver());
451   Node* patched_receiver = BuildPatchReceiverToGlobalProxy(original_receiver);
452   env.Bind(scope->receiver(), patched_receiver);
453
454   // Build function context only if there are context allocated variables.
455   int heap_slots = info()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS;
456   if (heap_slots > 0) {
457     // Push a new inner context scope for the function.
458     Node* closure = GetFunctionClosure();
459     Node* inner_context =
460         BuildLocalFunctionContext(function_context_.get(), closure);
461     ContextScope top_context(this, scope, inner_context);
462     CreateGraphBody();
463   } else {
464     // Simply use the outer function context in building the graph.
465     CreateGraphBody();
466   }
467
468   // Finish the basic structure of the graph.
469   graph()->SetEnd(graph()->NewNode(common()->End(), exit_control()));
470
471   // Failures indicated by stack overflow.
472   return !HasStackOverflow();
473 }
474
475
476 void AstGraphBuilder::CreateGraphBody() {
477   Scope* scope = info()->scope();
478
479   // Build the arguments object if it is used.
480   BuildArgumentsObject(scope->arguments());
481
482   // Build rest arguments array if it is used.
483   int rest_index;
484   Variable* rest_parameter = scope->rest_parameter(&rest_index);
485   BuildRestArgumentsArray(rest_parameter, rest_index);
486
487   // Emit tracing call if requested to do so.
488   if (FLAG_trace) {
489     NewNode(javascript()->CallRuntime(Runtime::kTraceEnter, 0));
490   }
491
492   // Visit implicit declaration of the function name.
493   if (scope->is_function_scope() && scope->function() != NULL) {
494     VisitVariableDeclaration(scope->function());
495   }
496
497   // Visit declarations within the function scope.
498   VisitDeclarations(scope->declarations());
499
500   // Build a stack-check before the body.
501   Node* node = BuildStackCheck();
502   PrepareFrameState(node, BailoutId::FunctionEntry());
503
504   // Visit statements in the function body.
505   VisitStatements(info()->function()->body());
506
507   // Emit tracing call if requested to do so.
508   if (FLAG_trace) {
509     // TODO(mstarzinger): Only traces implicit return.
510     Node* return_value = jsgraph()->UndefinedConstant();
511     NewNode(javascript()->CallRuntime(Runtime::kTraceExit, 1), return_value);
512   }
513
514   // Return 'undefined' in case we can fall off the end.
515   BuildReturn(jsgraph()->UndefinedConstant());
516 }
517
518
519 // Left-hand side can only be a property, a global or a variable slot.
520 enum LhsKind { VARIABLE, NAMED_PROPERTY, KEYED_PROPERTY };
521
522
523 // Determine the left-hand side kind of an assignment.
524 static LhsKind DetermineLhsKind(Expression* expr) {
525   Property* property = expr->AsProperty();
526   DCHECK(expr->IsValidReferenceExpression());
527   LhsKind lhs_kind =
528       (property == NULL) ? VARIABLE : (property->key()->IsPropertyName())
529                                           ? NAMED_PROPERTY
530                                           : KEYED_PROPERTY;
531   return lhs_kind;
532 }
533
534
535 AstGraphBuilder::Environment::Environment(AstGraphBuilder* builder,
536                                           Scope* scope,
537                                           Node* control_dependency)
538     : builder_(builder),
539       parameters_count_(scope->num_parameters() + 1),
540       locals_count_(scope->num_stack_slots()),
541       values_(builder_->local_zone()),
542       contexts_(builder_->local_zone()),
543       control_dependency_(control_dependency),
544       effect_dependency_(control_dependency),
545       parameters_node_(nullptr),
546       locals_node_(nullptr),
547       stack_node_(nullptr) {
548   DCHECK_EQ(scope->num_parameters() + 1, parameters_count());
549
550   // Bind the receiver variable.
551   Node* receiver = builder->graph()->NewNode(common()->Parameter(0),
552                                              builder->graph()->start());
553   values()->push_back(receiver);
554
555   // Bind all parameter variables. The parameter indices are shifted by 1
556   // (receiver is parameter index -1 but environment index 0).
557   for (int i = 0; i < scope->num_parameters(); ++i) {
558     Node* parameter = builder->graph()->NewNode(common()->Parameter(i + 1),
559                                                 builder->graph()->start());
560     values()->push_back(parameter);
561   }
562
563   // Bind all local variables to undefined.
564   Node* undefined_constant = builder->jsgraph()->UndefinedConstant();
565   values()->insert(values()->end(), locals_count(), undefined_constant);
566 }
567
568
569 AstGraphBuilder::Environment::Environment(
570     const AstGraphBuilder::Environment* copy)
571     : builder_(copy->builder_),
572       parameters_count_(copy->parameters_count_),
573       locals_count_(copy->locals_count_),
574       values_(copy->zone()),
575       contexts_(copy->zone()),
576       control_dependency_(copy->control_dependency_),
577       effect_dependency_(copy->effect_dependency_),
578       parameters_node_(copy->parameters_node_),
579       locals_node_(copy->locals_node_),
580       stack_node_(copy->stack_node_) {
581   const size_t kStackEstimate = 7;  // optimum from experimentation!
582   values_.reserve(copy->values_.size() + kStackEstimate);
583   values_.insert(values_.begin(), copy->values_.begin(), copy->values_.end());
584   contexts_.reserve(copy->contexts_.size());
585   contexts_.insert(contexts_.begin(), copy->contexts_.begin(),
586                    copy->contexts_.end());
587 }
588
589
590 void AstGraphBuilder::Environment::UpdateStateValues(Node** state_values,
591                                                      int offset, int count) {
592   bool should_update = false;
593   Node** env_values = (count == 0) ? NULL : &values()->at(offset);
594   if (*state_values == NULL || (*state_values)->InputCount() != count) {
595     should_update = true;
596   } else {
597     DCHECK(static_cast<size_t>(offset + count) <= values()->size());
598     for (int i = 0; i < count; i++) {
599       if ((*state_values)->InputAt(i) != env_values[i]) {
600         should_update = true;
601         break;
602       }
603     }
604   }
605   if (should_update) {
606     const Operator* op = common()->StateValues(count);
607     (*state_values) = graph()->NewNode(op, count, env_values);
608   }
609 }
610
611
612 Node* AstGraphBuilder::Environment::Checkpoint(
613     BailoutId ast_id, OutputFrameStateCombine combine) {
614   UpdateStateValues(&parameters_node_, 0, parameters_count());
615   UpdateStateValues(&locals_node_, parameters_count(), locals_count());
616   UpdateStateValues(&stack_node_, parameters_count() + locals_count(),
617                     stack_height());
618
619   const Operator* op = common()->FrameState(JS_FRAME, ast_id, combine);
620
621   return graph()->NewNode(op, parameters_node_, locals_node_, stack_node_,
622                           builder()->current_context(),
623                           builder()->jsgraph()->UndefinedConstant());
624 }
625
626
627 AstGraphBuilder::AstContext::AstContext(AstGraphBuilder* own,
628                                         Expression::Context kind)
629     : kind_(kind), owner_(own), outer_(own->ast_context()) {
630   owner()->set_ast_context(this);  // Push.
631 #ifdef DEBUG
632   original_height_ = environment()->stack_height();
633 #endif
634 }
635
636
637 AstGraphBuilder::AstContext::~AstContext() {
638   owner()->set_ast_context(outer_);  // Pop.
639 }
640
641
642 AstGraphBuilder::AstEffectContext::~AstEffectContext() {
643   DCHECK(environment()->stack_height() == original_height_);
644 }
645
646
647 AstGraphBuilder::AstValueContext::~AstValueContext() {
648   DCHECK(environment()->stack_height() == original_height_ + 1);
649 }
650
651
652 AstGraphBuilder::AstTestContext::~AstTestContext() {
653   DCHECK(environment()->stack_height() == original_height_ + 1);
654 }
655
656
657 void AstGraphBuilder::AstEffectContext::ProduceValue(Node* value) {
658   // The value is ignored.
659 }
660
661
662 void AstGraphBuilder::AstValueContext::ProduceValue(Node* value) {
663   environment()->Push(value);
664 }
665
666
667 void AstGraphBuilder::AstTestContext::ProduceValue(Node* value) {
668   environment()->Push(owner()->BuildToBoolean(value));
669 }
670
671
672 Node* AstGraphBuilder::AstEffectContext::ConsumeValue() { return NULL; }
673
674
675 Node* AstGraphBuilder::AstValueContext::ConsumeValue() {
676   return environment()->Pop();
677 }
678
679
680 Node* AstGraphBuilder::AstTestContext::ConsumeValue() {
681   return environment()->Pop();
682 }
683
684
685 Scope* AstGraphBuilder::current_scope() const {
686   return execution_context_->scope();
687 }
688
689
690 Node* AstGraphBuilder::current_context() const {
691   return environment()->Context();
692 }
693
694
695 void AstGraphBuilder::ControlScope::PerformCommand(Command command,
696                                                    Statement* target,
697                                                    Node* value) {
698   Environment* env = environment()->CopyAsUnreachable();
699   ControlScope* current = this;
700   while (current != NULL) {
701     if (current->Execute(command, target, value)) break;
702     environment()->Drop(current->stack_delta());
703     current = current->outer_;
704   }
705   builder()->set_environment(env);
706   DCHECK(current != NULL);  // Always handled (unless stack is malformed).
707 }
708
709
710 void AstGraphBuilder::ControlScope::BreakTo(BreakableStatement* stmt) {
711   PerformCommand(CMD_BREAK, stmt, nullptr);
712 }
713
714
715 void AstGraphBuilder::ControlScope::ContinueTo(BreakableStatement* stmt) {
716   PerformCommand(CMD_CONTINUE, stmt, nullptr);
717 }
718
719
720 void AstGraphBuilder::ControlScope::ReturnValue(Node* return_value) {
721   PerformCommand(CMD_RETURN, nullptr, return_value);
722 }
723
724
725 void AstGraphBuilder::ControlScope::ThrowValue(Node* exception_value) {
726   PerformCommand(CMD_THROW, nullptr, exception_value);
727 }
728
729
730 void AstGraphBuilder::VisitForValueOrNull(Expression* expr) {
731   if (expr == NULL) {
732     return environment()->Push(jsgraph()->NullConstant());
733   }
734   VisitForValue(expr);
735 }
736
737
738 void AstGraphBuilder::VisitForValueOrTheHole(Expression* expr) {
739   if (expr == NULL) {
740     return environment()->Push(jsgraph()->TheHoleConstant());
741   }
742   VisitForValue(expr);
743 }
744
745
746 void AstGraphBuilder::VisitForValues(ZoneList<Expression*>* exprs) {
747   for (int i = 0; i < exprs->length(); ++i) {
748     VisitForValue(exprs->at(i));
749   }
750 }
751
752
753 void AstGraphBuilder::VisitForValue(Expression* expr) {
754   AstValueContext for_value(this);
755   if (!CheckStackOverflow()) {
756     expr->Accept(this);
757   } else {
758     ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
759   }
760 }
761
762
763 void AstGraphBuilder::VisitForEffect(Expression* expr) {
764   AstEffectContext for_effect(this);
765   if (!CheckStackOverflow()) {
766     expr->Accept(this);
767   } else {
768     ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
769   }
770 }
771
772
773 void AstGraphBuilder::VisitForTest(Expression* expr) {
774   AstTestContext for_condition(this);
775   if (!CheckStackOverflow()) {
776     expr->Accept(this);
777   } else {
778     ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
779   }
780 }
781
782
783 void AstGraphBuilder::Visit(Expression* expr) {
784   // Reuses enclosing AstContext.
785   if (!CheckStackOverflow()) {
786     expr->Accept(this);
787   } else {
788     ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
789   }
790 }
791
792
793 void AstGraphBuilder::VisitVariableDeclaration(VariableDeclaration* decl) {
794   Variable* variable = decl->proxy()->var();
795   VariableMode mode = decl->mode();
796   bool hole_init = mode == CONST || mode == CONST_LEGACY || mode == LET;
797   switch (variable->location()) {
798     case Variable::UNALLOCATED: {
799       Handle<Oddball> value = variable->binding_needs_init()
800                                   ? isolate()->factory()->the_hole_value()
801                                   : isolate()->factory()->undefined_value();
802       globals()->push_back(variable->name());
803       globals()->push_back(value);
804       break;
805     }
806     case Variable::PARAMETER:
807     case Variable::LOCAL:
808       if (hole_init) {
809         Node* value = jsgraph()->TheHoleConstant();
810         environment()->Bind(variable, value);
811       }
812       break;
813     case Variable::CONTEXT:
814       if (hole_init) {
815         Node* value = jsgraph()->TheHoleConstant();
816         const Operator* op = javascript()->StoreContext(0, variable->index());
817         NewNode(op, current_context(), value);
818       }
819       break;
820     case Variable::LOOKUP:
821       UNIMPLEMENTED();
822   }
823 }
824
825
826 void AstGraphBuilder::VisitFunctionDeclaration(FunctionDeclaration* decl) {
827   Variable* variable = decl->proxy()->var();
828   switch (variable->location()) {
829     case Variable::UNALLOCATED: {
830       Handle<SharedFunctionInfo> function =
831           Compiler::BuildFunctionInfo(decl->fun(), info()->script(), info());
832       // Check for stack-overflow exception.
833       if (function.is_null()) return SetStackOverflow();
834       globals()->push_back(variable->name());
835       globals()->push_back(function);
836       break;
837     }
838     case Variable::PARAMETER:
839     case Variable::LOCAL: {
840       VisitForValue(decl->fun());
841       Node* value = environment()->Pop();
842       environment()->Bind(variable, value);
843       break;
844     }
845     case Variable::CONTEXT: {
846       VisitForValue(decl->fun());
847       Node* value = environment()->Pop();
848       const Operator* op = javascript()->StoreContext(0, variable->index());
849       NewNode(op, current_context(), value);
850       break;
851     }
852     case Variable::LOOKUP:
853       UNIMPLEMENTED();
854   }
855 }
856
857
858 void AstGraphBuilder::VisitModuleDeclaration(ModuleDeclaration* decl) {
859   UNREACHABLE();
860 }
861
862
863 void AstGraphBuilder::VisitImportDeclaration(ImportDeclaration* decl) {
864   UNREACHABLE();
865 }
866
867
868 void AstGraphBuilder::VisitExportDeclaration(ExportDeclaration* decl) {
869   UNREACHABLE();
870 }
871
872
873 void AstGraphBuilder::VisitModuleLiteral(ModuleLiteral* modl) { UNREACHABLE(); }
874
875
876 void AstGraphBuilder::VisitModulePath(ModulePath* modl) { UNREACHABLE(); }
877
878
879 void AstGraphBuilder::VisitModuleUrl(ModuleUrl* modl) { UNREACHABLE(); }
880
881
882 void AstGraphBuilder::VisitBlock(Block* stmt) {
883   BlockBuilder block(this);
884   ControlScopeForBreakable scope(this, stmt, &block);
885   if (stmt->labels() != NULL) block.BeginBlock();
886   if (stmt->scope() == NULL) {
887     // Visit statements in the same scope, no declarations.
888     VisitStatements(stmt->statements());
889   } else {
890     // Visit declarations and statements in a block scope.
891     Node* context = BuildLocalBlockContext(stmt->scope());
892     ContextScope scope(this, stmt->scope(), context);
893     VisitDeclarations(stmt->scope()->declarations());
894     VisitStatements(stmt->statements());
895   }
896   if (stmt->labels() != NULL) block.EndBlock();
897 }
898
899
900 void AstGraphBuilder::VisitModuleStatement(ModuleStatement* stmt) {
901   UNREACHABLE();
902 }
903
904
905 void AstGraphBuilder::VisitExpressionStatement(ExpressionStatement* stmt) {
906   VisitForEffect(stmt->expression());
907 }
908
909
910 void AstGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) {
911   // Do nothing.
912 }
913
914
915 void AstGraphBuilder::VisitIfStatement(IfStatement* stmt) {
916   IfBuilder compare_if(this);
917   VisitForTest(stmt->condition());
918   Node* condition = environment()->Pop();
919   compare_if.If(condition);
920   compare_if.Then();
921   Visit(stmt->then_statement());
922   compare_if.Else();
923   Visit(stmt->else_statement());
924   compare_if.End();
925 }
926
927
928 void AstGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) {
929   execution_control()->ContinueTo(stmt->target());
930 }
931
932
933 void AstGraphBuilder::VisitBreakStatement(BreakStatement* stmt) {
934   execution_control()->BreakTo(stmt->target());
935 }
936
937
938 void AstGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) {
939   VisitForValue(stmt->expression());
940   Node* result = environment()->Pop();
941   execution_control()->ReturnValue(result);
942 }
943
944
945 void AstGraphBuilder::VisitWithStatement(WithStatement* stmt) {
946   VisitForValue(stmt->expression());
947   Node* value = environment()->Pop();
948   const Operator* op = javascript()->CreateWithContext();
949   Node* context = NewNode(op, value, GetFunctionClosure());
950   PrepareFrameState(context, stmt->EntryId());
951   ContextScope scope(this, stmt->scope(), context);
952   Visit(stmt->statement());
953 }
954
955
956 void AstGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
957   ZoneList<CaseClause*>* clauses = stmt->cases();
958   SwitchBuilder compare_switch(this, clauses->length());
959   ControlScopeForBreakable scope(this, stmt, &compare_switch);
960   compare_switch.BeginSwitch();
961   int default_index = -1;
962
963   // Keep the switch value on the stack until a case matches.
964   VisitForValue(stmt->tag());
965   Node* tag = environment()->Top();
966
967   // Iterate over all cases and create nodes for label comparison.
968   for (int i = 0; i < clauses->length(); i++) {
969     CaseClause* clause = clauses->at(i);
970
971     // The default is not a test, remember index.
972     if (clause->is_default()) {
973       default_index = i;
974       continue;
975     }
976
977     // Create nodes to perform label comparison as if via '==='. The switch
978     // value is still on the operand stack while the label is evaluated.
979     VisitForValue(clause->label());
980     Node* label = environment()->Pop();
981     const Operator* op = javascript()->StrictEqual();
982     Node* condition = NewNode(op, tag, label);
983     compare_switch.BeginLabel(i, condition);
984
985     // Discard the switch value at label match.
986     environment()->Pop();
987     compare_switch.EndLabel();
988   }
989
990   // Discard the switch value and mark the default case.
991   environment()->Pop();
992   if (default_index >= 0) {
993     compare_switch.DefaultAt(default_index);
994   }
995
996   // Iterate over all cases and create nodes for case bodies.
997   for (int i = 0; i < clauses->length(); i++) {
998     CaseClause* clause = clauses->at(i);
999     compare_switch.BeginCase(i);
1000     VisitStatements(clause->statements());
1001     compare_switch.EndCase();
1002   }
1003
1004   compare_switch.EndSwitch();
1005 }
1006
1007
1008 void AstGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
1009   LoopBuilder while_loop(this);
1010   while_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt));
1011   VisitIterationBody(stmt, &while_loop, 0);
1012   while_loop.EndBody();
1013   VisitForTest(stmt->cond());
1014   Node* condition = environment()->Pop();
1015   while_loop.BreakUnless(condition);
1016   while_loop.EndLoop();
1017 }
1018
1019
1020 void AstGraphBuilder::VisitWhileStatement(WhileStatement* stmt) {
1021   LoopBuilder while_loop(this);
1022   while_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt));
1023   VisitForTest(stmt->cond());
1024   Node* condition = environment()->Pop();
1025   while_loop.BreakUnless(condition);
1026   VisitIterationBody(stmt, &while_loop, 0);
1027   while_loop.EndBody();
1028   while_loop.EndLoop();
1029 }
1030
1031
1032 void AstGraphBuilder::VisitForStatement(ForStatement* stmt) {
1033   LoopBuilder for_loop(this);
1034   VisitIfNotNull(stmt->init());
1035   for_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt));
1036   if (stmt->cond() != NULL) {
1037     VisitForTest(stmt->cond());
1038     Node* condition = environment()->Pop();
1039     for_loop.BreakUnless(condition);
1040   } else {
1041     for_loop.BreakUnless(jsgraph()->TrueConstant());
1042   }
1043   VisitIterationBody(stmt, &for_loop, 0);
1044   for_loop.EndBody();
1045   VisitIfNotNull(stmt->next());
1046   for_loop.EndLoop();
1047 }
1048
1049
1050 // TODO(dcarney): this is a big function.  Try to clean up some.
1051 void AstGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
1052   VisitForValue(stmt->subject());
1053   Node* obj = environment()->Pop();
1054   // Check for undefined or null before entering loop.
1055   IfBuilder is_undefined(this);
1056   Node* is_undefined_cond =
1057       NewNode(javascript()->StrictEqual(), obj, jsgraph()->UndefinedConstant());
1058   is_undefined.If(is_undefined_cond);
1059   is_undefined.Then();
1060   is_undefined.Else();
1061   {
1062     IfBuilder is_null(this);
1063     Node* is_null_cond =
1064         NewNode(javascript()->StrictEqual(), obj, jsgraph()->NullConstant());
1065     is_null.If(is_null_cond);
1066     is_null.Then();
1067     is_null.Else();
1068     // Convert object to jsobject.
1069     // PrepareForBailoutForId(stmt->PrepareId(), TOS_REG);
1070     obj = NewNode(javascript()->ToObject(), obj);
1071     PrepareFrameState(obj, stmt->ToObjectId(), OutputFrameStateCombine::Push());
1072     environment()->Push(obj);
1073     // TODO(dcarney): should do a fast enum cache check here to skip runtime.
1074     Node* cache_type = NewNode(
1075         javascript()->CallRuntime(Runtime::kGetPropertyNamesFast, 1), obj);
1076     PrepareFrameState(cache_type, stmt->EnumId(),
1077                       OutputFrameStateCombine::Push());
1078     // TODO(dcarney): these next runtime calls should be removed in favour of
1079     //                a few simplified instructions.
1080     Node* cache_pair = NewNode(
1081         javascript()->CallRuntime(Runtime::kForInInit, 2), obj, cache_type);
1082     // cache_type may have been replaced.
1083     Node* cache_array = NewNode(common()->Projection(0), cache_pair);
1084     cache_type = NewNode(common()->Projection(1), cache_pair);
1085     Node* cache_length =
1086         NewNode(javascript()->CallRuntime(Runtime::kForInCacheArrayLength, 2),
1087                 cache_type, cache_array);
1088     {
1089       // TODO(dcarney): this check is actually supposed to be for the
1090       //                empty enum case only.
1091       IfBuilder have_no_properties(this);
1092       Node* empty_array_cond = NewNode(javascript()->StrictEqual(),
1093                                        cache_length, jsgraph()->ZeroConstant());
1094       have_no_properties.If(empty_array_cond);
1095       have_no_properties.Then();
1096       // Pop obj and skip loop.
1097       environment()->Pop();
1098       have_no_properties.Else();
1099       {
1100         // Construct the rest of the environment.
1101         environment()->Push(cache_type);
1102         environment()->Push(cache_array);
1103         environment()->Push(cache_length);
1104         environment()->Push(jsgraph()->ZeroConstant());
1105
1106         // Build the actual loop body.
1107         VisitForInBody(stmt);
1108       }
1109       have_no_properties.End();
1110     }
1111     is_null.End();
1112   }
1113   is_undefined.End();
1114 }
1115
1116
1117 // TODO(dcarney): this is a big function.  Try to clean up some.
1118 void AstGraphBuilder::VisitForInBody(ForInStatement* stmt) {
1119   LoopBuilder for_loop(this);
1120   for_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt));
1121
1122   // These stack values are renamed in the case of OSR, so reload them
1123   // from the environment.
1124   Node* index = environment()->Peek(0);
1125   Node* cache_length = environment()->Peek(1);
1126   Node* cache_array = environment()->Peek(2);
1127   Node* cache_type = environment()->Peek(3);
1128   Node* obj = environment()->Peek(4);
1129
1130   // Check loop termination condition.
1131   Node* exit_cond = NewNode(javascript()->LessThan(), index, cache_length);
1132   // TODO(jarin): provide real bailout id.
1133   PrepareFrameState(exit_cond, BailoutId::None());
1134   for_loop.BreakUnless(exit_cond);
1135   Node* pair = NewNode(javascript()->CallRuntime(Runtime::kForInNext, 4), obj,
1136                        cache_array, cache_type, index);
1137   Node* value = NewNode(common()->Projection(0), pair);
1138   Node* should_filter = NewNode(common()->Projection(1), pair);
1139   environment()->Push(value);
1140   {
1141     // Test if FILTER_KEY needs to be called.
1142     IfBuilder test_should_filter(this);
1143     Node* should_filter_cond = NewNode(
1144         javascript()->StrictEqual(), should_filter, jsgraph()->TrueConstant());
1145     test_should_filter.If(should_filter_cond);
1146     test_should_filter.Then();
1147     value = environment()->Pop();
1148     Node* builtins = BuildLoadBuiltinsObject();
1149     Node* function = BuildLoadObjectField(
1150         builtins,
1151         JSBuiltinsObject::OffsetOfFunctionWithId(Builtins::FILTER_KEY));
1152     // result is either the string key or Smi(0) indicating the property
1153     // is gone.
1154     Node* res = NewNode(javascript()->CallFunction(3, NO_CALL_FUNCTION_FLAGS),
1155                         function, obj, value);
1156     // TODO(jarin): provide real bailout id.
1157     PrepareFrameState(res, BailoutId::None());
1158     Node* property_missing =
1159         NewNode(javascript()->StrictEqual(), res, jsgraph()->ZeroConstant());
1160     {
1161       IfBuilder is_property_missing(this);
1162       is_property_missing.If(property_missing);
1163       is_property_missing.Then();
1164       // Inc counter and continue.
1165       Node* index_inc =
1166           NewNode(javascript()->Add(), index, jsgraph()->OneConstant());
1167       // TODO(jarin): provide real bailout id.
1168       PrepareFrameState(index_inc, BailoutId::None());
1169       environment()->Poke(0, index_inc);
1170       for_loop.Continue();
1171       is_property_missing.Else();
1172       is_property_missing.End();
1173     }
1174     // Replace 'value' in environment.
1175     environment()->Push(res);
1176     test_should_filter.Else();
1177     test_should_filter.End();
1178   }
1179   value = environment()->Pop();
1180   // Bind value and do loop body.
1181   VisitForInAssignment(stmt->each(), value, stmt->AssignmentId());
1182   VisitIterationBody(stmt, &for_loop, 5);
1183   for_loop.EndBody();
1184   // Inc counter and continue.
1185   Node* index_inc =
1186       NewNode(javascript()->Add(), index, jsgraph()->OneConstant());
1187   // TODO(jarin): provide real bailout id.
1188   PrepareFrameState(index_inc, BailoutId::None());
1189   environment()->Poke(0, index_inc);
1190   for_loop.EndLoop();
1191   environment()->Drop(5);
1192   // PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
1193 }
1194
1195
1196 void AstGraphBuilder::VisitForOfStatement(ForOfStatement* stmt) {
1197   LoopBuilder for_loop(this);
1198   VisitForEffect(stmt->assign_iterator());
1199   for_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt));
1200   VisitForEffect(stmt->next_result());
1201   VisitForTest(stmt->result_done());
1202   Node* condition = environment()->Pop();
1203   for_loop.BreakWhen(condition);
1204   VisitForEffect(stmt->assign_each());
1205   VisitIterationBody(stmt, &for_loop, 0);
1206   for_loop.EndBody();
1207   for_loop.EndLoop();
1208 }
1209
1210
1211 void AstGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) {
1212   TryCatchBuilder try_control(this);
1213
1214   // Evaluate the try-block inside a control scope. This simulates a handler
1215   // that is intercepting 'throw' control commands.
1216   try_control.BeginTry();
1217   {
1218     ControlScopeForCatch scope(this, &try_control);
1219     Visit(stmt->try_block());
1220   }
1221   try_control.EndTry();
1222
1223   // Create a catch scope that binds the exception.
1224   Node* exception = try_control.GetExceptionNode();
1225   Unique<String> name = MakeUnique(stmt->variable()->name());
1226   const Operator* op = javascript()->CreateCatchContext(name);
1227   Node* context = NewNode(op, exception, GetFunctionClosure());
1228   PrepareFrameState(context, BailoutId::None());
1229   {
1230     ContextScope scope(this, stmt->scope(), context);
1231     DCHECK(stmt->scope()->declarations()->is_empty());
1232     // Evaluate the catch-block.
1233     Visit(stmt->catch_block());
1234   }
1235   try_control.EndCatch();
1236
1237   // TODO(mstarzinger): Remove bailout once everything works.
1238   if (!FLAG_turbo_exceptions) SetStackOverflow();
1239 }
1240
1241
1242 void AstGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
1243   TryFinallyBuilder try_control(this);
1244
1245   // We keep a record of all paths that enter the finally-block to be able to
1246   // dispatch to the correct continuation point after the statements in the
1247   // finally-block have been evaluated.
1248   //
1249   // The try-finally construct can enter the finally-block in three ways:
1250   // 1. By exiting the try-block normally, falling through at the end.
1251   // 2. By exiting the try-block with a function-local control flow transfer
1252   //    (i.e. through break/continue/return statements).
1253   // 3. By exiting the try-block with a thrown exception.
1254   ControlScope::DeferredCommands* commands =
1255       new (zone()) ControlScope::DeferredCommands(this);
1256
1257   // Evaluate the try-block inside a control scope. This simulates a handler
1258   // that is intercepting all control commands.
1259   try_control.BeginTry();
1260   {
1261     ControlScopeForFinally scope(this, commands, &try_control);
1262     Visit(stmt->try_block());
1263   }
1264   try_control.EndTry(commands->GetFallThroughToken());
1265
1266   // Evaluate the finally-block.
1267   Visit(stmt->finally_block());
1268   try_control.EndFinally();
1269
1270   // Dynamic dispatch after the finally-block.
1271   Node* token = try_control.GetDispatchTokenNode();
1272   commands->ApplyDeferredCommands(token);
1273
1274   // TODO(mstarzinger): Remove bailout once everything works.
1275   if (!FLAG_turbo_exceptions) SetStackOverflow();
1276 }
1277
1278
1279 void AstGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
1280   // TODO(turbofan): Do we really need a separate reloc-info for this?
1281   Node* node = NewNode(javascript()->CallRuntime(Runtime::kDebugBreak, 0));
1282   PrepareFrameState(node, stmt->DebugBreakId());
1283 }
1284
1285
1286 void AstGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
1287   Node* context = current_context();
1288
1289   // Build a new shared function info if we cannot find one in the baseline
1290   // code. We also have a stack overflow if the recursive compilation did.
1291   expr->InitializeSharedInfo(handle(info()->shared_info()->code()));
1292   Handle<SharedFunctionInfo> shared_info = expr->shared_info();
1293   if (shared_info.is_null()) {
1294     shared_info = Compiler::BuildFunctionInfo(expr, info()->script(), info());
1295     CHECK(!shared_info.is_null());  // TODO(mstarzinger): Set stack overflow?
1296   }
1297
1298   // Create node to instantiate a new closure.
1299   Node* info = jsgraph()->Constant(shared_info);
1300   Node* pretenure = jsgraph()->BooleanConstant(expr->pretenure());
1301   const Operator* op = javascript()->CallRuntime(Runtime::kNewClosure, 3);
1302   Node* value = NewNode(op, context, info, pretenure);
1303   ast_context()->ProduceValue(value);
1304 }
1305
1306
1307 void AstGraphBuilder::VisitClassLiteral(ClassLiteral* expr) {
1308   if (expr->scope() == NULL) {
1309     // Visit class literal in the same scope, no declarations.
1310     VisitClassLiteralContents(expr);
1311   } else {
1312     // Visit declarations and class literal in a block scope.
1313     Node* context = BuildLocalBlockContext(expr->scope());
1314     ContextScope scope(this, expr->scope(), context);
1315     VisitDeclarations(expr->scope()->declarations());
1316     VisitClassLiteralContents(expr);
1317   }
1318 }
1319
1320
1321 void AstGraphBuilder::VisitClassLiteralContents(ClassLiteral* expr) {
1322   Node* class_name = expr->raw_name() ? jsgraph()->Constant(expr->name())
1323                                       : jsgraph()->UndefinedConstant();
1324
1325   // The class name is expected on the operand stack.
1326   environment()->Push(class_name);
1327   VisitForValueOrTheHole(expr->extends());
1328   VisitForValue(expr->constructor());
1329
1330   // Create node to instantiate a new class.
1331   Node* constructor = environment()->Pop();
1332   Node* extends = environment()->Pop();
1333   Node* name = environment()->Pop();
1334   Node* script = jsgraph()->Constant(info()->script());
1335   Node* start = jsgraph()->Constant(expr->start_position());
1336   Node* end = jsgraph()->Constant(expr->end_position());
1337   const Operator* opc = javascript()->CallRuntime(Runtime::kDefineClass, 6);
1338   Node* literal = NewNode(opc, name, extends, constructor, script, start, end);
1339
1340   // The prototype is ensured to exist by Runtime_DefineClass. No access check
1341   // is needed here since the constructor is created by the class literal.
1342   Node* proto =
1343       BuildLoadObjectField(literal, JSFunction::kPrototypeOrInitialMapOffset);
1344
1345   // The class literal and the prototype are both expected on the operand stack
1346   // during evaluation of the method values.
1347   environment()->Push(literal);
1348   environment()->Push(proto);
1349
1350   // Create nodes to store method values into the literal.
1351   for (int i = 0; i < expr->properties()->length(); i++) {
1352     ObjectLiteral::Property* property = expr->properties()->at(i);
1353     environment()->Push(property->is_static() ? literal : proto);
1354
1355     VisitForValue(property->key());
1356     environment()->Push(
1357         BuildToName(environment()->Pop(), expr->GetIdForProperty(i)));
1358     VisitForValue(property->value());
1359     Node* value = environment()->Pop();
1360     Node* key = environment()->Pop();
1361     Node* receiver = environment()->Pop();
1362     BuildSetHomeObject(value, receiver, property->value());
1363
1364     switch (property->kind()) {
1365       case ObjectLiteral::Property::CONSTANT:
1366       case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1367       case ObjectLiteral::Property::PROTOTYPE:
1368         UNREACHABLE();
1369       case ObjectLiteral::Property::COMPUTED: {
1370         const Operator* op =
1371             javascript()->CallRuntime(Runtime::kDefineClassMethod, 3);
1372         NewNode(op, receiver, key, value);
1373         break;
1374       }
1375       case ObjectLiteral::Property::GETTER: {
1376         Node* attr = jsgraph()->Constant(DONT_ENUM);
1377         const Operator* op = javascript()->CallRuntime(
1378             Runtime::kDefineGetterPropertyUnchecked, 4);
1379         NewNode(op, receiver, key, value, attr);
1380         break;
1381       }
1382       case ObjectLiteral::Property::SETTER: {
1383         Node* attr = jsgraph()->Constant(DONT_ENUM);
1384         const Operator* op = javascript()->CallRuntime(
1385             Runtime::kDefineSetterPropertyUnchecked, 4);
1386         NewNode(op, receiver, key, value, attr);
1387         break;
1388       }
1389     }
1390   }
1391
1392   // Transform both the class literal and the prototype to fast properties.
1393   const Operator* op = javascript()->CallRuntime(Runtime::kToFastProperties, 1);
1394   NewNode(op, environment()->Pop());  // prototype
1395   NewNode(op, environment()->Pop());  // literal
1396
1397   // Assign to class variable.
1398   if (expr->scope() != NULL) {
1399     DCHECK_NOT_NULL(expr->class_variable_proxy());
1400     Variable* var = expr->class_variable_proxy()->var();
1401     BuildVariableAssignment(var, literal, Token::INIT_CONST, BailoutId::None());
1402   }
1403
1404   PrepareFrameState(literal, expr->id(), ast_context()->GetStateCombine());
1405   ast_context()->ProduceValue(literal);
1406 }
1407
1408
1409 void AstGraphBuilder::VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) {
1410   UNREACHABLE();
1411 }
1412
1413
1414 void AstGraphBuilder::VisitConditional(Conditional* expr) {
1415   IfBuilder compare_if(this);
1416   VisitForTest(expr->condition());
1417   Node* condition = environment()->Pop();
1418   compare_if.If(condition);
1419   compare_if.Then();
1420   Visit(expr->then_expression());
1421   compare_if.Else();
1422   Visit(expr->else_expression());
1423   compare_if.End();
1424   ast_context()->ReplaceValue();
1425 }
1426
1427
1428 void AstGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
1429   VectorSlotPair pair = CreateVectorSlotPair(expr->VariableFeedbackSlot());
1430   Node* value = BuildVariableLoad(expr->var(), expr->id(), pair);
1431   ast_context()->ProduceValue(value);
1432 }
1433
1434
1435 void AstGraphBuilder::VisitLiteral(Literal* expr) {
1436   Node* value = jsgraph()->Constant(expr->value());
1437   ast_context()->ProduceValue(value);
1438 }
1439
1440
1441 void AstGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
1442   Node* closure = GetFunctionClosure();
1443
1444   // Create node to materialize a regular expression literal.
1445   Node* literals_array =
1446       BuildLoadObjectField(closure, JSFunction::kLiteralsOffset);
1447   Node* literal_index = jsgraph()->Constant(expr->literal_index());
1448   Node* pattern = jsgraph()->Constant(expr->pattern());
1449   Node* flags = jsgraph()->Constant(expr->flags());
1450   const Operator* op =
1451       javascript()->CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
1452   Node* literal = NewNode(op, literals_array, literal_index, pattern, flags);
1453   PrepareFrameState(literal, expr->id(), ast_context()->GetStateCombine());
1454   ast_context()->ProduceValue(literal);
1455 }
1456
1457
1458 void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
1459   Node* closure = GetFunctionClosure();
1460
1461   // Create node to deep-copy the literal boilerplate.
1462   expr->BuildConstantProperties(isolate());
1463   Node* literals_array =
1464       BuildLoadObjectField(closure, JSFunction::kLiteralsOffset);
1465   Node* literal_index = jsgraph()->Constant(expr->literal_index());
1466   Node* constants = jsgraph()->Constant(expr->constant_properties());
1467   Node* flags = jsgraph()->Constant(expr->ComputeFlags(true));
1468   const Operator* op =
1469       javascript()->CallRuntime(Runtime::kCreateObjectLiteral, 4);
1470   Node* literal = NewNode(op, literals_array, literal_index, constants, flags);
1471   PrepareFrameState(literal, expr->CreateLiteralId(),
1472                     OutputFrameStateCombine::Push());
1473
1474   // The object is expected on the operand stack during computation of the
1475   // property values and is the value of the entire expression.
1476   environment()->Push(literal);
1477
1478   // Mark all computed expressions that are bound to a key that is shadowed by
1479   // a later occurrence of the same key. For the marked expressions, no store
1480   // code is emitted.
1481   expr->CalculateEmitStore(zone());
1482
1483   // Create nodes to store computed values into the literal.
1484   int property_index = 0;
1485   AccessorTable accessor_table(zone());
1486   for (; property_index < expr->properties()->length(); property_index++) {
1487     ObjectLiteral::Property* property = expr->properties()->at(property_index);
1488     if (property->is_computed_name()) break;
1489     if (property->IsCompileTimeValue()) continue;
1490
1491     Literal* key = property->key()->AsLiteral();
1492     switch (property->kind()) {
1493       case ObjectLiteral::Property::CONSTANT:
1494         UNREACHABLE();
1495       case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1496         DCHECK(!CompileTimeValue::IsCompileTimeValue(property->value()));
1497       // Fall through.
1498       case ObjectLiteral::Property::COMPUTED: {
1499         // It is safe to use [[Put]] here because the boilerplate already
1500         // contains computed properties with an uninitialized value.
1501         if (key->value()->IsInternalizedString()) {
1502           if (property->emit_store()) {
1503             VisitForValue(property->value());
1504             Node* value = environment()->Pop();
1505             Unique<Name> name = MakeUnique(key->AsPropertyName());
1506             Node* store =
1507                 NewNode(javascript()->StoreNamed(language_mode(), name),
1508                         literal, value);
1509             PrepareFrameState(store, key->id());
1510             BuildSetHomeObject(value, literal, property->value());
1511           } else {
1512             VisitForEffect(property->value());
1513           }
1514           break;
1515         }
1516         environment()->Push(literal);  // Duplicate receiver.
1517         VisitForValue(property->key());
1518         VisitForValue(property->value());
1519         Node* value = environment()->Pop();
1520         Node* key = environment()->Pop();
1521         Node* receiver = environment()->Pop();
1522         if (property->emit_store()) {
1523           Node* language = jsgraph()->Constant(SLOPPY);
1524           const Operator* op =
1525               javascript()->CallRuntime(Runtime::kSetProperty, 4);
1526           NewNode(op, receiver, key, value, language);
1527           BuildSetHomeObject(value, receiver, property->value());
1528         }
1529         break;
1530       }
1531       case ObjectLiteral::Property::PROTOTYPE: {
1532         environment()->Push(literal);  // Duplicate receiver.
1533         VisitForValue(property->value());
1534         Node* value = environment()->Pop();
1535         Node* receiver = environment()->Pop();
1536         DCHECK(property->emit_store());
1537         const Operator* op =
1538             javascript()->CallRuntime(Runtime::kInternalSetPrototype, 2);
1539         Node* set_prototype = NewNode(op, receiver, value);
1540         // SetPrototype should not lazy deopt on an object literal.
1541         PrepareFrameState(set_prototype, BailoutId::None());
1542         break;
1543       }
1544       case ObjectLiteral::Property::GETTER:
1545         if (property->emit_store()) {
1546           accessor_table.lookup(key)->second->getter = property->value();
1547         }
1548         break;
1549       case ObjectLiteral::Property::SETTER:
1550         if (property->emit_store()) {
1551           accessor_table.lookup(key)->second->setter = property->value();
1552         }
1553         break;
1554     }
1555   }
1556
1557   // Create nodes to define accessors, using only a single call to the runtime
1558   // for each pair of corresponding getters and setters.
1559   for (AccessorTable::Iterator it = accessor_table.begin();
1560        it != accessor_table.end(); ++it) {
1561     VisitForValue(it->first);
1562     VisitForValueOrNull(it->second->getter);
1563     BuildSetHomeObject(environment()->Top(), literal, it->second->getter);
1564     VisitForValueOrNull(it->second->setter);
1565     BuildSetHomeObject(environment()->Top(), literal, it->second->setter);
1566     Node* setter = environment()->Pop();
1567     Node* getter = environment()->Pop();
1568     Node* name = environment()->Pop();
1569     Node* attr = jsgraph()->Constant(NONE);
1570     const Operator* op =
1571         javascript()->CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5);
1572     Node* call = NewNode(op, literal, name, getter, setter, attr);
1573     // This should not lazy deopt on a new literal.
1574     PrepareFrameState(call, BailoutId::None());
1575   }
1576
1577   // Object literals have two parts. The "static" part on the left contains no
1578   // computed property names, and so we can compute its map ahead of time; see
1579   // Runtime_CreateObjectLiteralBoilerplate. The second "dynamic" part starts
1580   // with the first computed property name and continues with all properties to
1581   // its right. All the code from above initializes the static component of the
1582   // object literal, and arranges for the map of the result to reflect the
1583   // static order in which the keys appear. For the dynamic properties, we
1584   // compile them into a series of "SetOwnProperty" runtime calls. This will
1585   // preserve insertion order.
1586   for (; property_index < expr->properties()->length(); property_index++) {
1587     ObjectLiteral::Property* property = expr->properties()->at(property_index);
1588
1589     environment()->Push(literal);  // Duplicate receiver.
1590     VisitForValue(property->key());
1591     environment()->Push(BuildToName(environment()->Pop(),
1592                                     expr->GetIdForProperty(property_index)));
1593     // TODO(mstarzinger): For ObjectLiteral::Property::PROTOTYPE the key should
1594     // not be on the operand stack while the value is being evaluated. Come up
1595     // with a repro for this and fix it. Also find a nice way to do so. :)
1596     VisitForValue(property->value());
1597     Node* value = environment()->Pop();
1598     Node* key = environment()->Pop();
1599     Node* receiver = environment()->Pop();
1600     BuildSetHomeObject(value, receiver, property->value());
1601
1602     switch (property->kind()) {
1603       case ObjectLiteral::Property::CONSTANT:
1604       case ObjectLiteral::Property::COMPUTED:
1605       case ObjectLiteral::Property::MATERIALIZED_LITERAL: {
1606         Node* attr = jsgraph()->Constant(NONE);
1607         const Operator* op =
1608             javascript()->CallRuntime(Runtime::kDefineDataPropertyUnchecked, 4);
1609         Node* call = NewNode(op, receiver, key, value, attr);
1610         PrepareFrameState(call, BailoutId::None());
1611         break;
1612       }
1613       case ObjectLiteral::Property::PROTOTYPE: {
1614         const Operator* op =
1615             javascript()->CallRuntime(Runtime::kInternalSetPrototype, 2);
1616         Node* call = NewNode(op, receiver, value);
1617         PrepareFrameState(call, BailoutId::None());
1618         break;
1619       }
1620       case ObjectLiteral::Property::GETTER: {
1621         Node* attr = jsgraph()->Constant(NONE);
1622         const Operator* op = javascript()->CallRuntime(
1623             Runtime::kDefineGetterPropertyUnchecked, 4);
1624         Node* call = NewNode(op, receiver, key, value, attr);
1625         PrepareFrameState(call, BailoutId::None());
1626         break;
1627       }
1628       case ObjectLiteral::Property::SETTER: {
1629         Node* attr = jsgraph()->Constant(NONE);
1630         const Operator* op = javascript()->CallRuntime(
1631             Runtime::kDefineSetterPropertyUnchecked, 4);
1632         Node* call = NewNode(op, receiver, key, value, attr);
1633         PrepareFrameState(call, BailoutId::None());
1634         break;
1635       }
1636     }
1637   }
1638
1639   // Transform literals that contain functions to fast properties.
1640   if (expr->has_function()) {
1641     const Operator* op =
1642         javascript()->CallRuntime(Runtime::kToFastProperties, 1);
1643     NewNode(op, literal);
1644   }
1645
1646   ast_context()->ProduceValue(environment()->Pop());
1647 }
1648
1649
1650 void AstGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
1651   Node* closure = GetFunctionClosure();
1652
1653   // Create node to deep-copy the literal boilerplate.
1654   expr->BuildConstantElements(isolate());
1655   Node* literals_array =
1656       BuildLoadObjectField(closure, JSFunction::kLiteralsOffset);
1657   Node* literal_index = jsgraph()->Constant(expr->literal_index());
1658   Node* constants = jsgraph()->Constant(expr->constant_elements());
1659   Node* flags = jsgraph()->Constant(expr->ComputeFlags(true));
1660   const Operator* op =
1661       javascript()->CallRuntime(Runtime::kCreateArrayLiteral, 4);
1662   Node* literal = NewNode(op, literals_array, literal_index, constants, flags);
1663   PrepareFrameState(literal, expr->CreateLiteralId(),
1664                     OutputFrameStateCombine::Push());
1665
1666   // The array and the literal index are both expected on the operand stack
1667   // during computation of the element values.
1668   environment()->Push(literal);
1669   environment()->Push(literal_index);
1670
1671   // Create nodes to evaluate all the non-constant subexpressions and to store
1672   // them into the newly cloned array.
1673   for (int i = 0; i < expr->values()->length(); i++) {
1674     Expression* subexpr = expr->values()->at(i);
1675     if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
1676
1677     VisitForValue(subexpr);
1678     Node* value = environment()->Pop();
1679     Node* index = jsgraph()->Constant(i);
1680     Node* store = NewNode(javascript()->StoreProperty(language_mode()), literal,
1681                           index, value);
1682     PrepareFrameState(store, expr->GetIdForElement(i));
1683   }
1684
1685   environment()->Pop();  // Array literal index.
1686   ast_context()->ProduceValue(environment()->Pop());
1687 }
1688
1689
1690 void AstGraphBuilder::VisitForInAssignment(Expression* expr, Node* value,
1691                                            BailoutId bailout_id) {
1692   DCHECK(expr->IsValidReferenceExpression());
1693
1694   // Left-hand side can only be a property, a global or a variable slot.
1695   Property* property = expr->AsProperty();
1696   LhsKind assign_type = DetermineLhsKind(expr);
1697
1698   // Evaluate LHS expression and store the value.
1699   switch (assign_type) {
1700     case VARIABLE: {
1701       Variable* var = expr->AsVariableProxy()->var();
1702       BuildVariableAssignment(var, value, Token::ASSIGN, bailout_id);
1703       break;
1704     }
1705     case NAMED_PROPERTY: {
1706       environment()->Push(value);
1707       VisitForValue(property->obj());
1708       Node* object = environment()->Pop();
1709       value = environment()->Pop();
1710       Unique<Name> name =
1711           MakeUnique(property->key()->AsLiteral()->AsPropertyName());
1712       Node* store = NewNode(javascript()->StoreNamed(language_mode(), name),
1713                             object, value);
1714       PrepareFrameState(store, bailout_id);
1715       break;
1716     }
1717     case KEYED_PROPERTY: {
1718       environment()->Push(value);
1719       VisitForValue(property->obj());
1720       VisitForValue(property->key());
1721       Node* key = environment()->Pop();
1722       Node* object = environment()->Pop();
1723       value = environment()->Pop();
1724       Node* store = NewNode(javascript()->StoreProperty(language_mode()),
1725                             object, key, value);
1726       PrepareFrameState(store, bailout_id);
1727       break;
1728     }
1729   }
1730 }
1731
1732
1733 void AstGraphBuilder::VisitAssignment(Assignment* expr) {
1734   DCHECK(expr->target()->IsValidReferenceExpression());
1735
1736   // Left-hand side can only be a property, a global or a variable slot.
1737   Property* property = expr->target()->AsProperty();
1738   LhsKind assign_type = DetermineLhsKind(expr->target());
1739
1740   // Evaluate LHS expression.
1741   switch (assign_type) {
1742     case VARIABLE:
1743       // Nothing to do here.
1744       break;
1745     case NAMED_PROPERTY:
1746       VisitForValue(property->obj());
1747       break;
1748     case KEYED_PROPERTY: {
1749       VisitForValue(property->obj());
1750       VisitForValue(property->key());
1751       break;
1752     }
1753   }
1754
1755   // Evaluate the value and potentially handle compound assignments by loading
1756   // the left-hand side value and performing a binary operation.
1757   if (expr->is_compound()) {
1758     Node* old_value = NULL;
1759     switch (assign_type) {
1760       case VARIABLE: {
1761         VariableProxy* proxy = expr->target()->AsVariableProxy();
1762         VectorSlotPair pair =
1763             CreateVectorSlotPair(proxy->VariableFeedbackSlot());
1764         old_value = BuildVariableLoad(proxy->var(), expr->target()->id(), pair);
1765         break;
1766       }
1767       case NAMED_PROPERTY: {
1768         Node* object = environment()->Top();
1769         Unique<Name> name =
1770             MakeUnique(property->key()->AsLiteral()->AsPropertyName());
1771         VectorSlotPair pair =
1772             CreateVectorSlotPair(property->PropertyFeedbackSlot());
1773         old_value = NewNode(javascript()->LoadNamed(name, pair), object);
1774         PrepareFrameState(old_value, property->LoadId(),
1775                           OutputFrameStateCombine::Push());
1776         break;
1777       }
1778       case KEYED_PROPERTY: {
1779         Node* key = environment()->Top();
1780         Node* object = environment()->Peek(1);
1781         VectorSlotPair pair =
1782             CreateVectorSlotPair(property->PropertyFeedbackSlot());
1783         old_value = NewNode(javascript()->LoadProperty(pair), object, key);
1784         PrepareFrameState(old_value, property->LoadId(),
1785                           OutputFrameStateCombine::Push());
1786         break;
1787       }
1788     }
1789     environment()->Push(old_value);
1790     VisitForValue(expr->value());
1791     Node* right = environment()->Pop();
1792     Node* left = environment()->Pop();
1793     Node* value = BuildBinaryOp(left, right, expr->binary_op());
1794     PrepareFrameState(value, expr->binary_operation()->id(),
1795                       OutputFrameStateCombine::Push());
1796     environment()->Push(value);
1797   } else {
1798     VisitForValue(expr->value());
1799   }
1800
1801   // Store the value.
1802   Node* value = environment()->Pop();
1803   switch (assign_type) {
1804     case VARIABLE: {
1805       Variable* variable = expr->target()->AsVariableProxy()->var();
1806       BuildVariableAssignment(variable, value, expr->op(), expr->AssignmentId(),
1807                               ast_context()->GetStateCombine());
1808       break;
1809     }
1810     case NAMED_PROPERTY: {
1811       Node* object = environment()->Pop();
1812       Unique<Name> name =
1813           MakeUnique(property->key()->AsLiteral()->AsPropertyName());
1814       Node* store = NewNode(javascript()->StoreNamed(language_mode(), name),
1815                             object, value);
1816       PrepareFrameState(store, expr->AssignmentId(),
1817                         ast_context()->GetStateCombine());
1818       break;
1819     }
1820     case KEYED_PROPERTY: {
1821       Node* key = environment()->Pop();
1822       Node* object = environment()->Pop();
1823       Node* store = NewNode(javascript()->StoreProperty(language_mode()),
1824                             object, key, value);
1825       PrepareFrameState(store, expr->AssignmentId(),
1826                         ast_context()->GetStateCombine());
1827       break;
1828     }
1829   }
1830
1831   ast_context()->ProduceValue(value);
1832 }
1833
1834
1835 void AstGraphBuilder::VisitYield(Yield* expr) {
1836   // TODO(turbofan): Implement yield here.
1837   SetStackOverflow();
1838   ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
1839 }
1840
1841
1842 void AstGraphBuilder::VisitThrow(Throw* expr) {
1843   VisitForValue(expr->exception());
1844   Node* exception = environment()->Pop();
1845   if (FLAG_turbo_exceptions) {
1846     execution_control()->ThrowValue(exception);
1847     ast_context()->ProduceValue(exception);
1848   } else {
1849     // TODO(mstarzinger): Temporary workaround for bailout-id for debugger.
1850     const Operator* op = javascript()->CallRuntime(Runtime::kThrow, 1);
1851     Node* value = NewNode(op, exception);
1852     PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
1853     ast_context()->ProduceValue(value);
1854   }
1855 }
1856
1857
1858 void AstGraphBuilder::VisitProperty(Property* expr) {
1859   Node* value;
1860   VectorSlotPair pair = CreateVectorSlotPair(expr->PropertyFeedbackSlot());
1861   if (expr->key()->IsPropertyName()) {
1862     VisitForValue(expr->obj());
1863     Node* object = environment()->Pop();
1864     Unique<Name> name = MakeUnique(expr->key()->AsLiteral()->AsPropertyName());
1865     value = NewNode(javascript()->LoadNamed(name, pair), object);
1866   } else {
1867     VisitForValue(expr->obj());
1868     VisitForValue(expr->key());
1869     Node* key = environment()->Pop();
1870     Node* object = environment()->Pop();
1871     value = NewNode(javascript()->LoadProperty(pair), object, key);
1872   }
1873   PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
1874   ast_context()->ProduceValue(value);
1875 }
1876
1877
1878 void AstGraphBuilder::VisitCall(Call* expr) {
1879   Expression* callee = expr->expression();
1880   Call::CallType call_type = expr->GetCallType(isolate());
1881
1882   // Prepare the callee and the receiver to the function call. This depends on
1883   // the semantics of the underlying call type.
1884   CallFunctionFlags flags = NO_CALL_FUNCTION_FLAGS;
1885   Node* receiver_value = NULL;
1886   Node* callee_value = NULL;
1887   bool possibly_eval = false;
1888   switch (call_type) {
1889     case Call::GLOBAL_CALL: {
1890       VariableProxy* proxy = callee->AsVariableProxy();
1891       VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot());
1892       callee_value =
1893           BuildVariableLoad(proxy->var(), expr->expression()->id(), pair);
1894       receiver_value = jsgraph()->UndefinedConstant();
1895       break;
1896     }
1897     case Call::LOOKUP_SLOT_CALL: {
1898       Variable* variable = callee->AsVariableProxy()->var();
1899       DCHECK(variable->location() == Variable::LOOKUP);
1900       Node* name = jsgraph()->Constant(variable->name());
1901       const Operator* op =
1902           javascript()->CallRuntime(Runtime::kLoadLookupSlot, 2);
1903       Node* pair = NewNode(op, current_context(), name);
1904       callee_value = NewNode(common()->Projection(0), pair);
1905       receiver_value = NewNode(common()->Projection(1), pair);
1906
1907       PrepareFrameState(pair, expr->EvalOrLookupId(),
1908                         OutputFrameStateCombine::Push(2));
1909       break;
1910     }
1911     case Call::PROPERTY_CALL: {
1912       Property* property = callee->AsProperty();
1913       VisitForValue(property->obj());
1914       Node* object = environment()->Top();
1915       VectorSlotPair pair =
1916           CreateVectorSlotPair(property->PropertyFeedbackSlot());
1917       if (property->key()->IsPropertyName()) {
1918         Unique<Name> name =
1919             MakeUnique(property->key()->AsLiteral()->AsPropertyName());
1920         callee_value = NewNode(javascript()->LoadNamed(name, pair), object);
1921       } else {
1922         VisitForValue(property->key());
1923         Node* key = environment()->Pop();
1924         callee_value = NewNode(javascript()->LoadProperty(pair), object, key);
1925       }
1926       PrepareFrameState(callee_value, property->LoadId(),
1927                         OutputFrameStateCombine::Push());
1928       receiver_value = environment()->Pop();
1929       // Note that a PROPERTY_CALL requires the receiver to be wrapped into an
1930       // object for sloppy callees. This could also be modeled explicitly here,
1931       // thereby obsoleting the need for a flag to the call operator.
1932       flags = CALL_AS_METHOD;
1933       break;
1934     }
1935     case Call::SUPER_CALL:
1936       // TODO(dslomov): Implement super calls.
1937       callee_value = jsgraph()->UndefinedConstant();
1938       receiver_value = jsgraph()->UndefinedConstant();
1939       SetStackOverflow();
1940       break;
1941     case Call::POSSIBLY_EVAL_CALL:
1942       possibly_eval = true;
1943     // Fall through.
1944     case Call::OTHER_CALL:
1945       VisitForValue(callee);
1946       callee_value = environment()->Pop();
1947       receiver_value = jsgraph()->UndefinedConstant();
1948       break;
1949   }
1950
1951   // The callee and the receiver both have to be pushed onto the operand stack
1952   // before arguments are being evaluated.
1953   environment()->Push(callee_value);
1954   environment()->Push(receiver_value);
1955
1956   // Evaluate all arguments to the function call,
1957   ZoneList<Expression*>* args = expr->arguments();
1958   VisitForValues(args);
1959
1960   // Resolve callee and receiver for a potential direct eval call. This block
1961   // will mutate the callee and receiver values pushed onto the environment.
1962   if (possibly_eval && args->length() > 0) {
1963     int arg_count = args->length();
1964
1965     // Extract callee and source string from the environment.
1966     Node* callee = environment()->Peek(arg_count + 1);
1967     Node* source = environment()->Peek(arg_count - 1);
1968
1969     // Create node to ask for help resolving potential eval call. This will
1970     // provide a fully resolved callee and the corresponding receiver.
1971     Node* function = GetFunctionClosure();
1972     Node* receiver = environment()->Lookup(info()->scope()->receiver());
1973     Node* language = jsgraph()->Constant(language_mode());
1974     Node* position = jsgraph()->Constant(info()->scope()->start_position());
1975     const Operator* op =
1976         javascript()->CallRuntime(Runtime::kResolvePossiblyDirectEval, 6);
1977     Node* pair =
1978         NewNode(op, callee, source, function, receiver, language, position);
1979     PrepareFrameState(pair, expr->EvalOrLookupId(),
1980                       OutputFrameStateCombine::PokeAt(arg_count + 1));
1981     Node* new_callee = NewNode(common()->Projection(0), pair);
1982     Node* new_receiver = NewNode(common()->Projection(1), pair);
1983
1984     // Patch callee and receiver on the environment.
1985     environment()->Poke(arg_count + 1, new_callee);
1986     environment()->Poke(arg_count + 0, new_receiver);
1987   }
1988
1989   // Create node to perform the function call.
1990   const Operator* call = javascript()->CallFunction(args->length() + 2, flags);
1991   Node* value = ProcessArguments(call, args->length() + 2);
1992   PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
1993   ast_context()->ProduceValue(value);
1994 }
1995
1996
1997 void AstGraphBuilder::VisitCallNew(CallNew* expr) {
1998   VisitForValue(expr->expression());
1999
2000   // Evaluate all arguments to the construct call.
2001   ZoneList<Expression*>* args = expr->arguments();
2002   VisitForValues(args);
2003
2004   // Create node to perform the construct call.
2005   const Operator* call = javascript()->CallConstruct(args->length() + 1);
2006   Node* value = ProcessArguments(call, args->length() + 1);
2007   PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
2008   ast_context()->ProduceValue(value);
2009 }
2010
2011
2012 void AstGraphBuilder::VisitCallJSRuntime(CallRuntime* expr) {
2013   Handle<String> name = expr->name();
2014
2015   // The callee and the receiver both have to be pushed onto the operand stack
2016   // before arguments are being evaluated.
2017   CallFunctionFlags flags = NO_CALL_FUNCTION_FLAGS;
2018   Node* receiver_value = BuildLoadBuiltinsObject();
2019   Unique<String> unique = MakeUnique(name);
2020   VectorSlotPair pair = CreateVectorSlotPair(expr->CallRuntimeFeedbackSlot());
2021   Node* callee_value =
2022       NewNode(javascript()->LoadNamed(unique, pair), receiver_value);
2023   // TODO(jarin): Find/create a bailout id to deoptimize to (crankshaft
2024   // refuses to optimize functions with jsruntime calls).
2025   PrepareFrameState(callee_value, BailoutId::None(),
2026                     OutputFrameStateCombine::Push());
2027   environment()->Push(callee_value);
2028   environment()->Push(receiver_value);
2029
2030   // Evaluate all arguments to the JS runtime call.
2031   ZoneList<Expression*>* args = expr->arguments();
2032   VisitForValues(args);
2033
2034   // Create node to perform the JS runtime call.
2035   const Operator* call = javascript()->CallFunction(args->length() + 2, flags);
2036   Node* value = ProcessArguments(call, args->length() + 2);
2037   PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
2038   ast_context()->ProduceValue(value);
2039 }
2040
2041
2042 void AstGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
2043   const Runtime::Function* function = expr->function();
2044
2045   // Handle calls to runtime functions implemented in JavaScript separately as
2046   // the call follows JavaScript ABI and the callee is statically unknown.
2047   if (expr->is_jsruntime()) {
2048     DCHECK(function == NULL && expr->name()->length() > 0);
2049     return VisitCallJSRuntime(expr);
2050   }
2051
2052   // Evaluate all arguments to the runtime call.
2053   ZoneList<Expression*>* args = expr->arguments();
2054   VisitForValues(args);
2055
2056   // Create node to perform the runtime call.
2057   Runtime::FunctionId functionId = function->function_id;
2058   const Operator* call = javascript()->CallRuntime(functionId, args->length());
2059   Node* value = ProcessArguments(call, args->length());
2060   PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
2061   ast_context()->ProduceValue(value);
2062 }
2063
2064
2065 void AstGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
2066   switch (expr->op()) {
2067     case Token::DELETE:
2068       return VisitDelete(expr);
2069     case Token::VOID:
2070       return VisitVoid(expr);
2071     case Token::TYPEOF:
2072       return VisitTypeof(expr);
2073     case Token::NOT:
2074       return VisitNot(expr);
2075     default:
2076       UNREACHABLE();
2077   }
2078 }
2079
2080
2081 void AstGraphBuilder::VisitCountOperation(CountOperation* expr) {
2082   DCHECK(expr->expression()->IsValidReferenceExpression());
2083
2084   // Left-hand side can only be a property, a global or a variable slot.
2085   Property* property = expr->expression()->AsProperty();
2086   LhsKind assign_type = DetermineLhsKind(expr->expression());
2087
2088   // Reserve space for result of postfix operation.
2089   bool is_postfix = expr->is_postfix() && !ast_context()->IsEffect();
2090   if (is_postfix) environment()->Push(jsgraph()->UndefinedConstant());
2091
2092   // Evaluate LHS expression and get old value.
2093   Node* old_value = NULL;
2094   int stack_depth = -1;
2095   switch (assign_type) {
2096     case VARIABLE: {
2097       VariableProxy* proxy = expr->expression()->AsVariableProxy();
2098       VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot());
2099       old_value =
2100           BuildVariableLoad(proxy->var(), expr->expression()->id(), pair);
2101       stack_depth = 0;
2102       break;
2103     }
2104     case NAMED_PROPERTY: {
2105       VisitForValue(property->obj());
2106       Node* object = environment()->Top();
2107       Unique<Name> name =
2108           MakeUnique(property->key()->AsLiteral()->AsPropertyName());
2109       VectorSlotPair pair =
2110           CreateVectorSlotPair(property->PropertyFeedbackSlot());
2111       old_value = NewNode(javascript()->LoadNamed(name, pair), object);
2112       PrepareFrameState(old_value, property->LoadId(),
2113                         OutputFrameStateCombine::Push());
2114       stack_depth = 1;
2115       break;
2116     }
2117     case KEYED_PROPERTY: {
2118       VisitForValue(property->obj());
2119       VisitForValue(property->key());
2120       Node* key = environment()->Top();
2121       Node* object = environment()->Peek(1);
2122       VectorSlotPair pair =
2123           CreateVectorSlotPair(property->PropertyFeedbackSlot());
2124       old_value = NewNode(javascript()->LoadProperty(pair), object, key);
2125       PrepareFrameState(old_value, property->LoadId(),
2126                         OutputFrameStateCombine::Push());
2127       stack_depth = 2;
2128       break;
2129     }
2130   }
2131
2132   // Convert old value into a number.
2133   old_value = NewNode(javascript()->ToNumber(), old_value);
2134   PrepareFrameState(old_value, expr->ToNumberId(),
2135                     OutputFrameStateCombine::Push());
2136
2137   // Save result for postfix expressions at correct stack depth.
2138   if (is_postfix) environment()->Poke(stack_depth, old_value);
2139
2140   // Create node to perform +1/-1 operation.
2141   Node* value =
2142       BuildBinaryOp(old_value, jsgraph()->OneConstant(), expr->binary_op());
2143   // TODO(jarin) Insert proper bailout id here (will need to change
2144   // full code generator).
2145   PrepareFrameState(value, BailoutId::None());
2146
2147   // Store the value.
2148   switch (assign_type) {
2149     case VARIABLE: {
2150       Variable* variable = expr->expression()->AsVariableProxy()->var();
2151       environment()->Push(value);
2152       BuildVariableAssignment(variable, value, expr->op(),
2153                               expr->AssignmentId());
2154       environment()->Pop();
2155       break;
2156     }
2157     case NAMED_PROPERTY: {
2158       Node* object = environment()->Pop();
2159       Unique<Name> name =
2160           MakeUnique(property->key()->AsLiteral()->AsPropertyName());
2161       Node* store = NewNode(javascript()->StoreNamed(language_mode(), name),
2162                             object, value);
2163       environment()->Push(value);
2164       PrepareFrameState(store, expr->AssignmentId());
2165       environment()->Pop();
2166       break;
2167     }
2168     case KEYED_PROPERTY: {
2169       Node* key = environment()->Pop();
2170       Node* object = environment()->Pop();
2171       Node* store = NewNode(javascript()->StoreProperty(language_mode()),
2172                             object, key, value);
2173       environment()->Push(value);
2174       PrepareFrameState(store, expr->AssignmentId());
2175       environment()->Pop();
2176       break;
2177     }
2178   }
2179
2180   // Restore old value for postfix expressions.
2181   if (is_postfix) value = environment()->Pop();
2182
2183   ast_context()->ProduceValue(value);
2184 }
2185
2186
2187 void AstGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) {
2188   switch (expr->op()) {
2189     case Token::COMMA:
2190       return VisitComma(expr);
2191     case Token::OR:
2192     case Token::AND:
2193       return VisitLogicalExpression(expr);
2194     default: {
2195       VisitForValue(expr->left());
2196       VisitForValue(expr->right());
2197       Node* right = environment()->Pop();
2198       Node* left = environment()->Pop();
2199       Node* value = BuildBinaryOp(left, right, expr->op());
2200       PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
2201       ast_context()->ProduceValue(value);
2202     }
2203   }
2204 }
2205
2206
2207 void AstGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
2208   const Operator* op;
2209   switch (expr->op()) {
2210     case Token::EQ:
2211       op = javascript()->Equal();
2212       break;
2213     case Token::NE:
2214       op = javascript()->NotEqual();
2215       break;
2216     case Token::EQ_STRICT:
2217       op = javascript()->StrictEqual();
2218       break;
2219     case Token::NE_STRICT:
2220       op = javascript()->StrictNotEqual();
2221       break;
2222     case Token::LT:
2223       op = javascript()->LessThan();
2224       break;
2225     case Token::GT:
2226       op = javascript()->GreaterThan();
2227       break;
2228     case Token::LTE:
2229       op = javascript()->LessThanOrEqual();
2230       break;
2231     case Token::GTE:
2232       op = javascript()->GreaterThanOrEqual();
2233       break;
2234     case Token::INSTANCEOF:
2235       op = javascript()->InstanceOf();
2236       break;
2237     case Token::IN:
2238       op = javascript()->HasProperty();
2239       break;
2240     default:
2241       op = NULL;
2242       UNREACHABLE();
2243   }
2244   VisitForValue(expr->left());
2245   VisitForValue(expr->right());
2246   Node* right = environment()->Pop();
2247   Node* left = environment()->Pop();
2248   Node* value = NewNode(op, left, right);
2249   PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
2250   ast_context()->ProduceValue(value);
2251 }
2252
2253
2254 void AstGraphBuilder::VisitThisFunction(ThisFunction* expr) {
2255   Node* value = GetFunctionClosure();
2256   ast_context()->ProduceValue(value);
2257 }
2258
2259
2260 void AstGraphBuilder::VisitSuperReference(SuperReference* expr) {
2261   // TODO(turbofan): Implement super here.
2262   SetStackOverflow();
2263   ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
2264 }
2265
2266
2267 void AstGraphBuilder::VisitCaseClause(CaseClause* expr) { UNREACHABLE(); }
2268
2269
2270 void AstGraphBuilder::VisitDeclarations(ZoneList<Declaration*>* declarations) {
2271   DCHECK(globals()->empty());
2272   AstVisitor::VisitDeclarations(declarations);
2273   if (globals()->empty()) return;
2274   int array_index = 0;
2275   Handle<FixedArray> data = isolate()->factory()->NewFixedArray(
2276       static_cast<int>(globals()->size()), TENURED);
2277   for (Handle<Object> obj : *globals()) data->set(array_index++, *obj);
2278   int encoded_flags = DeclareGlobalsEvalFlag::encode(info()->is_eval()) |
2279                       DeclareGlobalsNativeFlag::encode(info()->is_native()) |
2280                       DeclareGlobalsLanguageMode::encode(language_mode());
2281   Node* flags = jsgraph()->Constant(encoded_flags);
2282   Node* pairs = jsgraph()->Constant(data);
2283   const Operator* op = javascript()->CallRuntime(Runtime::kDeclareGlobals, 3);
2284   NewNode(op, current_context(), pairs, flags);
2285   globals()->clear();
2286 }
2287
2288
2289 void AstGraphBuilder::VisitIfNotNull(Statement* stmt) {
2290   if (stmt == NULL) return;
2291   Visit(stmt);
2292 }
2293
2294
2295 void AstGraphBuilder::VisitIterationBody(IterationStatement* stmt,
2296                                          LoopBuilder* loop, int stack_delta) {
2297   ControlScopeForIteration scope(this, stmt, loop, stack_delta);
2298   Visit(stmt->body());
2299 }
2300
2301
2302 void AstGraphBuilder::VisitDelete(UnaryOperation* expr) {
2303   Node* value;
2304   if (expr->expression()->IsVariableProxy()) {
2305     // Delete of an unqualified identifier is only allowed in classic mode but
2306     // deleting "this" is allowed in all language modes.
2307     Variable* variable = expr->expression()->AsVariableProxy()->var();
2308     DCHECK(is_sloppy(language_mode()) || variable->is_this());
2309     value = BuildVariableDelete(variable, expr->id(),
2310                                 ast_context()->GetStateCombine());
2311   } else if (expr->expression()->IsProperty()) {
2312     Property* property = expr->expression()->AsProperty();
2313     VisitForValue(property->obj());
2314     VisitForValue(property->key());
2315     Node* key = environment()->Pop();
2316     Node* object = environment()->Pop();
2317     value = NewNode(javascript()->DeleteProperty(language_mode()), object, key);
2318     PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
2319   } else {
2320     VisitForEffect(expr->expression());
2321     value = jsgraph()->TrueConstant();
2322   }
2323   ast_context()->ProduceValue(value);
2324 }
2325
2326
2327 void AstGraphBuilder::VisitVoid(UnaryOperation* expr) {
2328   VisitForEffect(expr->expression());
2329   Node* value = jsgraph()->UndefinedConstant();
2330   ast_context()->ProduceValue(value);
2331 }
2332
2333
2334 void AstGraphBuilder::VisitTypeof(UnaryOperation* expr) {
2335   Node* operand;
2336   if (expr->expression()->IsVariableProxy()) {
2337     // Typeof does not throw a reference error on global variables, hence we
2338     // perform a non-contextual load in case the operand is a variable proxy.
2339     VariableProxy* proxy = expr->expression()->AsVariableProxy();
2340     VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot());
2341     operand = BuildVariableLoad(proxy->var(), expr->expression()->id(), pair,
2342                                 NOT_CONTEXTUAL);
2343   } else {
2344     VisitForValue(expr->expression());
2345     operand = environment()->Pop();
2346   }
2347   Node* value = NewNode(javascript()->TypeOf(), operand);
2348   ast_context()->ProduceValue(value);
2349 }
2350
2351
2352 void AstGraphBuilder::VisitNot(UnaryOperation* expr) {
2353   VisitForValue(expr->expression());
2354   Node* operand = environment()->Pop();
2355   // TODO(mstarzinger): Possible optimization when we are in effect context.
2356   Node* value = NewNode(javascript()->UnaryNot(), operand);
2357   ast_context()->ProduceValue(value);
2358 }
2359
2360
2361 void AstGraphBuilder::VisitComma(BinaryOperation* expr) {
2362   VisitForEffect(expr->left());
2363   Visit(expr->right());
2364   ast_context()->ReplaceValue();
2365 }
2366
2367
2368 void AstGraphBuilder::VisitLogicalExpression(BinaryOperation* expr) {
2369   bool is_logical_and = expr->op() == Token::AND;
2370   IfBuilder compare_if(this);
2371   VisitForValue(expr->left());
2372   Node* condition = environment()->Top();
2373   compare_if.If(BuildToBoolean(condition));
2374   compare_if.Then();
2375   if (is_logical_and) {
2376     environment()->Pop();
2377     Visit(expr->right());
2378   } else if (ast_context()->IsEffect()) {
2379     environment()->Pop();
2380   }
2381   compare_if.Else();
2382   if (!is_logical_and) {
2383     environment()->Pop();
2384     Visit(expr->right());
2385   } else if (ast_context()->IsEffect()) {
2386     environment()->Pop();
2387   }
2388   compare_if.End();
2389   ast_context()->ReplaceValue();
2390 }
2391
2392
2393 LanguageMode AstGraphBuilder::language_mode() const {
2394   return info()->language_mode();
2395 }
2396
2397
2398 VectorSlotPair AstGraphBuilder::CreateVectorSlotPair(
2399     FeedbackVectorICSlot slot) const {
2400   return VectorSlotPair(handle(info()->shared_info()->feedback_vector()), slot);
2401 }
2402
2403
2404 Node* AstGraphBuilder::ProcessArguments(const Operator* op, int arity) {
2405   DCHECK(environment()->stack_height() >= arity);
2406   Node** all = info()->zone()->NewArray<Node*>(arity);
2407   for (int i = arity - 1; i >= 0; --i) {
2408     all[i] = environment()->Pop();
2409   }
2410   Node* value = NewNode(op, arity, all);
2411   return value;
2412 }
2413
2414
2415 Node* AstGraphBuilder::BuildPatchReceiverToGlobalProxy(Node* receiver) {
2416   // Sloppy mode functions and builtins need to replace the receiver with the
2417   // global proxy when called as functions (without an explicit receiver
2418   // object). Otherwise there is nothing left to do here.
2419   if (is_strict(language_mode()) || info()->is_native()) return receiver;
2420
2421   // There is no need to perform patching if the receiver is never used. Note
2422   // that scope predicates are purely syntactical, a call to eval might still
2423   // inspect the receiver value.
2424   if (!info()->scope()->uses_this() && !info()->scope()->inner_uses_this() &&
2425       !info()->scope()->calls_sloppy_eval()) {
2426     return receiver;
2427   }
2428
2429   IfBuilder receiver_check(this);
2430   Node* undefined = jsgraph()->UndefinedConstant();
2431   Node* check = NewNode(javascript()->StrictEqual(), receiver, undefined);
2432   receiver_check.If(check);
2433   receiver_check.Then();
2434   environment()->Push(BuildLoadGlobalProxy());
2435   receiver_check.Else();
2436   environment()->Push(receiver);
2437   receiver_check.End();
2438   return environment()->Pop();
2439 }
2440
2441
2442 Node* AstGraphBuilder::BuildLocalFunctionContext(Node* context, Node* closure) {
2443   // Allocate a new local context.
2444   const Operator* op = javascript()->CreateFunctionContext();
2445   Node* local_context = NewNode(op, closure);
2446
2447   // Copy parameters into context if necessary.
2448   int num_parameters = info()->scope()->num_parameters();
2449   for (int i = 0; i < num_parameters; i++) {
2450     Variable* variable = info()->scope()->parameter(i);
2451     if (!variable->IsContextSlot()) continue;
2452     // Temporary parameter node. The parameter indices are shifted by 1
2453     // (receiver is parameter index -1 but environment index 0).
2454     Node* parameter = NewNode(common()->Parameter(i + 1), graph()->start());
2455     // Context variable (at bottom of the context chain).
2456     DCHECK_EQ(0, info()->scope()->ContextChainLength(variable->scope()));
2457     const Operator* op = javascript()->StoreContext(0, variable->index());
2458     NewNode(op, local_context, parameter);
2459   }
2460
2461   return local_context;
2462 }
2463
2464
2465 Node* AstGraphBuilder::BuildLocalBlockContext(Scope* scope) {
2466   Node* closure = GetFunctionClosure();
2467
2468   // Allocate a new local context.
2469   const Operator* op = javascript()->CreateBlockContext();
2470   Node* scope_info = jsgraph()->Constant(scope->GetScopeInfo(info_->isolate()));
2471   Node* local_context = NewNode(op, scope_info, closure);
2472
2473   return local_context;
2474 }
2475
2476
2477 Node* AstGraphBuilder::BuildArgumentsObject(Variable* arguments) {
2478   if (arguments == NULL) return NULL;
2479
2480   // Allocate and initialize a new arguments object.
2481   Node* callee = GetFunctionClosure();
2482   const Operator* op = javascript()->CallRuntime(Runtime::kNewArguments, 1);
2483   Node* object = NewNode(op, callee);
2484
2485   // Assign the object to the arguments variable.
2486   DCHECK(arguments->IsContextSlot() || arguments->IsStackAllocated());
2487   // This should never lazy deopt, so it is fine to send invalid bailout id.
2488   BuildVariableAssignment(arguments, object, Token::ASSIGN, BailoutId::None());
2489
2490   return object;
2491 }
2492
2493
2494 Node* AstGraphBuilder::BuildRestArgumentsArray(Variable* rest, int index) {
2495   if (rest == NULL) return NULL;
2496
2497   DCHECK(index >= 0);
2498   const Operator* op = javascript()->CallRuntime(Runtime::kNewRestParamSlow, 1);
2499   Node* object = NewNode(op, jsgraph()->SmiConstant(index));
2500
2501   // Assign the object to the rest array
2502   DCHECK(rest->IsContextSlot() || rest->IsStackAllocated());
2503   // This should never lazy deopt, so it is fine to send invalid bailout id.
2504   BuildVariableAssignment(rest, object, Token::ASSIGN, BailoutId::None());
2505
2506   return object;
2507 }
2508
2509
2510 Node* AstGraphBuilder::BuildHoleCheckSilent(Node* value, Node* for_hole,
2511                                             Node* not_hole) {
2512   IfBuilder hole_check(this);
2513   Node* the_hole = jsgraph()->TheHoleConstant();
2514   Node* check = NewNode(javascript()->StrictEqual(), value, the_hole);
2515   hole_check.If(check);
2516   hole_check.Then();
2517   environment()->Push(for_hole);
2518   hole_check.Else();
2519   environment()->Push(not_hole);
2520   hole_check.End();
2521   return environment()->Pop();
2522 }
2523
2524
2525 Node* AstGraphBuilder::BuildHoleCheckThrow(Node* value, Variable* variable,
2526                                            Node* not_hole,
2527                                            BailoutId bailout_id) {
2528   IfBuilder hole_check(this);
2529   Node* the_hole = jsgraph()->TheHoleConstant();
2530   Node* check = NewNode(javascript()->StrictEqual(), value, the_hole);
2531   hole_check.If(check);
2532   hole_check.Then();
2533   environment()->Push(BuildThrowReferenceError(variable, bailout_id));
2534   hole_check.Else();
2535   environment()->Push(not_hole);
2536   hole_check.End();
2537   return environment()->Pop();
2538 }
2539
2540
2541 Node* AstGraphBuilder::BuildVariableLoad(Variable* variable,
2542                                          BailoutId bailout_id,
2543                                          const VectorSlotPair& feedback,
2544                                          ContextualMode contextual_mode) {
2545   Node* the_hole = jsgraph()->TheHoleConstant();
2546   VariableMode mode = variable->mode();
2547   switch (variable->location()) {
2548     case Variable::UNALLOCATED: {
2549       // Global var, const, or let variable.
2550       Node* global = BuildLoadGlobalObject();
2551       Unique<Name> name = MakeUnique(variable->name());
2552       const Operator* op =
2553           javascript()->LoadNamed(name, feedback, contextual_mode);
2554       Node* node = NewNode(op, global);
2555       PrepareFrameState(node, bailout_id, OutputFrameStateCombine::Push());
2556       return node;
2557     }
2558     case Variable::PARAMETER:
2559     case Variable::LOCAL: {
2560       // Local var, const, or let variable.
2561       Node* value = environment()->Lookup(variable);
2562       if (mode == CONST_LEGACY) {
2563         // Perform check for uninitialized legacy const variables.
2564         if (value->op() == the_hole->op()) {
2565           value = jsgraph()->UndefinedConstant();
2566         } else if (value->opcode() == IrOpcode::kPhi) {
2567           Node* undefined = jsgraph()->UndefinedConstant();
2568           value = BuildHoleCheckSilent(value, undefined, value);
2569         }
2570       } else if (mode == LET || mode == CONST) {
2571         // Perform check for uninitialized let/const variables.
2572         if (value->op() == the_hole->op()) {
2573           value = BuildThrowReferenceError(variable, bailout_id);
2574         } else if (value->opcode() == IrOpcode::kPhi) {
2575           value = BuildHoleCheckThrow(value, variable, value, bailout_id);
2576         }
2577       }
2578       return value;
2579     }
2580     case Variable::CONTEXT: {
2581       // Context variable (potentially up the context chain).
2582       int depth = current_scope()->ContextChainLength(variable->scope());
2583       bool immutable = variable->maybe_assigned() == kNotAssigned;
2584       const Operator* op =
2585           javascript()->LoadContext(depth, variable->index(), immutable);
2586       Node* value = NewNode(op, current_context());
2587       // TODO(titzer): initialization checks are redundant for already
2588       // initialized immutable context loads, but only specialization knows.
2589       // Maybe specializer should be a parameter to the graph builder?
2590       if (mode == CONST_LEGACY) {
2591         // Perform check for uninitialized legacy const variables.
2592         Node* undefined = jsgraph()->UndefinedConstant();
2593         value = BuildHoleCheckSilent(value, undefined, value);
2594       } else if (mode == LET || mode == CONST) {
2595         // Perform check for uninitialized let/const variables.
2596         value = BuildHoleCheckThrow(value, variable, value, bailout_id);
2597       }
2598       return value;
2599     }
2600     case Variable::LOOKUP: {
2601       // Dynamic lookup of context variable (anywhere in the chain).
2602       Node* name = jsgraph()->Constant(variable->name());
2603       Runtime::FunctionId function_id =
2604           (contextual_mode == CONTEXTUAL)
2605               ? Runtime::kLoadLookupSlot
2606               : Runtime::kLoadLookupSlotNoReferenceError;
2607       const Operator* op = javascript()->CallRuntime(function_id, 2);
2608       Node* pair = NewNode(op, current_context(), name);
2609       PrepareFrameState(pair, bailout_id, OutputFrameStateCombine::Push(1));
2610       return NewNode(common()->Projection(0), pair);
2611     }
2612   }
2613   UNREACHABLE();
2614   return NULL;
2615 }
2616
2617
2618 Node* AstGraphBuilder::BuildVariableDelete(
2619     Variable* variable, BailoutId bailout_id,
2620     OutputFrameStateCombine state_combine) {
2621   switch (variable->location()) {
2622     case Variable::UNALLOCATED: {
2623       // Global var, const, or let variable.
2624       Node* global = BuildLoadGlobalObject();
2625       Node* name = jsgraph()->Constant(variable->name());
2626       const Operator* op = javascript()->DeleteProperty(language_mode());
2627       Node* result = NewNode(op, global, name);
2628       PrepareFrameState(result, bailout_id, state_combine);
2629       return result;
2630     }
2631     case Variable::PARAMETER:
2632     case Variable::LOCAL:
2633     case Variable::CONTEXT:
2634       // Local var, const, or let variable or context variable.
2635       return jsgraph()->BooleanConstant(variable->is_this());
2636     case Variable::LOOKUP: {
2637       // Dynamic lookup of context variable (anywhere in the chain).
2638       Node* name = jsgraph()->Constant(variable->name());
2639       const Operator* op =
2640           javascript()->CallRuntime(Runtime::kDeleteLookupSlot, 2);
2641       Node* result = NewNode(op, current_context(), name);
2642       PrepareFrameState(result, bailout_id, state_combine);
2643       return result;
2644     }
2645   }
2646   UNREACHABLE();
2647   return NULL;
2648 }
2649
2650
2651 Node* AstGraphBuilder::BuildVariableAssignment(
2652     Variable* variable, Node* value, Token::Value op, BailoutId bailout_id,
2653     OutputFrameStateCombine combine) {
2654   Node* the_hole = jsgraph()->TheHoleConstant();
2655   VariableMode mode = variable->mode();
2656   switch (variable->location()) {
2657     case Variable::UNALLOCATED: {
2658       // Global var, const, or let variable.
2659       Node* global = BuildLoadGlobalObject();
2660       Unique<Name> name = MakeUnique(variable->name());
2661       const Operator* op = javascript()->StoreNamed(language_mode(), name);
2662       Node* store = NewNode(op, global, value);
2663       PrepareFrameState(store, bailout_id, combine);
2664       return store;
2665     }
2666     case Variable::PARAMETER:
2667     case Variable::LOCAL:
2668       // Local var, const, or let variable.
2669       if (mode == CONST_LEGACY && op == Token::INIT_CONST_LEGACY) {
2670         // Perform an initialization check for legacy const variables.
2671         Node* current = environment()->Lookup(variable);
2672         if (current->op() != the_hole->op()) {
2673           value = BuildHoleCheckSilent(current, value, current);
2674         }
2675       } else if (mode == CONST_LEGACY && op != Token::INIT_CONST_LEGACY) {
2676         // Non-initializing assignments to legacy const is
2677         // - exception in strict mode.
2678         // - ignored in sloppy mode.
2679         if (is_strict(language_mode())) {
2680           return BuildThrowConstAssignError(bailout_id);
2681         }
2682         return value;
2683       } else if (mode == LET && op != Token::INIT_LET) {
2684         // Perform an initialization check for let declared variables.
2685         // Also note that the dynamic hole-check is only done to ensure that
2686         // this does not break in the presence of do-expressions within the
2687         // temporal dead zone of a let declared variable.
2688         Node* current = environment()->Lookup(variable);
2689         if (current->op() == the_hole->op()) {
2690           value = BuildThrowReferenceError(variable, bailout_id);
2691         } else if (value->opcode() == IrOpcode::kPhi) {
2692           value = BuildHoleCheckThrow(current, variable, value, bailout_id);
2693         }
2694       } else if (mode == CONST && op != Token::INIT_CONST) {
2695         // Non-initializing assignments to const is exception in all modes.
2696         return BuildThrowConstAssignError(bailout_id);
2697       }
2698       environment()->Bind(variable, value);
2699       return value;
2700     case Variable::CONTEXT: {
2701       // Context variable (potentially up the context chain).
2702       int depth = current_scope()->ContextChainLength(variable->scope());
2703       if (mode == CONST_LEGACY && op == Token::INIT_CONST_LEGACY) {
2704         // Perform an initialization check for legacy const variables.
2705         const Operator* op =
2706             javascript()->LoadContext(depth, variable->index(), false);
2707         Node* current = NewNode(op, current_context());
2708         value = BuildHoleCheckSilent(current, value, current);
2709       } else if (mode == CONST_LEGACY && op != Token::INIT_CONST_LEGACY) {
2710         // Non-initializing assignments to legacy const is
2711         // - exception in strict mode.
2712         // - ignored in sloppy mode.
2713         if (is_strict(language_mode())) {
2714           return BuildThrowConstAssignError(bailout_id);
2715         }
2716         return value;
2717       } else if (mode == LET && op != Token::INIT_LET) {
2718         // Perform an initialization check for let declared variables.
2719         const Operator* op =
2720             javascript()->LoadContext(depth, variable->index(), false);
2721         Node* current = NewNode(op, current_context());
2722         value = BuildHoleCheckThrow(current, variable, value, bailout_id);
2723       } else if (mode == CONST && op != Token::INIT_CONST) {
2724         // Non-initializing assignments to const is exception in all modes.
2725         return BuildThrowConstAssignError(bailout_id);
2726       }
2727       const Operator* op = javascript()->StoreContext(depth, variable->index());
2728       return NewNode(op, current_context(), value);
2729     }
2730     case Variable::LOOKUP: {
2731       // Dynamic lookup of context variable (anywhere in the chain).
2732       Node* name = jsgraph()->Constant(variable->name());
2733       Node* language = jsgraph()->Constant(language_mode());
2734       // TODO(mstarzinger): Use Runtime::kInitializeLegacyConstLookupSlot for
2735       // initializations of const declarations.
2736       const Operator* op =
2737           javascript()->CallRuntime(Runtime::kStoreLookupSlot, 4);
2738       Node* store = NewNode(op, value, current_context(), name, language);
2739       PrepareFrameState(store, bailout_id, combine);
2740       return store;
2741     }
2742   }
2743   UNREACHABLE();
2744   return NULL;
2745 }
2746
2747
2748 Node* AstGraphBuilder::BuildLoadObjectField(Node* object, int offset) {
2749   Node* field_load = NewNode(jsgraph()->machine()->Load(kMachAnyTagged), object,
2750                              jsgraph()->Int32Constant(offset - kHeapObjectTag));
2751   return field_load;
2752 }
2753
2754
2755 Node* AstGraphBuilder::BuildLoadBuiltinsObject() {
2756   Node* global = BuildLoadGlobalObject();
2757   Node* builtins =
2758       BuildLoadObjectField(global, JSGlobalObject::kBuiltinsOffset);
2759   return builtins;
2760 }
2761
2762
2763 Node* AstGraphBuilder::BuildLoadGlobalObject() {
2764   const Operator* load_op =
2765       javascript()->LoadContext(0, Context::GLOBAL_OBJECT_INDEX, true);
2766   return NewNode(load_op, function_context_.get());
2767 }
2768
2769
2770 Node* AstGraphBuilder::BuildLoadGlobalProxy() {
2771   Node* global = BuildLoadGlobalObject();
2772   Node* proxy =
2773       BuildLoadObjectField(global, JSGlobalObject::kGlobalProxyOffset);
2774   return proxy;
2775 }
2776
2777
2778 Node* AstGraphBuilder::BuildToBoolean(Node* input) {
2779   // TODO(titzer): This should be in a JSOperatorReducer.
2780   switch (input->opcode()) {
2781     case IrOpcode::kInt32Constant:
2782       return jsgraph_->BooleanConstant(!Int32Matcher(input).Is(0));
2783     case IrOpcode::kFloat64Constant:
2784       return jsgraph_->BooleanConstant(!Float64Matcher(input).Is(0));
2785     case IrOpcode::kNumberConstant:
2786       return jsgraph_->BooleanConstant(!NumberMatcher(input).Is(0));
2787     case IrOpcode::kHeapConstant: {
2788       Handle<Object> object = HeapObjectMatcher<Object>(input).Value().handle();
2789       return jsgraph_->BooleanConstant(object->BooleanValue());
2790     }
2791     default:
2792       break;
2793   }
2794   if (NodeProperties::IsTyped(input)) {
2795     Type* upper = NodeProperties::GetBounds(input).upper;
2796     if (upper->Is(Type::Boolean())) return input;
2797   }
2798
2799   return NewNode(javascript()->ToBoolean(), input);
2800 }
2801
2802
2803 Node* AstGraphBuilder::BuildToName(Node* input, BailoutId bailout_id) {
2804   // TODO(turbofan): Possible optimization is to NOP on name constants. But the
2805   // same caveat as with BuildToBoolean applies, and it should be factored out
2806   // into a JSOperatorReducer.
2807   Node* name = NewNode(javascript()->ToName(), input);
2808   PrepareFrameState(name, bailout_id);
2809   return name;
2810 }
2811
2812
2813 Node* AstGraphBuilder::BuildSetHomeObject(Node* value, Node* home_object,
2814                                           Expression* expr) {
2815   if (!FunctionLiteral::NeedsHomeObject(expr)) return value;
2816   Unique<Name> name = MakeUnique(isolate()->factory()->home_object_symbol());
2817   const Operator* op = javascript()->StoreNamed(language_mode(), name);
2818   Node* store = NewNode(op, value, home_object);
2819   PrepareFrameState(store, BailoutId::None());
2820   return store;
2821 }
2822
2823
2824 Node* AstGraphBuilder::BuildThrowReferenceError(Variable* variable,
2825                                                 BailoutId bailout_id) {
2826   // TODO(mstarzinger): Should be unified with the VisitThrow implementation.
2827   Node* variable_name = jsgraph()->Constant(variable->name());
2828   const Operator* op =
2829       javascript()->CallRuntime(Runtime::kThrowReferenceError, 1);
2830   Node* call = NewNode(op, variable_name);
2831   PrepareFrameState(call, bailout_id);
2832   return call;
2833 }
2834
2835
2836 Node* AstGraphBuilder::BuildThrowConstAssignError(BailoutId bailout_id) {
2837   // TODO(mstarzinger): Should be unified with the VisitThrow implementation.
2838   const Operator* op =
2839       javascript()->CallRuntime(Runtime::kThrowConstAssignError, 0);
2840   Node* call = NewNode(op);
2841   PrepareFrameState(call, bailout_id);
2842   return call;
2843 }
2844
2845
2846 Node* AstGraphBuilder::BuildReturn(Node* return_value) {
2847   Node* control = NewNode(common()->Return(), return_value);
2848   UpdateControlDependencyToLeaveFunction(control);
2849   return control;
2850 }
2851
2852
2853 Node* AstGraphBuilder::BuildThrow(Node* exception_value) {
2854   NewNode(javascript()->CallRuntime(Runtime::kReThrow, 1), exception_value);
2855   Node* control = NewNode(common()->Throw(), exception_value);
2856   UpdateControlDependencyToLeaveFunction(control);
2857   return control;
2858 }
2859
2860
2861 Node* AstGraphBuilder::BuildBinaryOp(Node* left, Node* right, Token::Value op) {
2862   const Operator* js_op;
2863   switch (op) {
2864     case Token::BIT_OR:
2865       js_op = javascript()->BitwiseOr();
2866       break;
2867     case Token::BIT_AND:
2868       js_op = javascript()->BitwiseAnd();
2869       break;
2870     case Token::BIT_XOR:
2871       js_op = javascript()->BitwiseXor();
2872       break;
2873     case Token::SHL:
2874       js_op = javascript()->ShiftLeft();
2875       break;
2876     case Token::SAR:
2877       js_op = javascript()->ShiftRight();
2878       break;
2879     case Token::SHR:
2880       js_op = javascript()->ShiftRightLogical();
2881       break;
2882     case Token::ADD:
2883       js_op = javascript()->Add();
2884       break;
2885     case Token::SUB:
2886       js_op = javascript()->Subtract();
2887       break;
2888     case Token::MUL:
2889       js_op = javascript()->Multiply();
2890       break;
2891     case Token::DIV:
2892       js_op = javascript()->Divide();
2893       break;
2894     case Token::MOD:
2895       js_op = javascript()->Modulus();
2896       break;
2897     default:
2898       UNREACHABLE();
2899       js_op = NULL;
2900   }
2901   return NewNode(js_op, left, right);
2902 }
2903
2904
2905 Node* AstGraphBuilder::BuildStackCheck() {
2906   IfBuilder stack_check(this);
2907   Node* limit =
2908       NewNode(jsgraph()->machine()->Load(kMachPtr),
2909               jsgraph()->ExternalConstant(
2910                   ExternalReference::address_of_stack_limit(isolate())),
2911               jsgraph()->ZeroConstant());
2912   Node* stack = NewNode(jsgraph()->machine()->LoadStackPointer());
2913   Node* tag = NewNode(jsgraph()->machine()->UintLessThan(), limit, stack);
2914   stack_check.If(tag, BranchHint::kTrue);
2915   stack_check.Then();
2916   stack_check.Else();
2917   Node* guard = NewNode(javascript()->CallRuntime(Runtime::kStackGuard, 0));
2918   stack_check.End();
2919   return guard;
2920 }
2921
2922
2923 bool AstGraphBuilder::CheckOsrEntry(IterationStatement* stmt) {
2924   if (info()->osr_ast_id() == stmt->OsrEntryId()) {
2925     info()->set_osr_expr_stack_height(std::max(
2926         environment()->stack_height(), info()->osr_expr_stack_height()));
2927     return true;
2928   }
2929   return false;
2930 }
2931
2932
2933 void AstGraphBuilder::PrepareFrameState(Node* node, BailoutId ast_id,
2934                                         OutputFrameStateCombine combine) {
2935   if (OperatorProperties::HasFrameStateInput(node->op())) {
2936     DCHECK(NodeProperties::GetFrameStateInput(node)->opcode() ==
2937            IrOpcode::kDead);
2938     NodeProperties::ReplaceFrameStateInput(
2939         node, environment()->Checkpoint(ast_id, combine));
2940   }
2941 }
2942
2943
2944 BitVector* AstGraphBuilder::GetVariablesAssignedInLoop(
2945     IterationStatement* stmt) {
2946   if (loop_assignment_analysis_ == NULL) return NULL;
2947   return loop_assignment_analysis_->GetVariablesAssignedInLoop(stmt);
2948 }
2949
2950
2951 Node** AstGraphBuilder::EnsureInputBufferSize(int size) {
2952   if (size > input_buffer_size_) {
2953     size = size + kInputBufferSizeIncrement + input_buffer_size_;
2954     input_buffer_ = local_zone()->NewArray<Node*>(size);
2955     input_buffer_size_ = size;
2956   }
2957   return input_buffer_;
2958 }
2959
2960
2961 Node* AstGraphBuilder::MakeNode(const Operator* op, int value_input_count,
2962                                 Node** value_inputs, bool incomplete) {
2963   DCHECK(op->ValueInputCount() == value_input_count);
2964
2965   bool has_context = OperatorProperties::HasContextInput(op);
2966   bool has_framestate = OperatorProperties::HasFrameStateInput(op);
2967   bool has_control = op->ControlInputCount() == 1;
2968   bool has_effect = op->EffectInputCount() == 1;
2969
2970   DCHECK(op->ControlInputCount() < 2);
2971   DCHECK(op->EffectInputCount() < 2);
2972
2973   Node* result = NULL;
2974   if (!has_context && !has_framestate && !has_control && !has_effect) {
2975     result = graph()->NewNode(op, value_input_count, value_inputs, incomplete);
2976   } else {
2977     int input_count_with_deps = value_input_count;
2978     if (has_context) ++input_count_with_deps;
2979     if (has_framestate) ++input_count_with_deps;
2980     if (has_control) ++input_count_with_deps;
2981     if (has_effect) ++input_count_with_deps;
2982     Node** buffer = EnsureInputBufferSize(input_count_with_deps);
2983     memcpy(buffer, value_inputs, kPointerSize * value_input_count);
2984     Node** current_input = buffer + value_input_count;
2985     if (has_context) {
2986       *current_input++ = current_context();
2987     }
2988     if (has_framestate) {
2989       // The frame state will be inserted later. Here we misuse
2990       // the {DeadControl} node as a sentinel to be later overwritten
2991       // with the real frame state.
2992       *current_input++ = jsgraph()->DeadControl();
2993     }
2994     if (has_effect) {
2995       *current_input++ = environment_->GetEffectDependency();
2996     }
2997     if (has_control) {
2998       *current_input++ = environment_->GetControlDependency();
2999     }
3000     result = graph()->NewNode(op, input_count_with_deps, buffer, incomplete);
3001     if (has_effect) {
3002       environment_->UpdateEffectDependency(result);
3003     }
3004     if (result->op()->ControlOutputCount() > 0 &&
3005         !environment()->IsMarkedAsUnreachable()) {
3006       environment_->UpdateControlDependency(result);
3007     }
3008   }
3009
3010   return result;
3011 }
3012
3013
3014 void AstGraphBuilder::UpdateControlDependencyToLeaveFunction(Node* exit) {
3015   if (environment()->IsMarkedAsUnreachable()) return;
3016   if (exit_control() != NULL) {
3017     exit = MergeControl(exit_control(), exit);
3018   }
3019   environment()->MarkAsUnreachable();
3020   set_exit_control(exit);
3021 }
3022
3023
3024 void AstGraphBuilder::Environment::Merge(Environment* other) {
3025   DCHECK(values_.size() == other->values_.size());
3026   // TODO(titzer): make context stack heights match.
3027   DCHECK(contexts_.size() <= other->contexts_.size());
3028
3029   // Nothing to do if the other environment is dead.
3030   if (other->IsMarkedAsUnreachable()) return;
3031
3032   // Resurrect a dead environment by copying the contents of the other one and
3033   // placing a singleton merge as the new control dependency.
3034   if (this->IsMarkedAsUnreachable()) {
3035     Node* other_control = other->control_dependency_;
3036     Node* inputs[] = {other_control};
3037     control_dependency_ =
3038         graph()->NewNode(common()->Merge(1), arraysize(inputs), inputs, true);
3039     effect_dependency_ = other->effect_dependency_;
3040     values_ = other->values_;
3041     // TODO(titzer): make context stack heights match.
3042     size_t min = std::min(contexts_.size(), other->contexts_.size());
3043     contexts_ = other->contexts_;
3044     contexts_.resize(min, nullptr);
3045     return;
3046   }
3047
3048   // Create a merge of the control dependencies of both environments and update
3049   // the current environment's control dependency accordingly.
3050   Node* control = builder_->MergeControl(this->GetControlDependency(),
3051                                          other->GetControlDependency());
3052   UpdateControlDependency(control);
3053
3054   // Create a merge of the effect dependencies of both environments and update
3055   // the current environment's effect dependency accordingly.
3056   Node* effect = builder_->MergeEffect(this->GetEffectDependency(),
3057                                        other->GetEffectDependency(), control);
3058   UpdateEffectDependency(effect);
3059
3060   // Introduce Phi nodes for values that have differing input at merge points,
3061   // potentially extending an existing Phi node if possible.
3062   for (int i = 0; i < static_cast<int>(values_.size()); ++i) {
3063     values_[i] = builder_->MergeValue(values_[i], other->values_[i], control);
3064   }
3065   for (int i = 0; i < static_cast<int>(contexts_.size()); ++i) {
3066     contexts_[i] =
3067         builder_->MergeValue(contexts_[i], other->contexts_[i], control);
3068   }
3069 }
3070
3071
3072 void AstGraphBuilder::Environment::PrepareForLoop(BitVector* assigned,
3073                                                   bool is_osr) {
3074   int size = static_cast<int>(values()->size());
3075
3076   Node* control = builder_->NewLoop();
3077   if (assigned == nullptr) {
3078     // Assume that everything is updated in the loop.
3079     for (int i = 0; i < size; ++i) {
3080       values()->at(i) = builder_->NewPhi(1, values()->at(i), control);
3081     }
3082   } else {
3083     // Only build phis for those locals assigned in this loop.
3084     for (int i = 0; i < size; ++i) {
3085       if (i < assigned->length() && !assigned->Contains(i)) continue;
3086       Node* phi = builder_->NewPhi(1, values()->at(i), control);
3087       values()->at(i) = phi;
3088     }
3089   }
3090   Node* effect = builder_->NewEffectPhi(1, GetEffectDependency(), control);
3091   UpdateEffectDependency(effect);
3092
3093   if (builder_->info()->is_osr()) {
3094     // Introduce phis for all context values in the case of an OSR graph.
3095     for (int i = 0; i < static_cast<int>(contexts()->size()); ++i) {
3096       Node* val = contexts()->at(i);
3097       if (!IrOpcode::IsConstantOpcode(val->opcode())) {
3098         contexts()->at(i) = builder_->NewPhi(1, val, control);
3099       }
3100     }
3101   }
3102
3103   if (is_osr) {
3104     // Merge OSR values as inputs to the phis of the loop.
3105     Graph* graph = builder_->graph();
3106     Node* osr_loop_entry = builder_->graph()->NewNode(
3107         builder_->common()->OsrLoopEntry(), graph->start(), graph->start());
3108
3109     builder_->MergeControl(control, osr_loop_entry);
3110     builder_->MergeEffect(effect, osr_loop_entry, control);
3111
3112     for (int i = 0; i < size; ++i) {
3113       Node* val = values()->at(i);
3114       if (!IrOpcode::IsConstantOpcode(val->opcode())) {
3115         Node* osr_value =
3116             graph->NewNode(builder_->common()->OsrValue(i), osr_loop_entry);
3117         values()->at(i) = builder_->MergeValue(val, osr_value, control);
3118       }
3119     }
3120
3121     // Rename all the contexts in the environment.
3122     // The innermost context is the OSR value, and the outer contexts are
3123     // reconstructed by dynamically walking up the context chain.
3124     Node* osr_context = nullptr;
3125     const Operator* op =
3126         builder_->javascript()->LoadContext(0, Context::PREVIOUS_INDEX, true);
3127     int last = static_cast<int>(contexts()->size() - 1);
3128     for (int i = last; i >= 0; i--) {
3129       Node* val = contexts()->at(i);
3130       if (!IrOpcode::IsConstantOpcode(val->opcode())) {
3131         osr_context = (i == last) ? builder_->NewCurrentContextOsrValue()
3132                                   : graph->NewNode(op, osr_context, osr_context,
3133                                                    osr_loop_entry);
3134         contexts()->at(i) = builder_->MergeValue(val, osr_context, control);
3135       } else {
3136         osr_context = val;
3137       }
3138     }
3139   }
3140 }
3141
3142
3143 Node* AstGraphBuilder::NewPhi(int count, Node* input, Node* control) {
3144   const Operator* phi_op = common()->Phi(kMachAnyTagged, count);
3145   Node** buffer = EnsureInputBufferSize(count + 1);
3146   MemsetPointer(buffer, input, count);
3147   buffer[count] = control;
3148   return graph()->NewNode(phi_op, count + 1, buffer, true);
3149 }
3150
3151
3152 // TODO(mstarzinger): Revisit this once we have proper effect states.
3153 Node* AstGraphBuilder::NewEffectPhi(int count, Node* input, Node* control) {
3154   const Operator* phi_op = common()->EffectPhi(count);
3155   Node** buffer = EnsureInputBufferSize(count + 1);
3156   MemsetPointer(buffer, input, count);
3157   buffer[count] = control;
3158   return graph()->NewNode(phi_op, count + 1, buffer, true);
3159 }
3160
3161
3162 Node* AstGraphBuilder::MergeControl(Node* control, Node* other) {
3163   int inputs = control->op()->ControlInputCount() + 1;
3164   if (control->opcode() == IrOpcode::kLoop) {
3165     // Control node for loop exists, add input.
3166     const Operator* op = common()->Loop(inputs);
3167     control->AppendInput(graph_zone(), other);
3168     control->set_op(op);
3169   } else if (control->opcode() == IrOpcode::kMerge) {
3170     // Control node for merge exists, add input.
3171     const Operator* op = common()->Merge(inputs);
3172     control->AppendInput(graph_zone(), other);
3173     control->set_op(op);
3174   } else {
3175     // Control node is a singleton, introduce a merge.
3176     const Operator* op = common()->Merge(inputs);
3177     Node* inputs[] = {control, other};
3178     control = graph()->NewNode(op, arraysize(inputs), inputs, true);
3179   }
3180   return control;
3181 }
3182
3183
3184 Node* AstGraphBuilder::MergeEffect(Node* value, Node* other, Node* control) {
3185   int inputs = control->op()->ControlInputCount();
3186   if (value->opcode() == IrOpcode::kEffectPhi &&
3187       NodeProperties::GetControlInput(value) == control) {
3188     // Phi already exists, add input.
3189     value->set_op(common()->EffectPhi(inputs));
3190     value->InsertInput(graph_zone(), inputs - 1, other);
3191   } else if (value != other) {
3192     // Phi does not exist yet, introduce one.
3193     value = NewEffectPhi(inputs, value, control);
3194     value->ReplaceInput(inputs - 1, other);
3195   }
3196   return value;
3197 }
3198
3199
3200 Node* AstGraphBuilder::MergeValue(Node* value, Node* other, Node* control) {
3201   int inputs = control->op()->ControlInputCount();
3202   if (value->opcode() == IrOpcode::kPhi &&
3203       NodeProperties::GetControlInput(value) == control) {
3204     // Phi already exists, add input.
3205     value->set_op(common()->Phi(kMachAnyTagged, inputs));
3206     value->InsertInput(graph_zone(), inputs - 1, other);
3207   } else if (value != other) {
3208     // Phi does not exist yet, introduce one.
3209     value = NewPhi(inputs, value, control);
3210     value->ReplaceInput(inputs - 1, other);
3211   }
3212   return value;
3213 }
3214
3215 }  // namespace compiler
3216 }  // namespace internal
3217 }  // namespace v8