[stubs] Use a single slot for context globals.
[platform/upstream/v8.git] / 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/js-type-feedback.h"
11 #include "src/compiler/linkage.h"
12 #include "src/compiler/liveness-analyzer.h"
13 #include "src/compiler/machine-operator.h"
14 #include "src/compiler/node-matchers.h"
15 #include "src/compiler/node-properties.h"
16 #include "src/compiler/operator-properties.h"
17 #include "src/compiler/state-values-utils.h"
18 #include "src/full-codegen/full-codegen.h"
19 #include "src/parser.h"
20 #include "src/scopes.h"
21
22 namespace v8 {
23 namespace internal {
24 namespace compiler {
25
26
27 // Each expression in the AST is evaluated in a specific context. This context
28 // decides how the evaluation result is passed up the visitor.
29 class AstGraphBuilder::AstContext BASE_EMBEDDED {
30  public:
31   bool IsEffect() const { return kind_ == Expression::kEffect; }
32   bool IsValue() const { return kind_ == Expression::kValue; }
33   bool IsTest() const { return kind_ == Expression::kTest; }
34
35   // Determines how to combine the frame state with the value
36   // that is about to be plugged into this AstContext.
37   OutputFrameStateCombine GetStateCombine() {
38     return IsEffect() ? OutputFrameStateCombine::Ignore()
39                       : OutputFrameStateCombine::Push();
40   }
41
42   // Plug a node into this expression context.  Call this function in tail
43   // position in the Visit functions for expressions.
44   virtual void ProduceValue(Node* value) = 0;
45
46   // Unplugs a node from this expression context.  Call this to retrieve the
47   // result of another Visit function that already plugged the context.
48   virtual Node* ConsumeValue() = 0;
49
50   // Shortcut for "context->ProduceValue(context->ConsumeValue())".
51   void ReplaceValue() { ProduceValue(ConsumeValue()); }
52
53  protected:
54   AstContext(AstGraphBuilder* owner, Expression::Context kind);
55   virtual ~AstContext();
56
57   AstGraphBuilder* owner() const { return owner_; }
58   Environment* environment() const { return owner_->environment(); }
59
60 // We want to be able to assert, in a context-specific way, that the stack
61 // height makes sense when the context is filled.
62 #ifdef DEBUG
63   int original_height_;
64 #endif
65
66  private:
67   Expression::Context kind_;
68   AstGraphBuilder* owner_;
69   AstContext* outer_;
70 };
71
72
73 // Context to evaluate expression for its side effects only.
74 class AstGraphBuilder::AstEffectContext final : public AstContext {
75  public:
76   explicit AstEffectContext(AstGraphBuilder* owner)
77       : AstContext(owner, Expression::kEffect) {}
78   ~AstEffectContext() final;
79   void ProduceValue(Node* value) final;
80   Node* ConsumeValue() final;
81 };
82
83
84 // Context to evaluate expression for its value (and side effects).
85 class AstGraphBuilder::AstValueContext final : public AstContext {
86  public:
87   explicit AstValueContext(AstGraphBuilder* owner)
88       : AstContext(owner, Expression::kValue) {}
89   ~AstValueContext() final;
90   void ProduceValue(Node* value) final;
91   Node* ConsumeValue() final;
92 };
93
94
95 // Context to evaluate expression for a condition value (and side effects).
96 class AstGraphBuilder::AstTestContext final : public AstContext {
97  public:
98   explicit AstTestContext(AstGraphBuilder* owner)
99       : AstContext(owner, Expression::kTest) {}
100   ~AstTestContext() final;
101   void ProduceValue(Node* value) final;
102   Node* ConsumeValue() final;
103 };
104
105
106 // Scoped class tracking context objects created by the visitor. Represents
107 // mutations of the context chain within the function body and allows to
108 // change the current {scope} and {context} during visitation.
109 class AstGraphBuilder::ContextScope BASE_EMBEDDED {
110  public:
111   ContextScope(AstGraphBuilder* builder, Scope* scope, Node* context)
112       : builder_(builder),
113         outer_(builder->execution_context()),
114         scope_(scope),
115         depth_(builder_->environment()->context_chain_length()) {
116     builder_->environment()->PushContext(context);  // Push.
117     builder_->set_execution_context(this);
118   }
119
120   ~ContextScope() {
121     builder_->set_execution_context(outer_);  // Pop.
122     builder_->environment()->PopContext();
123     CHECK_EQ(depth_, builder_->environment()->context_chain_length());
124   }
125
126   // Current scope during visitation.
127   Scope* scope() const { return scope_; }
128
129  private:
130   AstGraphBuilder* builder_;
131   ContextScope* outer_;
132   Scope* scope_;
133   int depth_;
134 };
135
136
137 // Scoped class tracking control statements entered by the visitor. There are
138 // different types of statements participating in this stack to properly track
139 // local as well as non-local control flow:
140 //  - IterationStatement : Allows proper 'break' and 'continue' behavior.
141 //  - BreakableStatement : Allows 'break' from block and switch statements.
142 //  - TryCatchStatement  : Intercepts 'throw' and implicit exceptional edges.
143 //  - TryFinallyStatement: Intercepts 'break', 'continue', 'throw' and 'return'.
144 class AstGraphBuilder::ControlScope BASE_EMBEDDED {
145  public:
146   explicit ControlScope(AstGraphBuilder* builder)
147       : builder_(builder),
148         outer_(builder->execution_control()),
149         context_length_(builder->environment()->context_chain_length()),
150         stack_height_(builder->environment()->stack_height()) {
151     builder_->set_execution_control(this);  // Push.
152   }
153
154   virtual ~ControlScope() {
155     builder_->set_execution_control(outer_);  // Pop.
156   }
157
158   // Either 'break' or 'continue' to the target statement.
159   void BreakTo(BreakableStatement* target);
160   void ContinueTo(BreakableStatement* target);
161
162   // Either 'return' or 'throw' the given value.
163   void ReturnValue(Node* return_value);
164   void ThrowValue(Node* exception_value);
165
166   class DeferredCommands;
167
168  protected:
169   enum Command { CMD_BREAK, CMD_CONTINUE, CMD_RETURN, CMD_THROW };
170
171   // Performs one of the above commands on this stack of control scopes. This
172   // walks through the stack giving each scope a chance to execute or defer the
173   // given command by overriding the {Execute} method appropriately. Note that
174   // this also drops extra operands from the environment for each skipped scope.
175   void PerformCommand(Command cmd, Statement* target, Node* value);
176
177   // Interface to execute a given command in this scope. Returning {true} here
178   // indicates successful execution whereas {false} requests to skip scope.
179   virtual bool Execute(Command cmd, Statement* target, Node* value) {
180     // For function-level control.
181     switch (cmd) {
182       case CMD_THROW:
183         builder()->BuildThrow(value);
184         return true;
185       case CMD_RETURN:
186         builder()->BuildReturn(value);
187         return true;
188       case CMD_BREAK:
189       case CMD_CONTINUE:
190         break;
191     }
192     return false;
193   }
194
195   Environment* environment() { return builder_->environment(); }
196   AstGraphBuilder* builder() const { return builder_; }
197   int context_length() const { return context_length_; }
198   int stack_height() const { return stack_height_; }
199
200  private:
201   AstGraphBuilder* builder_;
202   ControlScope* outer_;
203   int context_length_;
204   int stack_height_;
205 };
206
207
208 // Helper class for a try-finally control scope. It can record intercepted
209 // control-flow commands that cause entry into a finally-block, and re-apply
210 // them after again leaving that block. Special tokens are used to identify
211 // paths going through the finally-block to dispatch after leaving the block.
212 class AstGraphBuilder::ControlScope::DeferredCommands : public ZoneObject {
213  public:
214   explicit DeferredCommands(AstGraphBuilder* owner)
215       : owner_(owner), deferred_(owner->zone()) {}
216
217   // One recorded control-flow command.
218   struct Entry {
219     Command command;       // The command type being applied on this path.
220     Statement* statement;  // The target statement for the command or {NULL}.
221     Node* token;           // A token identifying this particular path.
222   };
223
224   // Records a control-flow command while entering the finally-block. This also
225   // generates a new dispatch token that identifies one particular path.
226   Node* RecordCommand(Command cmd, Statement* stmt, Node* value) {
227     Node* token = NewPathTokenForDeferredCommand();
228     deferred_.push_back({cmd, stmt, token});
229     return token;
230   }
231
232   // Returns the dispatch token to be used to identify the implicit fall-through
233   // path at the end of a try-block into the corresponding finally-block.
234   Node* GetFallThroughToken() { return NewPathTokenForImplicitFallThrough(); }
235
236   // Applies all recorded control-flow commands after the finally-block again.
237   // This generates a dynamic dispatch on the token from the entry point.
238   void ApplyDeferredCommands(Node* token, Node* value) {
239     SwitchBuilder dispatch(owner_, static_cast<int>(deferred_.size()));
240     dispatch.BeginSwitch();
241     for (size_t i = 0; i < deferred_.size(); ++i) {
242       Node* condition = NewPathDispatchCondition(token, deferred_[i].token);
243       dispatch.BeginLabel(static_cast<int>(i), condition);
244       dispatch.EndLabel();
245     }
246     for (size_t i = 0; i < deferred_.size(); ++i) {
247       dispatch.BeginCase(static_cast<int>(i));
248       owner_->execution_control()->PerformCommand(
249           deferred_[i].command, deferred_[i].statement, value);
250       dispatch.EndCase();
251     }
252     dispatch.EndSwitch();
253   }
254
255  protected:
256   Node* NewPathTokenForDeferredCommand() {
257     return owner_->jsgraph()->Constant(static_cast<int>(deferred_.size()));
258   }
259   Node* NewPathTokenForImplicitFallThrough() {
260     return owner_->jsgraph()->Constant(-1);
261   }
262   Node* NewPathDispatchCondition(Node* t1, Node* t2) {
263     // TODO(mstarzinger): This should be machine()->WordEqual(), but our Phi
264     // nodes all have kRepTagged|kTypeAny, which causes representation mismatch.
265     return owner_->NewNode(owner_->javascript()->StrictEqual(), t1, t2);
266   }
267
268  private:
269   AstGraphBuilder* owner_;
270   ZoneVector<Entry> deferred_;
271 };
272
273
274 // Control scope implementation for a BreakableStatement.
275 class AstGraphBuilder::ControlScopeForBreakable : public ControlScope {
276  public:
277   ControlScopeForBreakable(AstGraphBuilder* owner, BreakableStatement* target,
278                            ControlBuilder* control)
279       : ControlScope(owner), target_(target), control_(control) {}
280
281  protected:
282   virtual bool Execute(Command cmd, Statement* target, Node* value) override {
283     if (target != target_) return false;  // We are not the command target.
284     switch (cmd) {
285       case CMD_BREAK:
286         control_->Break();
287         return true;
288       case CMD_CONTINUE:
289       case CMD_THROW:
290       case CMD_RETURN:
291         break;
292     }
293     return false;
294   }
295
296  private:
297   BreakableStatement* target_;
298   ControlBuilder* control_;
299 };
300
301
302 // Control scope implementation for an IterationStatement.
303 class AstGraphBuilder::ControlScopeForIteration : public ControlScope {
304  public:
305   ControlScopeForIteration(AstGraphBuilder* owner, IterationStatement* target,
306                            LoopBuilder* control)
307       : ControlScope(owner), target_(target), control_(control) {}
308
309  protected:
310   virtual bool Execute(Command cmd, Statement* target, Node* value) override {
311     if (target != target_) return false;  // We are not the command target.
312     switch (cmd) {
313       case CMD_BREAK:
314         control_->Break();
315         return true;
316       case CMD_CONTINUE:
317         control_->Continue();
318         return true;
319       case CMD_THROW:
320       case CMD_RETURN:
321         break;
322     }
323     return false;
324   }
325
326  private:
327   BreakableStatement* target_;
328   LoopBuilder* control_;
329 };
330
331
332 // Control scope implementation for a TryCatchStatement.
333 class AstGraphBuilder::ControlScopeForCatch : public ControlScope {
334  public:
335   ControlScopeForCatch(AstGraphBuilder* owner, TryCatchBuilder* control)
336       : ControlScope(owner), control_(control) {
337     builder()->try_nesting_level_++;  // Increment nesting.
338     builder()->try_catch_nesting_level_++;
339   }
340   ~ControlScopeForCatch() {
341     builder()->try_nesting_level_--;  // Decrement nesting.
342     builder()->try_catch_nesting_level_--;
343   }
344
345  protected:
346   virtual bool Execute(Command cmd, Statement* target, Node* value) override {
347     switch (cmd) {
348       case CMD_THROW:
349         control_->Throw(value);
350         return true;
351       case CMD_BREAK:
352       case CMD_CONTINUE:
353       case CMD_RETURN:
354         break;
355     }
356     return false;
357   }
358
359  private:
360   TryCatchBuilder* control_;
361 };
362
363
364 // Control scope implementation for a TryFinallyStatement.
365 class AstGraphBuilder::ControlScopeForFinally : public ControlScope {
366  public:
367   ControlScopeForFinally(AstGraphBuilder* owner, DeferredCommands* commands,
368                          TryFinallyBuilder* control)
369       : ControlScope(owner), commands_(commands), control_(control) {
370     builder()->try_nesting_level_++;  // Increment nesting.
371   }
372   ~ControlScopeForFinally() {
373     builder()->try_nesting_level_--;  // Decrement nesting.
374   }
375
376  protected:
377   virtual bool Execute(Command cmd, Statement* target, Node* value) override {
378     Node* token = commands_->RecordCommand(cmd, target, value);
379     control_->LeaveTry(token, value);
380     return true;
381   }
382
383  private:
384   DeferredCommands* commands_;
385   TryFinallyBuilder* control_;
386 };
387
388
389 // Helper for generating before and after frame states.
390 class AstGraphBuilder::FrameStateBeforeAndAfter {
391  public:
392   FrameStateBeforeAndAfter(AstGraphBuilder* builder, BailoutId id_before)
393       : builder_(builder), frame_state_before_(nullptr) {
394     frame_state_before_ = id_before == BailoutId::None()
395                               ? builder_->jsgraph()->EmptyFrameState()
396                               : builder_->environment()->Checkpoint(id_before);
397   }
398
399   void AddToNode(Node* node, BailoutId id_after,
400                  OutputFrameStateCombine combine) {
401     int count = OperatorProperties::GetFrameStateInputCount(node->op());
402     DCHECK_LE(count, 2);
403
404     if (count >= 1) {
405       // Add the frame state for after the operation.
406       DCHECK_EQ(IrOpcode::kDead,
407                 NodeProperties::GetFrameStateInput(node, 0)->opcode());
408
409       Node* frame_state_after =
410           id_after == BailoutId::None()
411               ? builder_->jsgraph()->EmptyFrameState()
412               : builder_->environment()->Checkpoint(id_after, combine);
413
414       NodeProperties::ReplaceFrameStateInput(node, 0, frame_state_after);
415     }
416
417     if (count >= 2) {
418       // Add the frame state for before the operation.
419       DCHECK_EQ(IrOpcode::kDead,
420                 NodeProperties::GetFrameStateInput(node, 1)->opcode());
421       NodeProperties::ReplaceFrameStateInput(node, 1, frame_state_before_);
422     }
423   }
424
425  private:
426   AstGraphBuilder* builder_;
427   Node* frame_state_before_;
428 };
429
430
431 AstGraphBuilder::AstGraphBuilder(Zone* local_zone, CompilationInfo* info,
432                                  JSGraph* jsgraph, LoopAssignmentAnalysis* loop,
433                                  JSTypeFeedbackTable* js_type_feedback)
434     : local_zone_(local_zone),
435       info_(info),
436       jsgraph_(jsgraph),
437       environment_(nullptr),
438       ast_context_(nullptr),
439       globals_(0, local_zone),
440       execution_control_(nullptr),
441       execution_context_(nullptr),
442       try_catch_nesting_level_(0),
443       try_nesting_level_(0),
444       input_buffer_size_(0),
445       input_buffer_(nullptr),
446       exit_controls_(local_zone),
447       loop_assignment_analysis_(loop),
448       state_values_cache_(jsgraph),
449       liveness_analyzer_(static_cast<size_t>(info->scope()->num_stack_slots()),
450                          local_zone),
451       frame_state_function_info_(common()->CreateFrameStateFunctionInfo(
452           FrameStateType::kJavaScriptFunction, info->num_parameters() + 1,
453           info->scope()->num_stack_slots(), info->shared_info(),
454           CALL_MAINTAINS_NATIVE_CONTEXT)),
455       js_type_feedback_(js_type_feedback) {
456   InitializeAstVisitor(info->isolate(), local_zone);
457 }
458
459
460 Node* AstGraphBuilder::GetFunctionClosureForContext() {
461   Scope* closure_scope = current_scope()->ClosureScope();
462   if (closure_scope->is_script_scope() ||
463       closure_scope->is_module_scope()) {
464     // Contexts nested in the native context have a canonical empty function as
465     // their closure, not the anonymous closure containing the global code.
466     // Pass a SMI sentinel and let the runtime look up the empty function.
467     return jsgraph()->SmiConstant(0);
468   } else {
469     DCHECK(closure_scope->is_function_scope());
470     return GetFunctionClosure();
471   }
472 }
473
474
475 Node* AstGraphBuilder::GetFunctionClosure() {
476   if (!function_closure_.is_set()) {
477     const Operator* op = common()->Parameter(
478         Linkage::kJSFunctionCallClosureParamIndex, "%closure");
479     Node* node = NewNode(op, graph()->start());
480     function_closure_.set(node);
481   }
482   return function_closure_.get();
483 }
484
485
486 Node* AstGraphBuilder::GetFunctionContext() {
487   if (!function_context_.is_set()) {
488     // Parameter (arity + 1) is special for the outer context of the function
489     const Operator* op = common()->Parameter(
490         info()->num_parameters_including_this(), "%context");
491     Node* node = NewNode(op, graph()->start());
492     function_context_.set(node);
493   }
494   return function_context_.get();
495 }
496
497
498 bool AstGraphBuilder::CreateGraph(bool stack_check) {
499   Scope* scope = info()->scope();
500   DCHECK(graph() != NULL);
501
502   // Set up the basic structure of the graph. Outputs for {Start} are the formal
503   // parameters (including the receiver) plus context and closure.
504   int actual_parameter_count = info()->num_parameters_including_this() + 2;
505   graph()->SetStart(graph()->NewNode(common()->Start(actual_parameter_count)));
506
507   // Initialize the top-level environment.
508   Environment env(this, scope, graph()->start());
509   set_environment(&env);
510
511   if (info()->is_osr()) {
512     // Use OSR normal entry as the start of the top-level environment.
513     // It will be replaced with {Dead} after typing and optimizations.
514     NewNode(common()->OsrNormalEntry());
515   }
516
517   // Initialize the incoming context.
518   ContextScope incoming(this, scope, GetFunctionContext());
519
520   // Initialize control scope.
521   ControlScope control(this);
522
523   // TODO(mstarzinger): For now we cannot assume that the {this} parameter is
524   // not {the_hole}, because for derived classes {this} has a TDZ and the
525   // JSConstructStubForDerived magically passes {the_hole} as a receiver.
526   if (scope->has_this_declaration() && scope->receiver()->is_const_mode()) {
527     env.RawParameterBind(0, jsgraph()->TheHoleConstant());
528   }
529
530   // Build receiver check for sloppy mode if necessary.
531   // TODO(mstarzinger/verwaest): Should this be moved back into the CallIC?
532   if (scope->has_this_declaration()) {
533     Node* original_receiver = env.RawParameterLookup(0);
534     Node* patched_receiver = BuildPatchReceiverToGlobalProxy(original_receiver);
535     env.RawParameterBind(0, patched_receiver);
536   }
537
538   // Build function context only if there are context allocated variables.
539   if (info()->num_heap_slots() > 0) {
540     // Push a new inner context scope for the function.
541     Node* inner_context = BuildLocalFunctionContext(GetFunctionContext());
542     ContextScope top_context(this, scope, inner_context);
543     CreateGraphBody(stack_check);
544   } else {
545     // Simply use the outer function context in building the graph.
546     CreateGraphBody(stack_check);
547   }
548
549   // Finish the basic structure of the graph.
550   DCHECK_NE(0u, exit_controls_.size());
551   int const input_count = static_cast<int>(exit_controls_.size());
552   Node** const inputs = &exit_controls_.front();
553   Node* end = graph()->NewNode(common()->End(input_count), input_count, inputs);
554   graph()->SetEnd(end);
555
556   // Compute local variable liveness information and use it to relax
557   // frame states.
558   ClearNonLiveSlotsInFrameStates();
559
560   // Failures indicated by stack overflow.
561   return !HasStackOverflow();
562 }
563
564
565 void AstGraphBuilder::CreateGraphBody(bool stack_check) {
566   Scope* scope = info()->scope();
567
568   // Build the arguments object if it is used.
569   BuildArgumentsObject(scope->arguments());
570
571   // Build rest arguments array if it is used.
572   int rest_index;
573   Variable* rest_parameter = scope->rest_parameter(&rest_index);
574   BuildRestArgumentsArray(rest_parameter, rest_index);
575
576   // Build assignment to {.this_function} variable if it is used.
577   BuildThisFunctionVariable(scope->this_function_var());
578
579   // Build assignment to {new.target} variable if it is used.
580   BuildNewTargetVariable(scope->new_target_var());
581
582   // Emit tracing call if requested to do so.
583   if (FLAG_trace) {
584     NewNode(javascript()->CallRuntime(Runtime::kTraceEnter, 0));
585   }
586
587   // Visit illegal re-declaration and bail out if it exists.
588   if (scope->HasIllegalRedeclaration()) {
589     AstEffectContext for_effect(this);
590     scope->VisitIllegalRedeclaration(this);
591     return;
592   }
593
594   // Visit declarations within the function scope.
595   VisitDeclarations(scope->declarations());
596
597   // Build a stack-check before the body.
598   if (stack_check) {
599     Node* node = NewNode(javascript()->StackCheck());
600     PrepareFrameState(node, BailoutId::FunctionEntry());
601   }
602
603   // Visit statements in the function body.
604   VisitStatements(info()->function()->body());
605
606   // Emit tracing call if requested to do so.
607   if (FLAG_trace) {
608     // TODO(mstarzinger): Only traces implicit return.
609     Node* return_value = jsgraph()->UndefinedConstant();
610     NewNode(javascript()->CallRuntime(Runtime::kTraceExit, 1), return_value);
611   }
612
613   // Return 'undefined' in case we can fall off the end.
614   BuildReturn(jsgraph()->UndefinedConstant());
615 }
616
617
618 void AstGraphBuilder::ClearNonLiveSlotsInFrameStates() {
619   if (!FLAG_analyze_environment_liveness ||
620       !info()->is_deoptimization_enabled()) {
621     return;
622   }
623
624   NonLiveFrameStateSlotReplacer replacer(
625       &state_values_cache_, jsgraph()->UndefinedConstant(),
626       liveness_analyzer()->local_count(), local_zone());
627   Variable* arguments = info()->scope()->arguments();
628   if (arguments != nullptr && arguments->IsStackAllocated()) {
629     replacer.MarkPermanentlyLive(arguments->index());
630   }
631   liveness_analyzer()->Run(&replacer);
632   if (FLAG_trace_environment_liveness) {
633     OFStream os(stdout);
634     liveness_analyzer()->Print(os);
635   }
636 }
637
638
639 // Gets the bailout id just before reading a variable proxy, but only for
640 // unallocated variables.
641 static BailoutId BeforeId(VariableProxy* proxy) {
642   return proxy->var()->IsUnallocatedOrGlobalSlot() ? proxy->BeforeId()
643                                                    : BailoutId::None();
644 }
645
646
647 static const char* GetDebugParameterName(Zone* zone, Scope* scope, int index) {
648 #if DEBUG
649   const AstRawString* name = scope->parameter(index)->raw_name();
650   if (name && name->length() > 0) {
651     char* data = zone->NewArray<char>(name->length() + 1);
652     data[name->length()] = 0;
653     memcpy(data, name->raw_data(), name->length());
654     return data;
655   }
656 #endif
657   return nullptr;
658 }
659
660
661 AstGraphBuilder::Environment::Environment(AstGraphBuilder* builder,
662                                           Scope* scope,
663                                           Node* control_dependency)
664     : builder_(builder),
665       parameters_count_(scope->num_parameters() + 1),
666       locals_count_(scope->num_stack_slots()),
667       liveness_block_(IsLivenessAnalysisEnabled()
668                           ? builder_->liveness_analyzer()->NewBlock()
669                           : nullptr),
670       values_(builder_->local_zone()),
671       contexts_(builder_->local_zone()),
672       control_dependency_(control_dependency),
673       effect_dependency_(control_dependency),
674       parameters_node_(nullptr),
675       locals_node_(nullptr),
676       stack_node_(nullptr) {
677   DCHECK_EQ(scope->num_parameters() + 1, parameters_count());
678
679   // Bind the receiver variable.
680   int param_num = 0;
681   if (builder->info()->is_this_defined()) {
682     const Operator* op = common()->Parameter(param_num++, "%this");
683     Node* receiver = builder->graph()->NewNode(op, builder->graph()->start());
684     values()->push_back(receiver);
685   } else {
686     values()->push_back(builder->jsgraph()->UndefinedConstant());
687   }
688
689   // Bind all parameter variables. The parameter indices are shifted by 1
690   // (receiver is parameter index -1 but environment index 0).
691   for (int i = 0; i < scope->num_parameters(); ++i) {
692     const char* debug_name = GetDebugParameterName(graph()->zone(), scope, i);
693     const Operator* op = common()->Parameter(param_num++, debug_name);
694     Node* parameter = builder->graph()->NewNode(op, builder->graph()->start());
695     values()->push_back(parameter);
696   }
697
698   // Bind all local variables to undefined.
699   Node* undefined_constant = builder->jsgraph()->UndefinedConstant();
700   values()->insert(values()->end(), locals_count(), undefined_constant);
701 }
702
703
704 AstGraphBuilder::Environment::Environment(AstGraphBuilder::Environment* copy,
705                                           LivenessAnalyzerBlock* liveness_block)
706     : builder_(copy->builder_),
707       parameters_count_(copy->parameters_count_),
708       locals_count_(copy->locals_count_),
709       liveness_block_(liveness_block),
710       values_(copy->zone()),
711       contexts_(copy->zone()),
712       control_dependency_(copy->control_dependency_),
713       effect_dependency_(copy->effect_dependency_),
714       parameters_node_(copy->parameters_node_),
715       locals_node_(copy->locals_node_),
716       stack_node_(copy->stack_node_) {
717   const size_t kStackEstimate = 7;  // optimum from experimentation!
718   values_.reserve(copy->values_.size() + kStackEstimate);
719   values_.insert(values_.begin(), copy->values_.begin(), copy->values_.end());
720   contexts_.reserve(copy->contexts_.size());
721   contexts_.insert(contexts_.begin(), copy->contexts_.begin(),
722                    copy->contexts_.end());
723 }
724
725
726 void AstGraphBuilder::Environment::Bind(Variable* variable, Node* node) {
727   DCHECK(variable->IsStackAllocated());
728   if (variable->IsParameter()) {
729     // The parameter indices are shifted by 1 (receiver is parameter
730     // index -1 but environment index 0).
731     values()->at(variable->index() + 1) = node;
732   } else {
733     DCHECK(variable->IsStackLocal());
734     values()->at(variable->index() + parameters_count_) = node;
735     DCHECK(IsLivenessBlockConsistent());
736     if (liveness_block() != nullptr) {
737       liveness_block()->Bind(variable->index());
738     }
739   }
740 }
741
742
743 Node* AstGraphBuilder::Environment::Lookup(Variable* variable) {
744   DCHECK(variable->IsStackAllocated());
745   if (variable->IsParameter()) {
746     // The parameter indices are shifted by 1 (receiver is parameter
747     // index -1 but environment index 0).
748     return values()->at(variable->index() + 1);
749   } else {
750     DCHECK(variable->IsStackLocal());
751     DCHECK(IsLivenessBlockConsistent());
752     if (liveness_block() != nullptr) {
753       liveness_block()->Lookup(variable->index());
754     }
755     return values()->at(variable->index() + parameters_count_);
756   }
757 }
758
759
760 void AstGraphBuilder::Environment::MarkAllLocalsLive() {
761   DCHECK(IsLivenessBlockConsistent());
762   if (liveness_block() != nullptr) {
763     for (int i = 0; i < locals_count_; i++) {
764       liveness_block()->Lookup(i);
765     }
766   }
767 }
768
769
770 void AstGraphBuilder::Environment::RawParameterBind(int index, Node* node) {
771   DCHECK_LT(index, parameters_count());
772   values()->at(index) = node;
773 }
774
775
776 Node* AstGraphBuilder::Environment::RawParameterLookup(int index) {
777   DCHECK_LT(index, parameters_count());
778   return values()->at(index);
779 }
780
781
782 AstGraphBuilder::Environment*
783 AstGraphBuilder::Environment::CopyForConditional() {
784   LivenessAnalyzerBlock* copy_liveness_block = nullptr;
785   if (liveness_block() != nullptr) {
786     copy_liveness_block =
787         builder_->liveness_analyzer()->NewBlock(liveness_block());
788     liveness_block_ = builder_->liveness_analyzer()->NewBlock(liveness_block());
789   }
790   return new (zone()) Environment(this, copy_liveness_block);
791 }
792
793
794 AstGraphBuilder::Environment*
795 AstGraphBuilder::Environment::CopyAsUnreachable() {
796   Environment* env = new (zone()) Environment(this, nullptr);
797   env->MarkAsUnreachable();
798   return env;
799 }
800
801
802 AstGraphBuilder::Environment*
803 AstGraphBuilder::Environment::CopyAndShareLiveness() {
804   if (liveness_block() != nullptr) {
805     // Finish the current liveness block before copying.
806     liveness_block_ = builder_->liveness_analyzer()->NewBlock(liveness_block());
807   }
808   Environment* env = new (zone()) Environment(this, liveness_block());
809   return env;
810 }
811
812
813 AstGraphBuilder::Environment* AstGraphBuilder::Environment::CopyForLoop(
814     BitVector* assigned, bool is_osr) {
815   PrepareForLoop(assigned, is_osr);
816   return CopyAndShareLiveness();
817 }
818
819
820 void AstGraphBuilder::Environment::UpdateStateValues(Node** state_values,
821                                                      int offset, int count) {
822   bool should_update = false;
823   Node** env_values = (count == 0) ? nullptr : &values()->at(offset);
824   if (*state_values == NULL || (*state_values)->InputCount() != count) {
825     should_update = true;
826   } else {
827     DCHECK(static_cast<size_t>(offset + count) <= values()->size());
828     for (int i = 0; i < count; i++) {
829       if ((*state_values)->InputAt(i) != env_values[i]) {
830         should_update = true;
831         break;
832       }
833     }
834   }
835   if (should_update) {
836     const Operator* op = common()->StateValues(count);
837     (*state_values) = graph()->NewNode(op, count, env_values);
838   }
839 }
840
841
842 void AstGraphBuilder::Environment::UpdateStateValuesWithCache(
843     Node** state_values, int offset, int count) {
844   Node** env_values = (count == 0) ? nullptr : &values()->at(offset);
845   *state_values = builder_->state_values_cache_.GetNodeForValues(
846       env_values, static_cast<size_t>(count));
847 }
848
849
850 Node* AstGraphBuilder::Environment::Checkpoint(
851     BailoutId ast_id, OutputFrameStateCombine combine) {
852   if (!builder()->info()->is_deoptimization_enabled()) {
853     return builder()->jsgraph()->EmptyFrameState();
854   }
855
856   UpdateStateValues(&parameters_node_, 0, parameters_count());
857   UpdateStateValuesWithCache(&locals_node_, parameters_count(), locals_count());
858   UpdateStateValues(&stack_node_, parameters_count() + locals_count(),
859                     stack_height());
860
861   const Operator* op = common()->FrameState(
862       ast_id, combine, builder()->frame_state_function_info());
863
864   Node* result = graph()->NewNode(op, parameters_node_, locals_node_,
865                                   stack_node_, builder()->current_context(),
866                                   builder()->GetFunctionClosure(),
867                                   builder()->graph()->start());
868
869   DCHECK(IsLivenessBlockConsistent());
870   if (liveness_block() != nullptr) {
871     liveness_block()->Checkpoint(result);
872   }
873   return result;
874 }
875
876
877 bool AstGraphBuilder::Environment::IsLivenessAnalysisEnabled() {
878   return FLAG_analyze_environment_liveness &&
879          builder()->info()->is_deoptimization_enabled();
880 }
881
882
883 bool AstGraphBuilder::Environment::IsLivenessBlockConsistent() {
884   return (!IsLivenessAnalysisEnabled() || IsMarkedAsUnreachable()) ==
885          (liveness_block() == nullptr);
886 }
887
888
889 AstGraphBuilder::AstContext::AstContext(AstGraphBuilder* own,
890                                         Expression::Context kind)
891     : kind_(kind), owner_(own), outer_(own->ast_context()) {
892   owner()->set_ast_context(this);  // Push.
893 #ifdef DEBUG
894   original_height_ = environment()->stack_height();
895 #endif
896 }
897
898
899 AstGraphBuilder::AstContext::~AstContext() {
900   owner()->set_ast_context(outer_);  // Pop.
901 }
902
903
904 AstGraphBuilder::AstEffectContext::~AstEffectContext() {
905   DCHECK(environment()->stack_height() == original_height_);
906 }
907
908
909 AstGraphBuilder::AstValueContext::~AstValueContext() {
910   DCHECK(environment()->stack_height() == original_height_ + 1);
911 }
912
913
914 AstGraphBuilder::AstTestContext::~AstTestContext() {
915   DCHECK(environment()->stack_height() == original_height_ + 1);
916 }
917
918
919 void AstGraphBuilder::AstEffectContext::ProduceValue(Node* value) {
920   // The value is ignored.
921 }
922
923
924 void AstGraphBuilder::AstValueContext::ProduceValue(Node* value) {
925   environment()->Push(value);
926 }
927
928
929 void AstGraphBuilder::AstTestContext::ProduceValue(Node* value) {
930   environment()->Push(owner()->BuildToBoolean(value));
931 }
932
933
934 Node* AstGraphBuilder::AstEffectContext::ConsumeValue() { return NULL; }
935
936
937 Node* AstGraphBuilder::AstValueContext::ConsumeValue() {
938   return environment()->Pop();
939 }
940
941
942 Node* AstGraphBuilder::AstTestContext::ConsumeValue() {
943   return environment()->Pop();
944 }
945
946
947 Scope* AstGraphBuilder::current_scope() const {
948   return execution_context_->scope();
949 }
950
951
952 Node* AstGraphBuilder::current_context() const {
953   return environment()->Context();
954 }
955
956
957 void AstGraphBuilder::ControlScope::PerformCommand(Command command,
958                                                    Statement* target,
959                                                    Node* value) {
960   Environment* env = environment()->CopyAsUnreachable();
961   ControlScope* current = this;
962   while (current != NULL) {
963     environment()->TrimStack(current->stack_height());
964     environment()->TrimContextChain(current->context_length());
965     if (current->Execute(command, target, value)) break;
966     current = current->outer_;
967   }
968   builder()->set_environment(env);
969   DCHECK(current != NULL);  // Always handled (unless stack is malformed).
970 }
971
972
973 void AstGraphBuilder::ControlScope::BreakTo(BreakableStatement* stmt) {
974   PerformCommand(CMD_BREAK, stmt, builder()->jsgraph()->TheHoleConstant());
975 }
976
977
978 void AstGraphBuilder::ControlScope::ContinueTo(BreakableStatement* stmt) {
979   PerformCommand(CMD_CONTINUE, stmt, builder()->jsgraph()->TheHoleConstant());
980 }
981
982
983 void AstGraphBuilder::ControlScope::ReturnValue(Node* return_value) {
984   PerformCommand(CMD_RETURN, nullptr, return_value);
985 }
986
987
988 void AstGraphBuilder::ControlScope::ThrowValue(Node* exception_value) {
989   PerformCommand(CMD_THROW, nullptr, exception_value);
990 }
991
992
993 void AstGraphBuilder::VisitForValueOrNull(Expression* expr) {
994   if (expr == NULL) {
995     return environment()->Push(jsgraph()->NullConstant());
996   }
997   VisitForValue(expr);
998 }
999
1000
1001 void AstGraphBuilder::VisitForValueOrTheHole(Expression* expr) {
1002   if (expr == NULL) {
1003     return environment()->Push(jsgraph()->TheHoleConstant());
1004   }
1005   VisitForValue(expr);
1006 }
1007
1008
1009 void AstGraphBuilder::VisitForValues(ZoneList<Expression*>* exprs) {
1010   for (int i = 0; i < exprs->length(); ++i) {
1011     VisitForValue(exprs->at(i));
1012   }
1013 }
1014
1015
1016 void AstGraphBuilder::VisitForValue(Expression* expr) {
1017   AstValueContext for_value(this);
1018   if (!CheckStackOverflow()) {
1019     expr->Accept(this);
1020   } else {
1021     ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
1022   }
1023 }
1024
1025
1026 void AstGraphBuilder::VisitForEffect(Expression* expr) {
1027   AstEffectContext for_effect(this);
1028   if (!CheckStackOverflow()) {
1029     expr->Accept(this);
1030   } else {
1031     ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
1032   }
1033 }
1034
1035
1036 void AstGraphBuilder::VisitForTest(Expression* expr) {
1037   AstTestContext for_condition(this);
1038   if (!CheckStackOverflow()) {
1039     expr->Accept(this);
1040   } else {
1041     ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
1042   }
1043 }
1044
1045
1046 void AstGraphBuilder::Visit(Expression* expr) {
1047   // Reuses enclosing AstContext.
1048   if (!CheckStackOverflow()) {
1049     expr->Accept(this);
1050   } else {
1051     ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
1052   }
1053 }
1054
1055
1056 void AstGraphBuilder::VisitVariableDeclaration(VariableDeclaration* decl) {
1057   Variable* variable = decl->proxy()->var();
1058   VariableMode mode = decl->mode();
1059   bool hole_init = mode == CONST || mode == CONST_LEGACY || mode == LET;
1060   switch (variable->location()) {
1061     case VariableLocation::GLOBAL:
1062     case VariableLocation::UNALLOCATED: {
1063       Handle<Oddball> value = variable->binding_needs_init()
1064                                   ? isolate()->factory()->the_hole_value()
1065                                   : isolate()->factory()->undefined_value();
1066       globals()->push_back(variable->name());
1067       globals()->push_back(value);
1068       break;
1069     }
1070     case VariableLocation::PARAMETER:
1071     case VariableLocation::LOCAL:
1072       if (hole_init) {
1073         Node* value = jsgraph()->TheHoleConstant();
1074         environment()->Bind(variable, value);
1075       }
1076       break;
1077     case VariableLocation::CONTEXT:
1078       if (hole_init) {
1079         Node* value = jsgraph()->TheHoleConstant();
1080         const Operator* op = javascript()->StoreContext(0, variable->index());
1081         NewNode(op, current_context(), value);
1082       }
1083       break;
1084     case VariableLocation::LOOKUP:
1085       UNIMPLEMENTED();
1086   }
1087 }
1088
1089
1090 void AstGraphBuilder::VisitFunctionDeclaration(FunctionDeclaration* decl) {
1091   Variable* variable = decl->proxy()->var();
1092   switch (variable->location()) {
1093     case VariableLocation::GLOBAL:
1094     case VariableLocation::UNALLOCATED: {
1095       Handle<SharedFunctionInfo> function = Compiler::GetSharedFunctionInfo(
1096           decl->fun(), info()->script(), info());
1097       // Check for stack-overflow exception.
1098       if (function.is_null()) return SetStackOverflow();
1099       globals()->push_back(variable->name());
1100       globals()->push_back(function);
1101       break;
1102     }
1103     case VariableLocation::PARAMETER:
1104     case VariableLocation::LOCAL: {
1105       VisitForValue(decl->fun());
1106       Node* value = environment()->Pop();
1107       environment()->Bind(variable, value);
1108       break;
1109     }
1110     case VariableLocation::CONTEXT: {
1111       VisitForValue(decl->fun());
1112       Node* value = environment()->Pop();
1113       const Operator* op = javascript()->StoreContext(0, variable->index());
1114       NewNode(op, current_context(), value);
1115       break;
1116     }
1117     case VariableLocation::LOOKUP:
1118       UNIMPLEMENTED();
1119   }
1120 }
1121
1122
1123 void AstGraphBuilder::VisitImportDeclaration(ImportDeclaration* decl) {
1124   UNREACHABLE();
1125 }
1126
1127
1128 void AstGraphBuilder::VisitExportDeclaration(ExportDeclaration* decl) {
1129   UNREACHABLE();
1130 }
1131
1132
1133 void AstGraphBuilder::VisitBlock(Block* stmt) {
1134   BlockBuilder block(this);
1135   ControlScopeForBreakable scope(this, stmt, &block);
1136   if (stmt->labels() != NULL) block.BeginBlock();
1137   if (stmt->scope() == NULL) {
1138     // Visit statements in the same scope, no declarations.
1139     VisitStatements(stmt->statements());
1140   } else {
1141     // Visit declarations and statements in a block scope.
1142     if (stmt->scope()->ContextLocalCount() > 0) {
1143       Node* context = BuildLocalBlockContext(stmt->scope());
1144       ContextScope scope(this, stmt->scope(), context);
1145       VisitDeclarations(stmt->scope()->declarations());
1146       VisitStatements(stmt->statements());
1147     } else {
1148       VisitDeclarations(stmt->scope()->declarations());
1149       VisitStatements(stmt->statements());
1150     }
1151   }
1152   if (stmt->labels() != NULL) block.EndBlock();
1153 }
1154
1155
1156 void AstGraphBuilder::VisitExpressionStatement(ExpressionStatement* stmt) {
1157   VisitForEffect(stmt->expression());
1158 }
1159
1160
1161 void AstGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) {
1162   // Do nothing.
1163 }
1164
1165
1166 void AstGraphBuilder::VisitIfStatement(IfStatement* stmt) {
1167   IfBuilder compare_if(this);
1168   VisitForTest(stmt->condition());
1169   Node* condition = environment()->Pop();
1170   compare_if.If(condition);
1171   compare_if.Then();
1172   Visit(stmt->then_statement());
1173   compare_if.Else();
1174   Visit(stmt->else_statement());
1175   compare_if.End();
1176 }
1177
1178
1179 void AstGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) {
1180   execution_control()->ContinueTo(stmt->target());
1181 }
1182
1183
1184 void AstGraphBuilder::VisitBreakStatement(BreakStatement* stmt) {
1185   execution_control()->BreakTo(stmt->target());
1186 }
1187
1188
1189 void AstGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) {
1190   VisitForValue(stmt->expression());
1191   Node* result = environment()->Pop();
1192   execution_control()->ReturnValue(result);
1193 }
1194
1195
1196 void AstGraphBuilder::VisitWithStatement(WithStatement* stmt) {
1197   VisitForValue(stmt->expression());
1198   Node* value = environment()->Pop();
1199   const Operator* op = javascript()->CreateWithContext();
1200   Node* context = NewNode(op, value, GetFunctionClosureForContext());
1201   PrepareFrameState(context, stmt->EntryId());
1202   VisitInScope(stmt->statement(), stmt->scope(), context);
1203 }
1204
1205
1206 void AstGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
1207   ZoneList<CaseClause*>* clauses = stmt->cases();
1208   SwitchBuilder compare_switch(this, clauses->length());
1209   ControlScopeForBreakable scope(this, stmt, &compare_switch);
1210   compare_switch.BeginSwitch();
1211   int default_index = -1;
1212
1213   // Keep the switch value on the stack until a case matches.
1214   VisitForValue(stmt->tag());
1215   Node* tag = environment()->Top();
1216
1217   // Iterate over all cases and create nodes for label comparison.
1218   for (int i = 0; i < clauses->length(); i++) {
1219     CaseClause* clause = clauses->at(i);
1220
1221     // The default is not a test, remember index.
1222     if (clause->is_default()) {
1223       default_index = i;
1224       continue;
1225     }
1226
1227     // Create nodes to perform label comparison as if via '==='. The switch
1228     // value is still on the operand stack while the label is evaluated.
1229     VisitForValue(clause->label());
1230     Node* label = environment()->Pop();
1231     const Operator* op = javascript()->StrictEqual();
1232     Node* condition = NewNode(op, tag, label);
1233     compare_switch.BeginLabel(i, condition);
1234
1235     // Discard the switch value at label match.
1236     environment()->Pop();
1237     compare_switch.EndLabel();
1238   }
1239
1240   // Discard the switch value and mark the default case.
1241   environment()->Pop();
1242   if (default_index >= 0) {
1243     compare_switch.DefaultAt(default_index);
1244   }
1245
1246   // Iterate over all cases and create nodes for case bodies.
1247   for (int i = 0; i < clauses->length(); i++) {
1248     CaseClause* clause = clauses->at(i);
1249     compare_switch.BeginCase(i);
1250     VisitStatements(clause->statements());
1251     compare_switch.EndCase();
1252   }
1253
1254   compare_switch.EndSwitch();
1255 }
1256
1257
1258 void AstGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
1259   LoopBuilder while_loop(this);
1260   while_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt));
1261   VisitIterationBody(stmt, &while_loop);
1262   while_loop.EndBody();
1263   VisitForTest(stmt->cond());
1264   Node* condition = environment()->Pop();
1265   while_loop.BreakUnless(condition);
1266   while_loop.EndLoop();
1267 }
1268
1269
1270 void AstGraphBuilder::VisitWhileStatement(WhileStatement* stmt) {
1271   LoopBuilder while_loop(this);
1272   while_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt));
1273   VisitForTest(stmt->cond());
1274   Node* condition = environment()->Pop();
1275   while_loop.BreakUnless(condition);
1276   VisitIterationBody(stmt, &while_loop);
1277   while_loop.EndBody();
1278   while_loop.EndLoop();
1279 }
1280
1281
1282 void AstGraphBuilder::VisitForStatement(ForStatement* stmt) {
1283   LoopBuilder for_loop(this);
1284   VisitIfNotNull(stmt->init());
1285   for_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt));
1286   if (stmt->cond() != NULL) {
1287     VisitForTest(stmt->cond());
1288     Node* condition = environment()->Pop();
1289     for_loop.BreakUnless(condition);
1290   } else {
1291     for_loop.BreakUnless(jsgraph()->TrueConstant());
1292   }
1293   VisitIterationBody(stmt, &for_loop);
1294   for_loop.EndBody();
1295   VisitIfNotNull(stmt->next());
1296   for_loop.EndLoop();
1297 }
1298
1299
1300 void AstGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
1301   VisitForValue(stmt->subject());
1302   Node* object = environment()->Pop();
1303   BlockBuilder for_block(this);
1304   for_block.BeginBlock();
1305   // Check for null or undefined before entering loop.
1306   Node* is_null_cond =
1307       NewNode(javascript()->StrictEqual(), object, jsgraph()->NullConstant());
1308   for_block.BreakWhen(is_null_cond, BranchHint::kFalse);
1309   Node* is_undefined_cond = NewNode(javascript()->StrictEqual(), object,
1310                                     jsgraph()->UndefinedConstant());
1311   for_block.BreakWhen(is_undefined_cond, BranchHint::kFalse);
1312   {
1313     // Convert object to jsobject.
1314     object = BuildToObject(object, stmt->ToObjectId());
1315     environment()->Push(object);
1316
1317     // Prepare for-in cache.
1318     Node* prepare = NewNode(javascript()->ForInPrepare(), object);
1319     PrepareFrameState(prepare, stmt->EnumId(), OutputFrameStateCombine::Push());
1320     Node* cache_type = NewNode(common()->Projection(0), prepare);
1321     Node* cache_array = NewNode(common()->Projection(1), prepare);
1322     Node* cache_length = NewNode(common()->Projection(2), prepare);
1323
1324     // Construct the rest of the environment.
1325     environment()->Push(cache_type);
1326     environment()->Push(cache_array);
1327     environment()->Push(cache_length);
1328     environment()->Push(jsgraph()->ZeroConstant());
1329
1330     // Build the actual loop body.
1331     LoopBuilder for_loop(this);
1332     for_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt));
1333     {
1334       // These stack values are renamed in the case of OSR, so reload them
1335       // from the environment.
1336       Node* index = environment()->Peek(0);
1337       Node* cache_length = environment()->Peek(1);
1338       Node* cache_array = environment()->Peek(2);
1339       Node* cache_type = environment()->Peek(3);
1340       Node* object = environment()->Peek(4);
1341
1342       // Check loop termination condition.
1343       Node* exit_cond = NewNode(javascript()->ForInDone(), index, cache_length);
1344       for_loop.BreakWhen(exit_cond);
1345
1346       // Compute the next enumerated value.
1347       Node* value = NewNode(javascript()->ForInNext(), object, cache_array,
1348                             cache_type, index);
1349       PrepareFrameState(value, stmt->FilterId(),
1350                         OutputFrameStateCombine::Push());
1351       IfBuilder test_value(this);
1352       Node* test_value_cond = NewNode(javascript()->StrictEqual(), value,
1353                                       jsgraph()->UndefinedConstant());
1354       test_value.If(test_value_cond, BranchHint::kFalse);
1355       test_value.Then();
1356       test_value.Else();
1357       {
1358         // Bind value and do loop body.
1359         VectorSlotPair feedback =
1360             CreateVectorSlotPair(stmt->EachFeedbackSlot());
1361         VisitForInAssignment(stmt->each(), value, feedback,
1362                              stmt->AssignmentId());
1363         VisitIterationBody(stmt, &for_loop);
1364       }
1365       test_value.End();
1366       index = environment()->Peek(0);
1367       for_loop.EndBody();
1368
1369       // Increment counter and continue.
1370       index = NewNode(javascript()->ForInStep(), index);
1371       environment()->Poke(0, index);
1372     }
1373     for_loop.EndLoop();
1374     environment()->Drop(5);
1375   }
1376   for_block.EndBlock();
1377 }
1378
1379
1380 void AstGraphBuilder::VisitForOfStatement(ForOfStatement* stmt) {
1381   LoopBuilder for_loop(this);
1382   VisitForEffect(stmt->assign_iterator());
1383   for_loop.BeginLoop(GetVariablesAssignedInLoop(stmt), CheckOsrEntry(stmt));
1384   VisitForEffect(stmt->next_result());
1385   VisitForTest(stmt->result_done());
1386   Node* condition = environment()->Pop();
1387   for_loop.BreakWhen(condition);
1388   VisitForEffect(stmt->assign_each());
1389   VisitIterationBody(stmt, &for_loop);
1390   for_loop.EndBody();
1391   for_loop.EndLoop();
1392 }
1393
1394
1395 void AstGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) {
1396   TryCatchBuilder try_control(this);
1397   ExternalReference message_object =
1398       ExternalReference::address_of_pending_message_obj(isolate());
1399
1400   // Evaluate the try-block inside a control scope. This simulates a handler
1401   // that is intercepting 'throw' control commands.
1402   try_control.BeginTry();
1403   {
1404     ControlScopeForCatch scope(this, &try_control);
1405     STATIC_ASSERT(TryBlockConstant::kElementCount == 1);
1406     environment()->Push(current_context());
1407     Visit(stmt->try_block());
1408     environment()->Pop();
1409   }
1410   try_control.EndTry();
1411
1412   // TODO(mstarzinger): We are only using a runtime call to get a lazy bailout
1413   // point, there is no need to really emit an actual call. Optimize this!
1414   Node* guard = NewNode(javascript()->CallRuntime(Runtime::kMaxSmi, 0));
1415   PrepareFrameState(guard, stmt->HandlerId());
1416
1417   // Clear message object as we enter the catch block.
1418   Node* the_hole = jsgraph()->TheHoleConstant();
1419   BuildStoreExternal(message_object, kMachAnyTagged, the_hole);
1420
1421   // Create a catch scope that binds the exception.
1422   Node* exception = try_control.GetExceptionNode();
1423   Unique<String> name = MakeUnique(stmt->variable()->name());
1424   const Operator* op = javascript()->CreateCatchContext(name);
1425   Node* context = NewNode(op, exception, GetFunctionClosureForContext());
1426
1427   // Evaluate the catch-block.
1428   VisitInScope(stmt->catch_block(), stmt->scope(), context);
1429   try_control.EndCatch();
1430
1431   // TODO(mstarzinger): Remove bailout once everything works.
1432   if (!FLAG_turbo_try_catch) SetStackOverflow();
1433 }
1434
1435
1436 void AstGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
1437   TryFinallyBuilder try_control(this);
1438   ExternalReference message_object =
1439       ExternalReference::address_of_pending_message_obj(isolate());
1440
1441   // We keep a record of all paths that enter the finally-block to be able to
1442   // dispatch to the correct continuation point after the statements in the
1443   // finally-block have been evaluated.
1444   //
1445   // The try-finally construct can enter the finally-block in three ways:
1446   // 1. By exiting the try-block normally, falling through at the end.
1447   // 2. By exiting the try-block with a function-local control flow transfer
1448   //    (i.e. through break/continue/return statements).
1449   // 3. By exiting the try-block with a thrown exception.
1450   Node* fallthrough_result = jsgraph()->TheHoleConstant();
1451   ControlScope::DeferredCommands* commands =
1452       new (zone()) ControlScope::DeferredCommands(this);
1453
1454   // Evaluate the try-block inside a control scope. This simulates a handler
1455   // that is intercepting all control commands.
1456   try_control.BeginTry();
1457   {
1458     ControlScopeForFinally scope(this, commands, &try_control);
1459     STATIC_ASSERT(TryBlockConstant::kElementCount == 1);
1460     environment()->Push(current_context());
1461     Visit(stmt->try_block());
1462     environment()->Pop();
1463   }
1464   try_control.EndTry(commands->GetFallThroughToken(), fallthrough_result);
1465
1466   // TODO(mstarzinger): We are only using a runtime call to get a lazy bailout
1467   // point, there is no need to really emit an actual call. Optimize this!
1468   Node* guard = NewNode(javascript()->CallRuntime(Runtime::kMaxSmi, 0));
1469   PrepareFrameState(guard, stmt->HandlerId());
1470
1471   // The result value semantics depend on how the block was entered:
1472   //  - ReturnStatement: It represents the return value being returned.
1473   //  - ThrowStatement: It represents the exception being thrown.
1474   //  - BreakStatement/ContinueStatement: Filled with the hole.
1475   //  - Falling through into finally-block: Filled with the hole.
1476   Node* result = try_control.GetResultValueNode();
1477   Node* token = try_control.GetDispatchTokenNode();
1478
1479   // The result value, dispatch token and message is expected on the operand
1480   // stack (this is in sync with FullCodeGenerator::EnterFinallyBlock).
1481   Node* message = BuildLoadExternal(message_object, kMachAnyTagged);
1482   environment()->Push(token);  // TODO(mstarzinger): Cook token!
1483   environment()->Push(result);
1484   environment()->Push(message);
1485
1486   // Clear message object as we enter the finally block.
1487   Node* the_hole = jsgraph()->TheHoleConstant();
1488   BuildStoreExternal(message_object, kMachAnyTagged, the_hole);
1489
1490   // Evaluate the finally-block.
1491   Visit(stmt->finally_block());
1492   try_control.EndFinally();
1493
1494   // The result value, dispatch token and message is restored from the operand
1495   // stack (this is in sync with FullCodeGenerator::ExitFinallyBlock).
1496   message = environment()->Pop();
1497   result = environment()->Pop();
1498   token = environment()->Pop();  // TODO(mstarzinger): Uncook token!
1499   BuildStoreExternal(message_object, kMachAnyTagged, message);
1500
1501   // Dynamic dispatch after the finally-block.
1502   commands->ApplyDeferredCommands(token, result);
1503
1504   // TODO(mstarzinger): Remove bailout once everything works.
1505   if (!FLAG_turbo_try_finally) SetStackOverflow();
1506 }
1507
1508
1509 void AstGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
1510   Node* node =
1511       NewNode(javascript()->CallRuntime(Runtime::kHandleDebuggerStatement, 0));
1512   PrepareFrameState(node, stmt->DebugBreakId());
1513   environment()->MarkAllLocalsLive();
1514 }
1515
1516
1517 void AstGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
1518   Node* context = current_context();
1519
1520   // Find or build a shared function info.
1521   Handle<SharedFunctionInfo> shared_info =
1522       Compiler::GetSharedFunctionInfo(expr, info()->script(), info());
1523   CHECK(!shared_info.is_null());  // TODO(mstarzinger): Set stack overflow?
1524
1525   // Create node to instantiate a new closure.
1526   PretenureFlag pretenure = expr->pretenure() ? TENURED : NOT_TENURED;
1527   const Operator* op = javascript()->CreateClosure(shared_info, pretenure);
1528   Node* value = NewNode(op, context);
1529   ast_context()->ProduceValue(value);
1530 }
1531
1532
1533 void AstGraphBuilder::VisitClassLiteral(ClassLiteral* expr) {
1534   if (expr->scope() == NULL) {
1535     // Visit class literal in the same scope, no declarations.
1536     VisitClassLiteralContents(expr);
1537   } else {
1538     // Visit declarations and class literal in a block scope.
1539     if (expr->scope()->ContextLocalCount() > 0) {
1540       Node* context = BuildLocalBlockContext(expr->scope());
1541       ContextScope scope(this, expr->scope(), context);
1542       VisitDeclarations(expr->scope()->declarations());
1543       VisitClassLiteralContents(expr);
1544     } else {
1545       VisitDeclarations(expr->scope()->declarations());
1546       VisitClassLiteralContents(expr);
1547     }
1548   }
1549 }
1550
1551
1552 void AstGraphBuilder::VisitClassLiteralContents(ClassLiteral* expr) {
1553   Node* class_name = expr->raw_name() ? jsgraph()->Constant(expr->name())
1554                                       : jsgraph()->UndefinedConstant();
1555
1556   // The class name is expected on the operand stack.
1557   environment()->Push(class_name);
1558   VisitForValueOrTheHole(expr->extends());
1559   VisitForValue(expr->constructor());
1560
1561   // Create node to instantiate a new class.
1562   Node* constructor = environment()->Pop();
1563   Node* extends = environment()->Pop();
1564   Node* name = environment()->Pop();
1565   Node* script = jsgraph()->Constant(info()->script());
1566   Node* start = jsgraph()->Constant(expr->start_position());
1567   Node* end = jsgraph()->Constant(expr->end_position());
1568   const Operator* opc = javascript()->CallRuntime(
1569       is_strong(language_mode()) ? Runtime::kDefineClassStrong
1570                                  : Runtime::kDefineClass,
1571       6);
1572   Node* literal = NewNode(opc, name, extends, constructor, script, start, end);
1573   PrepareFrameState(literal, expr->CreateLiteralId(),
1574                     OutputFrameStateCombine::Push());
1575
1576   // The prototype is ensured to exist by Runtime_DefineClass. No access check
1577   // is needed here since the constructor is created by the class literal.
1578   Node* proto =
1579       BuildLoadObjectField(literal, JSFunction::kPrototypeOrInitialMapOffset);
1580
1581   // The class literal and the prototype are both expected on the operand stack
1582   // during evaluation of the method values.
1583   environment()->Push(literal);
1584   environment()->Push(proto);
1585
1586   // Create nodes to store method values into the literal.
1587   int store_slot_index = 0;
1588   for (int i = 0; i < expr->properties()->length(); i++) {
1589     ObjectLiteral::Property* property = expr->properties()->at(i);
1590     environment()->Push(property->is_static() ? literal : proto);
1591
1592     VisitForValue(property->key());
1593     Node* name = BuildToName(environment()->Pop(), expr->GetIdForProperty(i));
1594     environment()->Push(name);
1595
1596     // The static prototype property is read only. We handle the non computed
1597     // property name case in the parser. Since this is the only case where we
1598     // need to check for an own read only property we special case this so we do
1599     // not need to do this for every property.
1600     if (property->is_static() && property->is_computed_name()) {
1601       Node* check = BuildThrowIfStaticPrototype(environment()->Pop(),
1602                                                 expr->GetIdForProperty(i));
1603       environment()->Push(check);
1604     }
1605
1606     VisitForValue(property->value());
1607     Node* value = environment()->Pop();
1608     Node* key = environment()->Pop();
1609     Node* receiver = environment()->Pop();
1610     VectorSlotPair feedback = CreateVectorSlotPair(
1611         expr->SlotForHomeObject(property->value(), &store_slot_index));
1612     BuildSetHomeObject(value, receiver, property->value(), feedback);
1613
1614     switch (property->kind()) {
1615       case ObjectLiteral::Property::CONSTANT:
1616       case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1617       case ObjectLiteral::Property::PROTOTYPE:
1618         UNREACHABLE();
1619       case ObjectLiteral::Property::COMPUTED: {
1620         const Operator* op =
1621             javascript()->CallRuntime(Runtime::kDefineClassMethod, 3);
1622         NewNode(op, receiver, key, value);
1623         break;
1624       }
1625       case ObjectLiteral::Property::GETTER: {
1626         Node* attr = jsgraph()->Constant(DONT_ENUM);
1627         const Operator* op = javascript()->CallRuntime(
1628             Runtime::kDefineGetterPropertyUnchecked, 4);
1629         NewNode(op, receiver, key, value, attr);
1630         break;
1631       }
1632       case ObjectLiteral::Property::SETTER: {
1633         Node* attr = jsgraph()->Constant(DONT_ENUM);
1634         const Operator* op = javascript()->CallRuntime(
1635             Runtime::kDefineSetterPropertyUnchecked, 4);
1636         NewNode(op, receiver, key, value, attr);
1637         break;
1638       }
1639     }
1640   }
1641
1642   // Transform both the class literal and the prototype to fast properties.
1643   const Operator* op = javascript()->CallRuntime(Runtime::kToFastProperties, 1);
1644   NewNode(op, environment()->Pop());  // prototype
1645   NewNode(op, environment()->Pop());  // literal
1646   if (is_strong(language_mode())) {
1647     // TODO(conradw): It would be more efficient to define the properties with
1648     // the right attributes the first time round.
1649     // Freeze the prototype.
1650     proto =
1651         NewNode(javascript()->CallRuntime(Runtime::kObjectFreeze, 1), proto);
1652     // Freezing the prototype should never deopt.
1653     PrepareFrameState(proto, BailoutId::None());
1654     // Freeze the constructor.
1655     literal =
1656         NewNode(javascript()->CallRuntime(Runtime::kObjectFreeze, 1), literal);
1657     // Freezing the constructor should never deopt.
1658     PrepareFrameState(literal, BailoutId::None());
1659   }
1660
1661   // Assign to class variable.
1662   if (expr->scope() != NULL) {
1663     DCHECK_NOT_NULL(expr->class_variable_proxy());
1664     Variable* var = expr->class_variable_proxy()->var();
1665     FrameStateBeforeAndAfter states(this, BailoutId::None());
1666     VectorSlotPair feedback =
1667         CreateVectorSlotPair(FLAG_vector_stores && var->IsUnallocated()
1668                                  ? expr->GetNthSlot(store_slot_index++)
1669                                  : FeedbackVectorICSlot::Invalid());
1670     BuildVariableAssignment(var, literal, Token::INIT_CONST, feedback,
1671                             BailoutId::None(), states);
1672   }
1673   ast_context()->ProduceValue(literal);
1674 }
1675
1676
1677 void AstGraphBuilder::VisitNativeFunctionLiteral(NativeFunctionLiteral* expr) {
1678   UNREACHABLE();
1679 }
1680
1681
1682 void AstGraphBuilder::VisitConditional(Conditional* expr) {
1683   IfBuilder compare_if(this);
1684   VisitForTest(expr->condition());
1685   Node* condition = environment()->Pop();
1686   compare_if.If(condition);
1687   compare_if.Then();
1688   Visit(expr->then_expression());
1689   compare_if.Else();
1690   Visit(expr->else_expression());
1691   compare_if.End();
1692   ast_context()->ReplaceValue();
1693 }
1694
1695
1696 void AstGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
1697   VectorSlotPair pair = CreateVectorSlotPair(expr->VariableFeedbackSlot());
1698   FrameStateBeforeAndAfter states(this, BeforeId(expr));
1699   Node* value = BuildVariableLoad(expr->var(), expr->id(), states, pair,
1700                                   ast_context()->GetStateCombine());
1701   ast_context()->ProduceValue(value);
1702 }
1703
1704
1705 void AstGraphBuilder::VisitLiteral(Literal* expr) {
1706   Node* value = jsgraph()->Constant(expr->value());
1707   ast_context()->ProduceValue(value);
1708 }
1709
1710
1711 void AstGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
1712   Node* closure = GetFunctionClosure();
1713
1714   // Create node to materialize a regular expression literal.
1715   Node* literals_array =
1716       BuildLoadObjectField(closure, JSFunction::kLiteralsOffset);
1717   Node* literal_index = jsgraph()->Constant(expr->literal_index());
1718   Node* pattern = jsgraph()->Constant(expr->pattern());
1719   Node* flags = jsgraph()->Constant(expr->flags());
1720   const Operator* op =
1721       javascript()->CallRuntime(Runtime::kMaterializeRegExpLiteral, 4);
1722   Node* literal = NewNode(op, literals_array, literal_index, pattern, flags);
1723   PrepareFrameState(literal, expr->id(), ast_context()->GetStateCombine());
1724   ast_context()->ProduceValue(literal);
1725 }
1726
1727
1728 void AstGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
1729   Node* closure = GetFunctionClosure();
1730
1731   // Create node to deep-copy the literal boilerplate.
1732   Node* literals_array =
1733       BuildLoadObjectField(closure, JSFunction::kLiteralsOffset);
1734   Node* literal_index = jsgraph()->Constant(expr->literal_index());
1735   Node* constants = jsgraph()->Constant(expr->constant_properties());
1736   const Operator* op =
1737       javascript()->CreateLiteralObject(expr->ComputeFlags(true));
1738   Node* literal = NewNode(op, literals_array, literal_index, constants);
1739   PrepareFrameState(literal, expr->CreateLiteralId(),
1740                     OutputFrameStateCombine::Push());
1741
1742   // The object is expected on the operand stack during computation of the
1743   // property values and is the value of the entire expression.
1744   environment()->Push(literal);
1745
1746   // Create nodes to store computed values into the literal.
1747   int property_index = 0;
1748   int store_slot_index = 0;
1749   AccessorTable accessor_table(zone());
1750   for (; property_index < expr->properties()->length(); property_index++) {
1751     ObjectLiteral::Property* property = expr->properties()->at(property_index);
1752     if (property->is_computed_name()) break;
1753     if (property->IsCompileTimeValue()) continue;
1754
1755     Literal* key = property->key()->AsLiteral();
1756     switch (property->kind()) {
1757       case ObjectLiteral::Property::CONSTANT:
1758         UNREACHABLE();
1759       case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1760         DCHECK(!CompileTimeValue::IsCompileTimeValue(property->value()));
1761       // Fall through.
1762       case ObjectLiteral::Property::COMPUTED: {
1763         // It is safe to use [[Put]] here because the boilerplate already
1764         // contains computed properties with an uninitialized value.
1765         if (key->value()->IsInternalizedString()) {
1766           if (property->emit_store()) {
1767             VisitForValue(property->value());
1768             FrameStateBeforeAndAfter states(this, property->value()->id());
1769             Node* value = environment()->Pop();
1770             Handle<Name> name = key->AsPropertyName();
1771             VectorSlotPair feedback =
1772                 FLAG_vector_stores
1773                     ? CreateVectorSlotPair(expr->GetNthSlot(store_slot_index++))
1774                     : VectorSlotPair();
1775             Node* store = BuildNamedStore(literal, name, value, feedback,
1776                                           TypeFeedbackId::None());
1777             states.AddToNode(store, key->id(),
1778                              OutputFrameStateCombine::Ignore());
1779             VectorSlotPair home_feedback = CreateVectorSlotPair(
1780                 expr->SlotForHomeObject(property->value(), &store_slot_index));
1781             BuildSetHomeObject(value, literal, property->value(),
1782                                home_feedback);
1783           } else {
1784             VisitForEffect(property->value());
1785           }
1786           break;
1787         }
1788         environment()->Push(literal);  // Duplicate receiver.
1789         VisitForValue(property->key());
1790         VisitForValue(property->value());
1791         Node* value = environment()->Pop();
1792         Node* key = environment()->Pop();
1793         Node* receiver = environment()->Pop();
1794         if (property->emit_store()) {
1795           Node* language = jsgraph()->Constant(SLOPPY);
1796           const Operator* op =
1797               javascript()->CallRuntime(Runtime::kSetProperty, 4);
1798           Node* set_property = NewNode(op, receiver, key, value, language);
1799           // SetProperty should not lazy deopt on an object literal.
1800           PrepareFrameState(set_property, BailoutId::None());
1801           VectorSlotPair home_feedback = CreateVectorSlotPair(
1802               expr->SlotForHomeObject(property->value(), &store_slot_index));
1803           BuildSetHomeObject(value, receiver, property->value(), home_feedback);
1804         }
1805         break;
1806       }
1807       case ObjectLiteral::Property::PROTOTYPE: {
1808         environment()->Push(literal);  // Duplicate receiver.
1809         VisitForValue(property->value());
1810         Node* value = environment()->Pop();
1811         Node* receiver = environment()->Pop();
1812         DCHECK(property->emit_store());
1813         const Operator* op =
1814             javascript()->CallRuntime(Runtime::kInternalSetPrototype, 2);
1815         Node* set_prototype = NewNode(op, receiver, value);
1816         // SetPrototype should not lazy deopt on an object literal.
1817         PrepareFrameState(set_prototype, BailoutId::None());
1818         break;
1819       }
1820       case ObjectLiteral::Property::GETTER:
1821         if (property->emit_store()) {
1822           accessor_table.lookup(key)->second->getter = property->value();
1823         }
1824         break;
1825       case ObjectLiteral::Property::SETTER:
1826         if (property->emit_store()) {
1827           accessor_table.lookup(key)->second->setter = property->value();
1828         }
1829         break;
1830     }
1831   }
1832
1833   // Create nodes to define accessors, using only a single call to the runtime
1834   // for each pair of corresponding getters and setters.
1835   for (AccessorTable::Iterator it = accessor_table.begin();
1836        it != accessor_table.end(); ++it) {
1837     VisitForValue(it->first);
1838     VisitForValueOrNull(it->second->getter);
1839     VectorSlotPair feedback_getter = CreateVectorSlotPair(
1840         expr->SlotForHomeObject(it->second->getter, &store_slot_index));
1841     BuildSetHomeObject(environment()->Top(), literal, it->second->getter,
1842                        feedback_getter);
1843     VisitForValueOrNull(it->second->setter);
1844     VectorSlotPair feedback_setter = CreateVectorSlotPair(
1845         expr->SlotForHomeObject(it->second->setter, &store_slot_index));
1846     BuildSetHomeObject(environment()->Top(), literal, it->second->setter,
1847                        feedback_setter);
1848     Node* setter = environment()->Pop();
1849     Node* getter = environment()->Pop();
1850     Node* name = environment()->Pop();
1851     Node* attr = jsgraph()->Constant(NONE);
1852     const Operator* op =
1853         javascript()->CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, 5);
1854     Node* call = NewNode(op, literal, name, getter, setter, attr);
1855     // This should not lazy deopt on a new literal.
1856     PrepareFrameState(call, BailoutId::None());
1857   }
1858
1859   // Object literals have two parts. The "static" part on the left contains no
1860   // computed property names, and so we can compute its map ahead of time; see
1861   // Runtime_CreateObjectLiteralBoilerplate. The second "dynamic" part starts
1862   // with the first computed property name and continues with all properties to
1863   // its right. All the code from above initializes the static component of the
1864   // object literal, and arranges for the map of the result to reflect the
1865   // static order in which the keys appear. For the dynamic properties, we
1866   // compile them into a series of "SetOwnProperty" runtime calls. This will
1867   // preserve insertion order.
1868   for (; property_index < expr->properties()->length(); property_index++) {
1869     ObjectLiteral::Property* property = expr->properties()->at(property_index);
1870
1871     if (property->kind() == ObjectLiteral::Property::PROTOTYPE) {
1872       environment()->Push(literal);  // Duplicate receiver.
1873       VisitForValue(property->value());
1874       Node* value = environment()->Pop();
1875       Node* receiver = environment()->Pop();
1876       const Operator* op =
1877           javascript()->CallRuntime(Runtime::kInternalSetPrototype, 2);
1878       Node* call = NewNode(op, receiver, value);
1879       PrepareFrameState(call, BailoutId::None());
1880       continue;
1881     }
1882
1883     environment()->Push(literal);  // Duplicate receiver.
1884     VisitForValue(property->key());
1885     Node* name = BuildToName(environment()->Pop(),
1886                              expr->GetIdForProperty(property_index));
1887     environment()->Push(name);
1888     VisitForValue(property->value());
1889     Node* value = environment()->Pop();
1890     Node* key = environment()->Pop();
1891     Node* receiver = environment()->Pop();
1892     VectorSlotPair feedback = CreateVectorSlotPair(
1893         expr->SlotForHomeObject(property->value(), &store_slot_index));
1894     BuildSetHomeObject(value, receiver, property->value(), feedback);
1895     switch (property->kind()) {
1896       case ObjectLiteral::Property::CONSTANT:
1897       case ObjectLiteral::Property::COMPUTED:
1898       case ObjectLiteral::Property::MATERIALIZED_LITERAL: {
1899         Node* attr = jsgraph()->Constant(NONE);
1900         const Operator* op =
1901             javascript()->CallRuntime(Runtime::kDefineDataPropertyUnchecked, 4);
1902         Node* call = NewNode(op, receiver, key, value, attr);
1903         PrepareFrameState(call, BailoutId::None());
1904         break;
1905       }
1906       case ObjectLiteral::Property::PROTOTYPE:
1907         UNREACHABLE();  // Handled specially above.
1908         break;
1909       case ObjectLiteral::Property::GETTER: {
1910         Node* attr = jsgraph()->Constant(NONE);
1911         const Operator* op = javascript()->CallRuntime(
1912             Runtime::kDefineGetterPropertyUnchecked, 4);
1913         Node* call = NewNode(op, receiver, key, value, attr);
1914         PrepareFrameState(call, BailoutId::None());
1915         break;
1916       }
1917       case ObjectLiteral::Property::SETTER: {
1918         Node* attr = jsgraph()->Constant(NONE);
1919         const Operator* op = javascript()->CallRuntime(
1920             Runtime::kDefineSetterPropertyUnchecked, 4);
1921         Node* call = NewNode(op, receiver, key, value, attr);
1922         PrepareFrameState(call, BailoutId::None());
1923         break;
1924       }
1925     }
1926   }
1927
1928   // Transform literals that contain functions to fast properties.
1929   if (expr->has_function()) {
1930     const Operator* op =
1931         javascript()->CallRuntime(Runtime::kToFastProperties, 1);
1932     NewNode(op, literal);
1933   }
1934
1935   // Verify that compilation exactly consumed the number of store ic slots that
1936   // the ObjectLiteral node had to offer.
1937   DCHECK(!FLAG_vector_stores || store_slot_index == expr->slot_count());
1938
1939   ast_context()->ProduceValue(environment()->Pop());
1940 }
1941
1942
1943 void AstGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
1944   Node* closure = GetFunctionClosure();
1945
1946   // Create node to deep-copy the literal boilerplate.
1947   expr->BuildConstantElements(isolate());
1948   Node* literals_array =
1949       BuildLoadObjectField(closure, JSFunction::kLiteralsOffset);
1950   Node* literal_index = jsgraph()->Constant(expr->literal_index());
1951   Node* constants = jsgraph()->Constant(expr->constant_elements());
1952   const Operator* op =
1953       javascript()->CreateLiteralArray(expr->ComputeFlags(true));
1954   Node* literal = NewNode(op, literals_array, literal_index, constants);
1955   PrepareFrameState(literal, expr->CreateLiteralId(),
1956                     OutputFrameStateCombine::Push());
1957
1958   // The array and the literal index are both expected on the operand stack
1959   // during computation of the element values.
1960   environment()->Push(literal);
1961   environment()->Push(literal_index);
1962
1963   // Create nodes to evaluate all the non-constant subexpressions and to store
1964   // them into the newly cloned array.
1965   int array_index = 0;
1966   for (; array_index < expr->values()->length(); array_index++) {
1967     Expression* subexpr = expr->values()->at(array_index);
1968     if (subexpr->IsSpread()) break;
1969     if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
1970
1971     VisitForValue(subexpr);
1972     {
1973       FrameStateBeforeAndAfter states(this, subexpr->id());
1974       Node* value = environment()->Pop();
1975       Node* index = jsgraph()->Constant(array_index);
1976       // TODO(turbofan): More efficient code could be generated here. Consider
1977       // that the store will be generic because we don't have a feedback vector
1978       // slot.
1979       Node* store = BuildKeyedStore(literal, index, value, VectorSlotPair(),
1980                                     TypeFeedbackId::None());
1981       states.AddToNode(store, expr->GetIdForElement(array_index),
1982                        OutputFrameStateCombine::Ignore());
1983     }
1984   }
1985
1986   // In case the array literal contains spread expressions it has two parts. The
1987   // first part is  the "static" array which has a literal index is handled
1988   // above. The second part is the part after the first spread expression
1989   // (inclusive) and these elements gets appended to the array. Note that the
1990   // number elements an iterable produces is unknown ahead of time.
1991   environment()->Pop();  // Array literal index.
1992   for (; array_index < expr->values()->length(); array_index++) {
1993     Expression* subexpr = expr->values()->at(array_index);
1994     Node* array = environment()->Pop();
1995     Node* result;
1996
1997     if (subexpr->IsSpread()) {
1998       VisitForValue(subexpr->AsSpread()->expression());
1999       Node* iterable = environment()->Pop();
2000       Node* builtins = BuildLoadBuiltinsObject();
2001       Node* function = BuildLoadObjectField(
2002           builtins, JSBuiltinsObject::OffsetOfFunctionWithId(
2003                         Builtins::CONCAT_ITERABLE_TO_ARRAY));
2004       result = NewNode(javascript()->CallFunction(3, NO_CALL_FUNCTION_FLAGS,
2005                                                   language_mode()),
2006                        function, array, iterable);
2007     } else {
2008       VisitForValue(subexpr);
2009       Node* value = environment()->Pop();
2010       const Operator* op =
2011           javascript()->CallRuntime(Runtime::kAppendElement, 2);
2012       result = NewNode(op, array, value);
2013     }
2014
2015     PrepareFrameState(result, expr->GetIdForElement(array_index));
2016     environment()->Push(result);
2017   }
2018
2019   ast_context()->ProduceValue(environment()->Pop());
2020 }
2021
2022
2023 void AstGraphBuilder::VisitForInAssignment(Expression* expr, Node* value,
2024                                            const VectorSlotPair& feedback,
2025                                            BailoutId bailout_id) {
2026   DCHECK(expr->IsValidReferenceExpressionOrThis());
2027
2028   // Left-hand side can only be a property, a global or a variable slot.
2029   Property* property = expr->AsProperty();
2030   LhsKind assign_type = Property::GetAssignType(property);
2031
2032   // Evaluate LHS expression and store the value.
2033   switch (assign_type) {
2034     case VARIABLE: {
2035       Variable* var = expr->AsVariableProxy()->var();
2036       FrameStateBeforeAndAfter states(this, BailoutId::None());
2037       BuildVariableAssignment(var, value, Token::ASSIGN, feedback, bailout_id,
2038                               states);
2039       break;
2040     }
2041     case NAMED_PROPERTY: {
2042       environment()->Push(value);
2043       VisitForValue(property->obj());
2044       FrameStateBeforeAndAfter states(this, property->obj()->id());
2045       Node* object = environment()->Pop();
2046       value = environment()->Pop();
2047       Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2048       Node* store = BuildNamedStore(object, name, value, feedback,
2049                                     TypeFeedbackId::None());
2050       states.AddToNode(store, bailout_id, OutputFrameStateCombine::Ignore());
2051       break;
2052     }
2053     case KEYED_PROPERTY: {
2054       environment()->Push(value);
2055       VisitForValue(property->obj());
2056       VisitForValue(property->key());
2057       FrameStateBeforeAndAfter states(this, property->key()->id());
2058       Node* key = environment()->Pop();
2059       Node* object = environment()->Pop();
2060       value = environment()->Pop();
2061       Node* store =
2062           BuildKeyedStore(object, key, value, feedback, TypeFeedbackId::None());
2063       states.AddToNode(store, bailout_id, OutputFrameStateCombine::Ignore());
2064       break;
2065     }
2066     case NAMED_SUPER_PROPERTY: {
2067       environment()->Push(value);
2068       VisitForValue(property->obj()->AsSuperPropertyReference()->this_var());
2069       VisitForValue(property->obj()->AsSuperPropertyReference()->home_object());
2070       FrameStateBeforeAndAfter states(this, property->obj()->id());
2071       Node* home_object = environment()->Pop();
2072       Node* receiver = environment()->Pop();
2073       value = environment()->Pop();
2074       Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2075       Node* store = BuildNamedSuperStore(receiver, home_object, name, value,
2076                                          TypeFeedbackId::None());
2077       states.AddToNode(store, bailout_id, OutputFrameStateCombine::Ignore());
2078       break;
2079     }
2080     case KEYED_SUPER_PROPERTY: {
2081       environment()->Push(value);
2082       VisitForValue(property->obj()->AsSuperPropertyReference()->this_var());
2083       VisitForValue(property->obj()->AsSuperPropertyReference()->home_object());
2084       VisitForValue(property->key());
2085       FrameStateBeforeAndAfter states(this, property->key()->id());
2086       Node* key = environment()->Pop();
2087       Node* home_object = environment()->Pop();
2088       Node* receiver = environment()->Pop();
2089       value = environment()->Pop();
2090       Node* store = BuildKeyedSuperStore(receiver, home_object, key, value,
2091                                          TypeFeedbackId::None());
2092       states.AddToNode(store, bailout_id, OutputFrameStateCombine::Ignore());
2093       break;
2094     }
2095   }
2096 }
2097
2098
2099 void AstGraphBuilder::VisitAssignment(Assignment* expr) {
2100   DCHECK(expr->target()->IsValidReferenceExpressionOrThis());
2101
2102   // Left-hand side can only be a property, a global or a variable slot.
2103   Property* property = expr->target()->AsProperty();
2104   LhsKind assign_type = Property::GetAssignType(property);
2105   bool needs_frame_state_before = true;
2106
2107   // Evaluate LHS expression.
2108   switch (assign_type) {
2109     case VARIABLE: {
2110       Variable* variable = expr->target()->AsVariableProxy()->var();
2111       if (variable->location() == VariableLocation::PARAMETER ||
2112           variable->location() == VariableLocation::LOCAL ||
2113           variable->location() == VariableLocation::CONTEXT) {
2114         needs_frame_state_before = false;
2115       }
2116       break;
2117     }
2118     case NAMED_PROPERTY:
2119       VisitForValue(property->obj());
2120       break;
2121     case KEYED_PROPERTY:
2122       VisitForValue(property->obj());
2123       VisitForValue(property->key());
2124       break;
2125     case NAMED_SUPER_PROPERTY:
2126       VisitForValue(property->obj()->AsSuperPropertyReference()->this_var());
2127       VisitForValue(property->obj()->AsSuperPropertyReference()->home_object());
2128       break;
2129     case KEYED_SUPER_PROPERTY:
2130       VisitForValue(property->obj()->AsSuperPropertyReference()->this_var());
2131       VisitForValue(property->obj()->AsSuperPropertyReference()->home_object());
2132       VisitForValue(property->key());
2133       break;
2134   }
2135
2136   BailoutId before_store_id = BailoutId::None();
2137   // Evaluate the value and potentially handle compound assignments by loading
2138   // the left-hand side value and performing a binary operation.
2139   if (expr->is_compound()) {
2140     Node* old_value = NULL;
2141     switch (assign_type) {
2142       case VARIABLE: {
2143         VariableProxy* proxy = expr->target()->AsVariableProxy();
2144         VectorSlotPair pair =
2145             CreateVectorSlotPair(proxy->VariableFeedbackSlot());
2146         FrameStateBeforeAndAfter states(this, BeforeId(proxy));
2147         old_value =
2148             BuildVariableLoad(proxy->var(), expr->target()->id(), states, pair,
2149                               OutputFrameStateCombine::Push());
2150         break;
2151       }
2152       case NAMED_PROPERTY: {
2153         Node* object = environment()->Top();
2154         Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2155         VectorSlotPair pair =
2156             CreateVectorSlotPair(property->PropertyFeedbackSlot());
2157         FrameStateBeforeAndAfter states(this, property->obj()->id());
2158         old_value = BuildNamedLoad(object, name, pair);
2159         states.AddToNode(old_value, property->LoadId(),
2160                          OutputFrameStateCombine::Push());
2161         break;
2162       }
2163       case KEYED_PROPERTY: {
2164         Node* key = environment()->Top();
2165         Node* object = environment()->Peek(1);
2166         VectorSlotPair pair =
2167             CreateVectorSlotPair(property->PropertyFeedbackSlot());
2168         FrameStateBeforeAndAfter states(this, property->key()->id());
2169         old_value = BuildKeyedLoad(object, key, pair);
2170         states.AddToNode(old_value, property->LoadId(),
2171                          OutputFrameStateCombine::Push());
2172         break;
2173       }
2174       case NAMED_SUPER_PROPERTY: {
2175         Node* home_object = environment()->Top();
2176         Node* receiver = environment()->Peek(1);
2177         Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2178         VectorSlotPair pair =
2179             CreateVectorSlotPair(property->PropertyFeedbackSlot());
2180         FrameStateBeforeAndAfter states(this, property->obj()->id());
2181         old_value = BuildNamedSuperLoad(receiver, home_object, name, pair);
2182         states.AddToNode(old_value, property->LoadId(),
2183                          OutputFrameStateCombine::Push());
2184         break;
2185       }
2186       case KEYED_SUPER_PROPERTY: {
2187         Node* key = environment()->Top();
2188         Node* home_object = environment()->Peek(1);
2189         Node* receiver = environment()->Peek(2);
2190         VectorSlotPair pair =
2191             CreateVectorSlotPair(property->PropertyFeedbackSlot());
2192         FrameStateBeforeAndAfter states(this, property->key()->id());
2193         old_value = BuildKeyedSuperLoad(receiver, home_object, key, pair);
2194         states.AddToNode(old_value, property->LoadId(),
2195                          OutputFrameStateCombine::Push());
2196         break;
2197       }
2198     }
2199     environment()->Push(old_value);
2200     VisitForValue(expr->value());
2201     Node* value;
2202     {
2203       FrameStateBeforeAndAfter states(this, expr->value()->id());
2204       Node* right = environment()->Pop();
2205       Node* left = environment()->Pop();
2206       value = BuildBinaryOp(left, right, expr->binary_op());
2207       states.AddToNode(value, expr->binary_operation()->id(),
2208                        OutputFrameStateCombine::Push());
2209     }
2210     environment()->Push(value);
2211     if (needs_frame_state_before) {
2212       before_store_id = expr->binary_operation()->id();
2213     }
2214   } else {
2215     VisitForValue(expr->value());
2216     if (needs_frame_state_before) {
2217       before_store_id = expr->value()->id();
2218     }
2219   }
2220
2221   FrameStateBeforeAndAfter store_states(this, before_store_id);
2222   // Store the value.
2223   Node* value = environment()->Pop();
2224   VectorSlotPair feedback = CreateVectorSlotPair(expr->AssignmentSlot());
2225   switch (assign_type) {
2226     case VARIABLE: {
2227       Variable* variable = expr->target()->AsVariableProxy()->var();
2228       BuildVariableAssignment(variable, value, expr->op(), feedback, expr->id(),
2229                               store_states, ast_context()->GetStateCombine());
2230       break;
2231     }
2232     case NAMED_PROPERTY: {
2233       Node* object = environment()->Pop();
2234       Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2235       Node* store = BuildNamedStore(object, name, value, feedback,
2236                                     expr->AssignmentFeedbackId());
2237       store_states.AddToNode(store, expr->id(),
2238                              ast_context()->GetStateCombine());
2239       break;
2240     }
2241     case KEYED_PROPERTY: {
2242       Node* key = environment()->Pop();
2243       Node* object = environment()->Pop();
2244       Node* store = BuildKeyedStore(object, key, value, feedback,
2245                                     expr->AssignmentFeedbackId());
2246       store_states.AddToNode(store, expr->id(),
2247                              ast_context()->GetStateCombine());
2248       break;
2249     }
2250     case NAMED_SUPER_PROPERTY: {
2251       Node* home_object = environment()->Pop();
2252       Node* receiver = environment()->Pop();
2253       Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2254       Node* store = BuildNamedSuperStore(receiver, home_object, name, value,
2255                                          expr->AssignmentFeedbackId());
2256       store_states.AddToNode(store, expr->id(),
2257                              ast_context()->GetStateCombine());
2258       break;
2259     }
2260     case KEYED_SUPER_PROPERTY: {
2261       Node* key = environment()->Pop();
2262       Node* home_object = environment()->Pop();
2263       Node* receiver = environment()->Pop();
2264       Node* store = BuildKeyedSuperStore(receiver, home_object, key, value,
2265                                          expr->AssignmentFeedbackId());
2266       store_states.AddToNode(store, expr->id(),
2267                              ast_context()->GetStateCombine());
2268       break;
2269     }
2270   }
2271
2272   ast_context()->ProduceValue(value);
2273 }
2274
2275
2276 void AstGraphBuilder::VisitYield(Yield* expr) {
2277   // TODO(turbofan): Implement yield here.
2278   SetStackOverflow();
2279   ast_context()->ProduceValue(jsgraph()->UndefinedConstant());
2280 }
2281
2282
2283 void AstGraphBuilder::VisitThrow(Throw* expr) {
2284   VisitForValue(expr->exception());
2285   Node* exception = environment()->Pop();
2286   Node* value = BuildThrowError(exception, expr->id());
2287   ast_context()->ProduceValue(value);
2288 }
2289
2290
2291 void AstGraphBuilder::VisitProperty(Property* expr) {
2292   Node* value = nullptr;
2293   LhsKind property_kind = Property::GetAssignType(expr);
2294   VectorSlotPair pair = CreateVectorSlotPair(expr->PropertyFeedbackSlot());
2295   switch (property_kind) {
2296     case VARIABLE:
2297       UNREACHABLE();
2298       break;
2299     case NAMED_PROPERTY: {
2300       VisitForValue(expr->obj());
2301       FrameStateBeforeAndAfter states(this, expr->obj()->id());
2302       Node* object = environment()->Pop();
2303       Handle<Name> name = expr->key()->AsLiteral()->AsPropertyName();
2304       value = BuildNamedLoad(object, name, pair);
2305       states.AddToNode(value, expr->id(), ast_context()->GetStateCombine());
2306       break;
2307     }
2308     case KEYED_PROPERTY: {
2309       VisitForValue(expr->obj());
2310       VisitForValue(expr->key());
2311       FrameStateBeforeAndAfter states(this, expr->key()->id());
2312       Node* key = environment()->Pop();
2313       Node* object = environment()->Pop();
2314       value = BuildKeyedLoad(object, key, pair);
2315       states.AddToNode(value, expr->id(), ast_context()->GetStateCombine());
2316       break;
2317     }
2318     case NAMED_SUPER_PROPERTY: {
2319       VisitForValue(expr->obj()->AsSuperPropertyReference()->this_var());
2320       VisitForValue(expr->obj()->AsSuperPropertyReference()->home_object());
2321       FrameStateBeforeAndAfter states(this, expr->obj()->id());
2322       Node* home_object = environment()->Pop();
2323       Node* receiver = environment()->Pop();
2324       Handle<Name> name = expr->key()->AsLiteral()->AsPropertyName();
2325       value = BuildNamedSuperLoad(receiver, home_object, name, pair);
2326       states.AddToNode(value, expr->id(), ast_context()->GetStateCombine());
2327       break;
2328     }
2329     case KEYED_SUPER_PROPERTY: {
2330       VisitForValue(expr->obj()->AsSuperPropertyReference()->this_var());
2331       VisitForValue(expr->obj()->AsSuperPropertyReference()->home_object());
2332       VisitForValue(expr->key());
2333       FrameStateBeforeAndAfter states(this, expr->key()->id());
2334       Node* key = environment()->Pop();
2335       Node* home_object = environment()->Pop();
2336       Node* receiver = environment()->Pop();
2337       value = BuildKeyedSuperLoad(receiver, home_object, key, pair);
2338       states.AddToNode(value, expr->id(), ast_context()->GetStateCombine());
2339       break;
2340     }
2341   }
2342   ast_context()->ProduceValue(value);
2343 }
2344
2345
2346 void AstGraphBuilder::VisitCall(Call* expr) {
2347   Expression* callee = expr->expression();
2348   Call::CallType call_type = expr->GetCallType(isolate());
2349
2350   // Prepare the callee and the receiver to the function call. This depends on
2351   // the semantics of the underlying call type.
2352   CallFunctionFlags flags = NO_CALL_FUNCTION_FLAGS;
2353   Node* receiver_value = NULL;
2354   Node* callee_value = NULL;
2355   bool possibly_eval = false;
2356   switch (call_type) {
2357     case Call::GLOBAL_CALL: {
2358       VariableProxy* proxy = callee->AsVariableProxy();
2359       VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot());
2360       FrameStateBeforeAndAfter states(this, BeforeId(proxy));
2361       callee_value =
2362           BuildVariableLoad(proxy->var(), expr->expression()->id(), states,
2363                             pair, OutputFrameStateCombine::Push());
2364       receiver_value = jsgraph()->UndefinedConstant();
2365       break;
2366     }
2367     case Call::LOOKUP_SLOT_CALL: {
2368       Variable* variable = callee->AsVariableProxy()->var();
2369       DCHECK(variable->location() == VariableLocation::LOOKUP);
2370       Node* name = jsgraph()->Constant(variable->name());
2371       const Operator* op =
2372           javascript()->CallRuntime(Runtime::kLoadLookupSlot, 2);
2373       Node* pair = NewNode(op, current_context(), name);
2374       callee_value = NewNode(common()->Projection(0), pair);
2375       receiver_value = NewNode(common()->Projection(1), pair);
2376
2377       PrepareFrameState(pair, expr->LookupId(),
2378                         OutputFrameStateCombine::Push(2));
2379       break;
2380     }
2381     case Call::PROPERTY_CALL: {
2382       Property* property = callee->AsProperty();
2383       VectorSlotPair pair =
2384           CreateVectorSlotPair(property->PropertyFeedbackSlot());
2385       if (!property->IsSuperAccess()) {
2386         VisitForValue(property->obj());
2387         Node* object = environment()->Top();
2388
2389         if (property->key()->IsPropertyName()) {
2390           FrameStateBeforeAndAfter states(this, property->obj()->id());
2391           Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2392           callee_value = BuildNamedLoad(object, name, pair);
2393           states.AddToNode(callee_value, property->LoadId(),
2394                            OutputFrameStateCombine::Push());
2395         } else {
2396           VisitForValue(property->key());
2397           FrameStateBeforeAndAfter states(this, property->key()->id());
2398           Node* key = environment()->Pop();
2399           callee_value = BuildKeyedLoad(object, key, pair);
2400           states.AddToNode(callee_value, property->LoadId(),
2401                            OutputFrameStateCombine::Push());
2402         }
2403         receiver_value = environment()->Pop();
2404         // Note that a PROPERTY_CALL requires the receiver to be wrapped into an
2405         // object for sloppy callees. This could also be modeled explicitly
2406         // here,
2407         // thereby obsoleting the need for a flag to the call operator.
2408         flags = CALL_AS_METHOD;
2409
2410       } else {
2411         VisitForValue(property->obj()->AsSuperPropertyReference()->this_var());
2412         VisitForValue(
2413             property->obj()->AsSuperPropertyReference()->home_object());
2414         Node* home_object = environment()->Pop();
2415         receiver_value = environment()->Pop();
2416         if (property->key()->IsPropertyName()) {
2417           FrameStateBeforeAndAfter states(this, property->obj()->id());
2418           Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2419           callee_value =
2420               BuildNamedSuperLoad(receiver_value, home_object, name, pair);
2421           states.AddToNode(callee_value, property->LoadId(),
2422                            OutputFrameStateCombine::Push());
2423
2424         } else {
2425           VisitForValue(property->key());
2426           FrameStateBeforeAndAfter states(this, property->key()->id());
2427           Node* key = environment()->Pop();
2428           callee_value =
2429               BuildKeyedSuperLoad(receiver_value, home_object, key, pair);
2430           states.AddToNode(callee_value, property->LoadId(),
2431                            OutputFrameStateCombine::Push());
2432         }
2433       }
2434
2435       break;
2436     }
2437     case Call::SUPER_CALL:
2438       return VisitCallSuper(expr);
2439     case Call::POSSIBLY_EVAL_CALL:
2440       possibly_eval = true;
2441       if (callee->AsVariableProxy()->var()->IsLookupSlot()) {
2442         Variable* variable = callee->AsVariableProxy()->var();
2443         Node* name = jsgraph()->Constant(variable->name());
2444         const Operator* op =
2445             javascript()->CallRuntime(Runtime::kLoadLookupSlot, 2);
2446         Node* pair = NewNode(op, current_context(), name);
2447         callee_value = NewNode(common()->Projection(0), pair);
2448         receiver_value = NewNode(common()->Projection(1), pair);
2449         PrepareFrameState(pair, expr->LookupId(),
2450                           OutputFrameStateCombine::Push(2));
2451         break;
2452       }
2453     // Fall through.
2454     case Call::OTHER_CALL:
2455       VisitForValue(callee);
2456       callee_value = environment()->Pop();
2457       receiver_value = jsgraph()->UndefinedConstant();
2458       break;
2459   }
2460
2461   // The callee and the receiver both have to be pushed onto the operand stack
2462   // before arguments are being evaluated.
2463   environment()->Push(callee_value);
2464   environment()->Push(receiver_value);
2465
2466   // Evaluate all arguments to the function call,
2467   ZoneList<Expression*>* args = expr->arguments();
2468   VisitForValues(args);
2469
2470   // Resolve callee and receiver for a potential direct eval call. This block
2471   // will mutate the callee and receiver values pushed onto the environment.
2472   if (possibly_eval && args->length() > 0) {
2473     int arg_count = args->length();
2474
2475     // Extract callee and source string from the environment.
2476     Node* callee = environment()->Peek(arg_count + 1);
2477     Node* source = environment()->Peek(arg_count - 1);
2478
2479     // Create node to ask for help resolving potential eval call. This will
2480     // provide a fully resolved callee and the corresponding receiver.
2481     Node* function = GetFunctionClosure();
2482     Node* language = jsgraph()->Constant(language_mode());
2483     Node* position = jsgraph()->Constant(current_scope()->start_position());
2484     const Operator* op =
2485         javascript()->CallRuntime(Runtime::kResolvePossiblyDirectEval, 5);
2486     Node* new_callee =
2487         NewNode(op, callee, source, function, language, position);
2488     PrepareFrameState(new_callee, expr->EvalId(),
2489                       OutputFrameStateCombine::PokeAt(arg_count + 1));
2490
2491     // Patch callee on the environment.
2492     environment()->Poke(arg_count + 1, new_callee);
2493   }
2494
2495   // Create node to perform the function call.
2496   VectorSlotPair feedback = CreateVectorSlotPair(expr->CallFeedbackICSlot());
2497   const Operator* call = javascript()->CallFunction(args->length() + 2, flags,
2498                                                     language_mode(), feedback);
2499   Node* value = ProcessArguments(call, args->length() + 2);
2500   PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
2501   ast_context()->ProduceValue(value);
2502 }
2503
2504
2505 void AstGraphBuilder::VisitCallSuper(Call* expr) {
2506   SuperCallReference* super = expr->expression()->AsSuperCallReference();
2507   DCHECK_NOT_NULL(super);
2508
2509   // Prepare the callee to the super call. The super constructor is stored as
2510   // the prototype of the constructor we are currently executing.
2511   VisitForValue(super->this_function_var());
2512   Node* this_function = environment()->Pop();
2513   const Operator* op = javascript()->CallRuntime(Runtime::kGetPrototype, 1);
2514   Node* super_function = NewNode(op, this_function);
2515   // TODO(mstarzinger): This probably needs a proper bailout id.
2516   PrepareFrameState(super_function, BailoutId::None());
2517   environment()->Push(super_function);
2518
2519   // Evaluate all arguments to the super call.
2520   ZoneList<Expression*>* args = expr->arguments();
2521   VisitForValues(args);
2522
2523   // Original constructor is loaded from the {new.target} variable.
2524   VisitForValue(super->new_target_var());
2525
2526   // Create node to perform the super call.
2527   const Operator* call = javascript()->CallConstruct(args->length() + 2);
2528   Node* value = ProcessArguments(call, args->length() + 2);
2529   PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
2530   ast_context()->ProduceValue(value);
2531 }
2532
2533
2534 void AstGraphBuilder::VisitCallNew(CallNew* expr) {
2535   VisitForValue(expr->expression());
2536
2537   // Evaluate all arguments to the construct call.
2538   ZoneList<Expression*>* args = expr->arguments();
2539   VisitForValues(args);
2540
2541   // Original constructor is the same as the callee.
2542   environment()->Push(environment()->Peek(args->length()));
2543
2544   // Create node to perform the construct call.
2545   const Operator* call = javascript()->CallConstruct(args->length() + 2);
2546   Node* value = ProcessArguments(call, args->length() + 2);
2547   PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
2548   ast_context()->ProduceValue(value);
2549 }
2550
2551
2552 void AstGraphBuilder::VisitCallJSRuntime(CallRuntime* expr) {
2553   Handle<String> name = expr->name();
2554
2555   // The callee and the receiver both have to be pushed onto the operand stack
2556   // before arguments are being evaluated.
2557   CallFunctionFlags flags = NO_CALL_FUNCTION_FLAGS;
2558   Node* receiver_value = BuildLoadBuiltinsObject();
2559   VectorSlotPair pair = CreateVectorSlotPair(expr->CallRuntimeFeedbackSlot());
2560   // TODO(jarin): bailout ids for runtime calls.
2561   FrameStateBeforeAndAfter states(this, BailoutId::None());
2562   Node* callee_value = BuildNamedLoad(receiver_value, name, pair);
2563   states.AddToNode(callee_value, BailoutId::None(),
2564                    OutputFrameStateCombine::Push());
2565   environment()->Push(callee_value);
2566   environment()->Push(receiver_value);
2567
2568   // Evaluate all arguments to the JS runtime call.
2569   ZoneList<Expression*>* args = expr->arguments();
2570   VisitForValues(args);
2571
2572   // Create node to perform the JS runtime call.
2573   const Operator* call =
2574       javascript()->CallFunction(args->length() + 2, flags, language_mode());
2575   Node* value = ProcessArguments(call, args->length() + 2);
2576   PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
2577   ast_context()->ProduceValue(value);
2578 }
2579
2580
2581 void AstGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
2582   const Runtime::Function* function = expr->function();
2583
2584   // Handle calls to runtime functions implemented in JavaScript separately as
2585   // the call follows JavaScript ABI and the callee is statically unknown.
2586   if (expr->is_jsruntime()) {
2587     DCHECK(function == NULL && expr->name()->length() > 0);
2588     return VisitCallJSRuntime(expr);
2589   }
2590
2591   // TODO(mstarzinger): This bailout is a gigantic hack, the owner is ashamed.
2592   if (function->function_id == Runtime::kInlineGeneratorNext ||
2593       function->function_id == Runtime::kInlineGeneratorThrow) {
2594     ast_context()->ProduceValue(jsgraph()->TheHoleConstant());
2595     return SetStackOverflow();
2596   }
2597
2598   // Evaluate all arguments to the runtime call.
2599   ZoneList<Expression*>* args = expr->arguments();
2600   VisitForValues(args);
2601
2602   // Create node to perform the runtime call.
2603   Runtime::FunctionId functionId = function->function_id;
2604   const Operator* call = javascript()->CallRuntime(functionId, args->length());
2605   FrameStateBeforeAndAfter states(this, expr->CallId());
2606   Node* value = ProcessArguments(call, args->length());
2607   states.AddToNode(value, expr->id(), ast_context()->GetStateCombine());
2608   ast_context()->ProduceValue(value);
2609 }
2610
2611
2612 void AstGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
2613   switch (expr->op()) {
2614     case Token::DELETE:
2615       return VisitDelete(expr);
2616     case Token::VOID:
2617       return VisitVoid(expr);
2618     case Token::TYPEOF:
2619       return VisitTypeof(expr);
2620     case Token::NOT:
2621       return VisitNot(expr);
2622     default:
2623       UNREACHABLE();
2624   }
2625 }
2626
2627
2628 void AstGraphBuilder::VisitCountOperation(CountOperation* expr) {
2629   DCHECK(expr->expression()->IsValidReferenceExpressionOrThis());
2630
2631   // Left-hand side can only be a property, a global or a variable slot.
2632   Property* property = expr->expression()->AsProperty();
2633   LhsKind assign_type = Property::GetAssignType(property);
2634
2635   // Reserve space for result of postfix operation.
2636   bool is_postfix = expr->is_postfix() && !ast_context()->IsEffect();
2637   if (is_postfix) environment()->Push(jsgraph()->UndefinedConstant());
2638
2639   // Evaluate LHS expression and get old value.
2640   Node* old_value = NULL;
2641   int stack_depth = -1;
2642   switch (assign_type) {
2643     case VARIABLE: {
2644       VariableProxy* proxy = expr->expression()->AsVariableProxy();
2645       VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot());
2646       FrameStateBeforeAndAfter states(this, BeforeId(proxy));
2647       old_value =
2648           BuildVariableLoad(proxy->var(), expr->expression()->id(), states,
2649                             pair, OutputFrameStateCombine::Push());
2650       stack_depth = 0;
2651       break;
2652     }
2653     case NAMED_PROPERTY: {
2654       VisitForValue(property->obj());
2655       FrameStateBeforeAndAfter states(this, property->obj()->id());
2656       Node* object = environment()->Top();
2657       Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2658       VectorSlotPair pair =
2659           CreateVectorSlotPair(property->PropertyFeedbackSlot());
2660       old_value = BuildNamedLoad(object, name, pair);
2661       states.AddToNode(old_value, property->LoadId(),
2662                        OutputFrameStateCombine::Push());
2663       stack_depth = 1;
2664       break;
2665     }
2666     case KEYED_PROPERTY: {
2667       VisitForValue(property->obj());
2668       VisitForValue(property->key());
2669       FrameStateBeforeAndAfter states(this, property->key()->id());
2670       Node* key = environment()->Top();
2671       Node* object = environment()->Peek(1);
2672       VectorSlotPair pair =
2673           CreateVectorSlotPair(property->PropertyFeedbackSlot());
2674       old_value = BuildKeyedLoad(object, key, pair);
2675       states.AddToNode(old_value, property->LoadId(),
2676                        OutputFrameStateCombine::Push());
2677       stack_depth = 2;
2678       break;
2679     }
2680     case NAMED_SUPER_PROPERTY: {
2681       VisitForValue(property->obj()->AsSuperPropertyReference()->this_var());
2682       VisitForValue(property->obj()->AsSuperPropertyReference()->home_object());
2683       FrameStateBeforeAndAfter states(this, property->obj()->id());
2684       Node* home_object = environment()->Top();
2685       Node* receiver = environment()->Peek(1);
2686       Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2687       VectorSlotPair pair =
2688           CreateVectorSlotPair(property->PropertyFeedbackSlot());
2689       old_value = BuildNamedSuperLoad(receiver, home_object, name, pair);
2690       states.AddToNode(old_value, property->LoadId(),
2691                        OutputFrameStateCombine::Push());
2692       stack_depth = 2;
2693       break;
2694     }
2695     case KEYED_SUPER_PROPERTY: {
2696       VisitForValue(property->obj()->AsSuperPropertyReference()->this_var());
2697       VisitForValue(property->obj()->AsSuperPropertyReference()->home_object());
2698       VisitForValue(property->key());
2699       FrameStateBeforeAndAfter states(this, property->obj()->id());
2700       Node* key = environment()->Top();
2701       Node* home_object = environment()->Peek(1);
2702       Node* receiver = environment()->Peek(2);
2703       VectorSlotPair pair =
2704           CreateVectorSlotPair(property->PropertyFeedbackSlot());
2705       old_value = BuildKeyedSuperLoad(receiver, home_object, key, pair);
2706       states.AddToNode(old_value, property->LoadId(),
2707                        OutputFrameStateCombine::Push());
2708       stack_depth = 3;
2709       break;
2710     }
2711   }
2712
2713   // Convert old value into a number.
2714   if (!is_strong(language_mode())) {
2715     old_value = NewNode(javascript()->ToNumber(), old_value);
2716     PrepareFrameState(old_value, expr->ToNumberId(),
2717                       OutputFrameStateCombine::Push());
2718   }
2719
2720   // TODO(titzer): combine this framestate with the above?
2721   FrameStateBeforeAndAfter store_states(this, assign_type == KEYED_PROPERTY
2722                                                   ? expr->ToNumberId()
2723                                                   : BailoutId::None());
2724
2725   // Save result for postfix expressions at correct stack depth.
2726   if (is_postfix) environment()->Poke(stack_depth, old_value);
2727
2728   // Create node to perform +1/-1 operation.
2729   Node* value;
2730   {
2731     FrameStateBeforeAndAfter states(this, BailoutId::None());
2732     value =
2733         BuildBinaryOp(old_value, jsgraph()->OneConstant(), expr->binary_op());
2734     // This should never deoptimize outside strong mode because otherwise we
2735     // have converted to number before.
2736     states.AddToNode(value, is_strong(language_mode()) ? expr->ToNumberId()
2737                                                        : BailoutId::None(),
2738                      OutputFrameStateCombine::Ignore());
2739   }
2740
2741   // Store the value.
2742   VectorSlotPair feedback = CreateVectorSlotPair(expr->CountSlot());
2743   switch (assign_type) {
2744     case VARIABLE: {
2745       Variable* variable = expr->expression()->AsVariableProxy()->var();
2746       environment()->Push(value);
2747       BuildVariableAssignment(variable, value, expr->op(), feedback,
2748                               expr->AssignmentId(), store_states);
2749       environment()->Pop();
2750       break;
2751     }
2752     case NAMED_PROPERTY: {
2753       Node* object = environment()->Pop();
2754       Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2755       Node* store = BuildNamedStore(object, name, value, feedback,
2756                                     expr->CountStoreFeedbackId());
2757       environment()->Push(value);
2758       store_states.AddToNode(store, expr->AssignmentId(),
2759                              OutputFrameStateCombine::Ignore());
2760       environment()->Pop();
2761       break;
2762     }
2763     case KEYED_PROPERTY: {
2764       Node* key = environment()->Pop();
2765       Node* object = environment()->Pop();
2766       Node* store = BuildKeyedStore(object, key, value, feedback,
2767                                     expr->CountStoreFeedbackId());
2768       environment()->Push(value);
2769       store_states.AddToNode(store, expr->AssignmentId(),
2770                              OutputFrameStateCombine::Ignore());
2771       environment()->Pop();
2772       break;
2773     }
2774     case NAMED_SUPER_PROPERTY: {
2775       Node* home_object = environment()->Pop();
2776       Node* receiver = environment()->Pop();
2777       Handle<Name> name = property->key()->AsLiteral()->AsPropertyName();
2778       Node* store = BuildNamedSuperStore(receiver, home_object, name, value,
2779                                          expr->CountStoreFeedbackId());
2780       environment()->Push(value);
2781       store_states.AddToNode(store, expr->AssignmentId(),
2782                              OutputFrameStateCombine::Ignore());
2783       environment()->Pop();
2784       break;
2785     }
2786     case KEYED_SUPER_PROPERTY: {
2787       Node* key = environment()->Pop();
2788       Node* home_object = environment()->Pop();
2789       Node* receiver = environment()->Pop();
2790       Node* store = BuildKeyedSuperStore(receiver, home_object, key, value,
2791                                          expr->CountStoreFeedbackId());
2792       environment()->Push(value);
2793       store_states.AddToNode(store, expr->AssignmentId(),
2794                              OutputFrameStateCombine::Ignore());
2795       environment()->Pop();
2796       break;
2797     }
2798   }
2799
2800   // Restore old value for postfix expressions.
2801   if (is_postfix) value = environment()->Pop();
2802
2803   ast_context()->ProduceValue(value);
2804 }
2805
2806
2807 void AstGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) {
2808   switch (expr->op()) {
2809     case Token::COMMA:
2810       return VisitComma(expr);
2811     case Token::OR:
2812     case Token::AND:
2813       return VisitLogicalExpression(expr);
2814     default: {
2815       VisitForValue(expr->left());
2816       VisitForValue(expr->right());
2817       FrameStateBeforeAndAfter states(this, expr->right()->id());
2818       Node* right = environment()->Pop();
2819       Node* left = environment()->Pop();
2820       Node* value = BuildBinaryOp(left, right, expr->op());
2821       states.AddToNode(value, expr->id(), ast_context()->GetStateCombine());
2822       ast_context()->ProduceValue(value);
2823     }
2824   }
2825 }
2826
2827
2828 void AstGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
2829   const Operator* op;
2830   switch (expr->op()) {
2831     case Token::EQ:
2832       op = javascript()->Equal();
2833       break;
2834     case Token::NE:
2835       op = javascript()->NotEqual();
2836       break;
2837     case Token::EQ_STRICT:
2838       op = javascript()->StrictEqual();
2839       break;
2840     case Token::NE_STRICT:
2841       op = javascript()->StrictNotEqual();
2842       break;
2843     case Token::LT:
2844       op = javascript()->LessThan(language_mode());
2845       break;
2846     case Token::GT:
2847       op = javascript()->GreaterThan(language_mode());
2848       break;
2849     case Token::LTE:
2850       op = javascript()->LessThanOrEqual(language_mode());
2851       break;
2852     case Token::GTE:
2853       op = javascript()->GreaterThanOrEqual(language_mode());
2854       break;
2855     case Token::INSTANCEOF:
2856       op = javascript()->InstanceOf();
2857       break;
2858     case Token::IN:
2859       op = javascript()->HasProperty();
2860       break;
2861     default:
2862       op = NULL;
2863       UNREACHABLE();
2864   }
2865   VisitForValue(expr->left());
2866   VisitForValue(expr->right());
2867   FrameStateBeforeAndAfter states(this, expr->right()->id());
2868   Node* right = environment()->Pop();
2869   Node* left = environment()->Pop();
2870   Node* value = NewNode(op, left, right);
2871   states.AddToNode(value, expr->id(), ast_context()->GetStateCombine());
2872   ast_context()->ProduceValue(value);
2873 }
2874
2875
2876 void AstGraphBuilder::VisitSpread(Spread* expr) {
2877   // Handled entirely by the parser itself.
2878   UNREACHABLE();
2879 }
2880
2881
2882 void AstGraphBuilder::VisitThisFunction(ThisFunction* expr) {
2883   Node* value = GetFunctionClosure();
2884   ast_context()->ProduceValue(value);
2885 }
2886
2887
2888 void AstGraphBuilder::VisitSuperPropertyReference(
2889     SuperPropertyReference* expr) {
2890   Node* value = BuildThrowUnsupportedSuperError(expr->id());
2891   ast_context()->ProduceValue(value);
2892 }
2893
2894
2895 void AstGraphBuilder::VisitSuperCallReference(SuperCallReference* expr) {
2896   // Handled by VisitCall
2897   UNREACHABLE();
2898 }
2899
2900
2901 void AstGraphBuilder::VisitCaseClause(CaseClause* expr) {
2902   // Handled entirely in VisitSwitch.
2903   UNREACHABLE();
2904 }
2905
2906
2907 void AstGraphBuilder::VisitDeclarations(ZoneList<Declaration*>* declarations) {
2908   DCHECK(globals()->empty());
2909   AstVisitor::VisitDeclarations(declarations);
2910   if (globals()->empty()) return;
2911   int array_index = 0;
2912   Handle<FixedArray> data = isolate()->factory()->NewFixedArray(
2913       static_cast<int>(globals()->size()), TENURED);
2914   for (Handle<Object> obj : *globals()) data->set(array_index++, *obj);
2915   int encoded_flags = DeclareGlobalsEvalFlag::encode(info()->is_eval()) |
2916                       DeclareGlobalsNativeFlag::encode(info()->is_native()) |
2917                       DeclareGlobalsLanguageMode::encode(language_mode());
2918   Node* flags = jsgraph()->Constant(encoded_flags);
2919   Node* pairs = jsgraph()->Constant(data);
2920   const Operator* op = javascript()->CallRuntime(Runtime::kDeclareGlobals, 3);
2921   Node* call = NewNode(op, current_context(), pairs, flags);
2922   PrepareFrameState(call, BailoutId::Declarations());
2923   globals()->clear();
2924 }
2925
2926
2927 void AstGraphBuilder::VisitIfNotNull(Statement* stmt) {
2928   if (stmt == NULL) return;
2929   Visit(stmt);
2930 }
2931
2932
2933 void AstGraphBuilder::VisitInScope(Statement* stmt, Scope* s, Node* context) {
2934   ContextScope scope(this, s, context);
2935   DCHECK(s->declarations()->is_empty());
2936   Visit(stmt);
2937 }
2938
2939
2940 void AstGraphBuilder::VisitIterationBody(IterationStatement* stmt,
2941                                          LoopBuilder* loop) {
2942   ControlScopeForIteration scope(this, stmt, loop);
2943   // TODO(mstarzinger): For now we only allow to interrupt non-asm.js code,
2944   // which is a gigantic hack and should be extended to all code at some point.
2945   if (!info()->shared_info()->asm_function()) {
2946     Node* node = NewNode(javascript()->StackCheck());
2947     PrepareFrameState(node, stmt->StackCheckId());
2948   }
2949   Visit(stmt->body());
2950 }
2951
2952
2953 void AstGraphBuilder::VisitDelete(UnaryOperation* expr) {
2954   Node* value;
2955   if (expr->expression()->IsVariableProxy()) {
2956     // Delete of an unqualified identifier is only allowed in classic mode but
2957     // deleting "this" is allowed in all language modes.
2958     Variable* variable = expr->expression()->AsVariableProxy()->var();
2959     // Delete of an unqualified identifier is disallowed in strict mode but
2960     // "delete this" is allowed.
2961     DCHECK(is_sloppy(language_mode()) || variable->HasThisName(isolate()));
2962     value = BuildVariableDelete(variable, expr->id(),
2963                                 ast_context()->GetStateCombine());
2964   } else if (expr->expression()->IsProperty()) {
2965     Property* property = expr->expression()->AsProperty();
2966     VisitForValue(property->obj());
2967     VisitForValue(property->key());
2968     Node* key = environment()->Pop();
2969     Node* object = environment()->Pop();
2970     value = NewNode(javascript()->DeleteProperty(language_mode()), object, key);
2971     PrepareFrameState(value, expr->id(), ast_context()->GetStateCombine());
2972   } else {
2973     VisitForEffect(expr->expression());
2974     value = jsgraph()->TrueConstant();
2975   }
2976   ast_context()->ProduceValue(value);
2977 }
2978
2979
2980 void AstGraphBuilder::VisitVoid(UnaryOperation* expr) {
2981   VisitForEffect(expr->expression());
2982   Node* value = jsgraph()->UndefinedConstant();
2983   ast_context()->ProduceValue(value);
2984 }
2985
2986
2987 void AstGraphBuilder::VisitTypeof(UnaryOperation* expr) {
2988   Node* operand;
2989   if (expr->expression()->IsVariableProxy()) {
2990     // Typeof does not throw a reference error on global variables, hence we
2991     // perform a non-contextual load in case the operand is a variable proxy.
2992     VariableProxy* proxy = expr->expression()->AsVariableProxy();
2993     VectorSlotPair pair = CreateVectorSlotPair(proxy->VariableFeedbackSlot());
2994     FrameStateBeforeAndAfter states(this, BeforeId(proxy));
2995     operand =
2996         BuildVariableLoad(proxy->var(), expr->expression()->id(), states, pair,
2997                           OutputFrameStateCombine::Push(), INSIDE_TYPEOF);
2998   } else {
2999     VisitForValue(expr->expression());
3000     operand = environment()->Pop();
3001   }
3002   Node* value = NewNode(javascript()->TypeOf(), operand);
3003   ast_context()->ProduceValue(value);
3004 }
3005
3006
3007 void AstGraphBuilder::VisitNot(UnaryOperation* expr) {
3008   VisitForValue(expr->expression());
3009   Node* operand = environment()->Pop();
3010   // TODO(mstarzinger): Possible optimization when we are in effect context.
3011   Node* value = NewNode(javascript()->UnaryNot(), operand);
3012   ast_context()->ProduceValue(value);
3013 }
3014
3015
3016 void AstGraphBuilder::VisitComma(BinaryOperation* expr) {
3017   VisitForEffect(expr->left());
3018   Visit(expr->right());
3019   ast_context()->ReplaceValue();
3020 }
3021
3022
3023 void AstGraphBuilder::VisitLogicalExpression(BinaryOperation* expr) {
3024   bool is_logical_and = expr->op() == Token::AND;
3025   IfBuilder compare_if(this);
3026   VisitForValue(expr->left());
3027   Node* condition = environment()->Top();
3028   compare_if.If(BuildToBoolean(condition));
3029   compare_if.Then();
3030   if (is_logical_and) {
3031     environment()->Pop();
3032     Visit(expr->right());
3033   } else if (ast_context()->IsEffect()) {
3034     environment()->Pop();
3035   } else if (ast_context()->IsTest()) {
3036     environment()->Poke(0, jsgraph()->TrueConstant());
3037   }
3038   compare_if.Else();
3039   if (!is_logical_and) {
3040     environment()->Pop();
3041     Visit(expr->right());
3042   } else if (ast_context()->IsEffect()) {
3043     environment()->Pop();
3044   } else if (ast_context()->IsTest()) {
3045     environment()->Poke(0, jsgraph()->FalseConstant());
3046   }
3047   compare_if.End();
3048   ast_context()->ReplaceValue();
3049 }
3050
3051
3052 LanguageMode AstGraphBuilder::language_mode() const {
3053   return info()->language_mode();
3054 }
3055
3056
3057 VectorSlotPair AstGraphBuilder::CreateVectorSlotPair(
3058     FeedbackVectorICSlot slot) const {
3059   return VectorSlotPair(handle(info()->shared_info()->feedback_vector()), slot);
3060 }
3061
3062
3063 uint32_t AstGraphBuilder::ComputeBitsetForDynamicGlobal(Variable* variable) {
3064   DCHECK_EQ(DYNAMIC_GLOBAL, variable->mode());
3065   bool found_eval_scope = false;
3066   uint32_t check_depths = 0;
3067   for (Scope* s = current_scope(); s != nullptr; s = s->outer_scope()) {
3068     if (s->num_heap_slots() <= 0) continue;
3069     // TODO(mstarzinger): If we have reached an eval scope, we check all
3070     // extensions from this point. Replicated from full-codegen, figure out
3071     // whether this is still needed. If not, drop {found_eval_scope} below.
3072     if (s->is_eval_scope()) found_eval_scope = true;
3073     if (!s->calls_sloppy_eval() && !found_eval_scope) continue;
3074     int depth = current_scope()->ContextChainLength(s);
3075     if (depth > DynamicGlobalAccess::kMaxCheckDepth) {
3076       return DynamicGlobalAccess::kFullCheckRequired;
3077     }
3078     check_depths |= 1 << depth;
3079   }
3080   return check_depths;
3081 }
3082
3083
3084 uint32_t AstGraphBuilder::ComputeBitsetForDynamicContext(Variable* variable) {
3085   DCHECK_EQ(DYNAMIC_LOCAL, variable->mode());
3086   uint32_t check_depths = 0;
3087   for (Scope* s = current_scope(); s != nullptr; s = s->outer_scope()) {
3088     if (s->num_heap_slots() <= 0) continue;
3089     if (!s->calls_sloppy_eval() && s != variable->scope()) continue;
3090     int depth = current_scope()->ContextChainLength(s);
3091     if (depth > DynamicContextAccess::kMaxCheckDepth) {
3092       return DynamicContextAccess::kFullCheckRequired;
3093     }
3094     check_depths |= 1 << depth;
3095     if (s == variable->scope()) break;
3096   }
3097   return check_depths;
3098 }
3099
3100
3101 Node* AstGraphBuilder::ProcessArguments(const Operator* op, int arity) {
3102   DCHECK(environment()->stack_height() >= arity);
3103   Node** all = info()->zone()->NewArray<Node*>(arity);
3104   for (int i = arity - 1; i >= 0; --i) {
3105     all[i] = environment()->Pop();
3106   }
3107   Node* value = NewNode(op, arity, all);
3108   return value;
3109 }
3110
3111
3112 Node* AstGraphBuilder::BuildPatchReceiverToGlobalProxy(Node* receiver) {
3113   // Sloppy mode functions and builtins need to replace the receiver with the
3114   // global proxy when called as functions (without an explicit receiver
3115   // object). Otherwise there is nothing left to do here.
3116   if (is_strict(language_mode()) || info()->is_native()) return receiver;
3117
3118   // There is no need to perform patching if the receiver will never be used.
3119   if (!info()->MayUseThis()) return receiver;
3120
3121   IfBuilder receiver_check(this);
3122   Node* undefined = jsgraph()->UndefinedConstant();
3123   Node* check = NewNode(javascript()->StrictEqual(), receiver, undefined);
3124   receiver_check.If(check);
3125   receiver_check.Then();
3126   Node* proxy = BuildLoadGlobalProxy();
3127   environment()->Push(proxy);
3128   receiver_check.Else();
3129   environment()->Push(receiver);
3130   receiver_check.End();
3131   return environment()->Pop();
3132 }
3133
3134
3135 Node* AstGraphBuilder::BuildLocalFunctionContext(Node* context) {
3136   Scope* scope = info()->scope();
3137   Node* closure = GetFunctionClosure();
3138
3139   // Allocate a new local context.
3140   Node* local_context =
3141       scope->is_script_scope()
3142           ? BuildLocalScriptContext(scope)
3143           : NewNode(javascript()->CreateFunctionContext(), closure);
3144
3145   if (scope->has_this_declaration() && scope->receiver()->IsContextSlot()) {
3146     Node* receiver = environment()->RawParameterLookup(0);
3147     // Context variable (at bottom of the context chain).
3148     Variable* variable = scope->receiver();
3149     DCHECK_EQ(0, scope->ContextChainLength(variable->scope()));
3150     const Operator* op = javascript()->StoreContext(0, variable->index());
3151     NewNode(op, local_context, receiver);
3152   }
3153
3154   // Copy parameters into context if necessary.
3155   int num_parameters = scope->num_parameters();
3156   for (int i = 0; i < num_parameters; i++) {
3157     Variable* variable = scope->parameter(i);
3158     if (!variable->IsContextSlot()) continue;
3159     Node* parameter = environment()->RawParameterLookup(i + 1);
3160     // Context variable (at bottom of the context chain).
3161     DCHECK_EQ(0, scope->ContextChainLength(variable->scope()));
3162     const Operator* op = javascript()->StoreContext(0, variable->index());
3163     NewNode(op, local_context, parameter);
3164   }
3165
3166   return local_context;
3167 }
3168
3169
3170 Node* AstGraphBuilder::BuildLocalScriptContext(Scope* scope) {
3171   DCHECK(scope->is_script_scope());
3172
3173   // Allocate a new local context.
3174   const Operator* op = javascript()->CreateScriptContext();
3175   Node* scope_info = jsgraph()->Constant(scope->GetScopeInfo(isolate()));
3176   Node* local_context = NewNode(op, GetFunctionClosure(), scope_info);
3177   PrepareFrameState(local_context, BailoutId::FunctionEntry());
3178
3179   return local_context;
3180 }
3181
3182
3183 Node* AstGraphBuilder::BuildLocalBlockContext(Scope* scope) {
3184   DCHECK(scope->is_block_scope());
3185
3186   // Allocate a new local context.
3187   const Operator* op = javascript()->CreateBlockContext();
3188   Node* scope_info = jsgraph()->Constant(scope->GetScopeInfo(isolate()));
3189   Node* local_context = NewNode(op, scope_info, GetFunctionClosureForContext());
3190
3191   return local_context;
3192 }
3193
3194
3195 Node* AstGraphBuilder::BuildArgumentsObject(Variable* arguments) {
3196   if (arguments == NULL) return NULL;
3197
3198   // Allocate and initialize a new arguments object.
3199   Node* callee = GetFunctionClosure();
3200   const Operator* op = javascript()->CallRuntime(Runtime::kNewArguments, 1);
3201   Node* object = NewNode(op, callee);
3202
3203   // Assign the object to the arguments variable.
3204   DCHECK(arguments->IsContextSlot() || arguments->IsStackAllocated());
3205   // This should never lazy deopt, so it is fine to send invalid bailout id.
3206   FrameStateBeforeAndAfter states(this, BailoutId::None());
3207   BuildVariableAssignment(arguments, object, Token::ASSIGN, VectorSlotPair(),
3208                           BailoutId::None(), states);
3209   return object;
3210 }
3211
3212
3213 Node* AstGraphBuilder::BuildRestArgumentsArray(Variable* rest, int index) {
3214   if (rest == NULL) return NULL;
3215
3216   DCHECK(index >= 0);
3217   const Operator* op = javascript()->CallRuntime(Runtime::kNewRestParamSlow, 2);
3218   Node* object = NewNode(op, jsgraph()->SmiConstant(index),
3219                          jsgraph()->SmiConstant(language_mode()));
3220
3221   // Assign the object to the rest parameter variable.
3222   DCHECK(rest->IsContextSlot() || rest->IsStackAllocated());
3223   // This should never lazy deopt, so it is fine to send invalid bailout id.
3224   FrameStateBeforeAndAfter states(this, BailoutId::None());
3225   BuildVariableAssignment(rest, object, Token::ASSIGN, VectorSlotPair(),
3226                           BailoutId::None(), states);
3227   return object;
3228 }
3229
3230
3231 Node* AstGraphBuilder::BuildThisFunctionVariable(Variable* this_function_var) {
3232   if (this_function_var == nullptr) return nullptr;
3233
3234   // Retrieve the closure we were called with.
3235   Node* this_function = GetFunctionClosure();
3236
3237   // Assign the object to the {.this_function} variable.
3238   FrameStateBeforeAndAfter states(this, BailoutId::None());
3239   BuildVariableAssignment(this_function_var, this_function, Token::INIT_CONST,
3240                           VectorSlotPair(), BailoutId::None(), states);
3241   return this_function;
3242 }
3243
3244
3245 Node* AstGraphBuilder::BuildNewTargetVariable(Variable* new_target_var) {
3246   if (new_target_var == nullptr) return nullptr;
3247
3248   // Retrieve the original constructor in case we are called as a constructor.
3249   const Operator* op =
3250       javascript()->CallRuntime(Runtime::kGetOriginalConstructor, 0);
3251   Node* object = NewNode(op);
3252
3253   // Assign the object to the {new.target} variable.
3254   FrameStateBeforeAndAfter states(this, BailoutId::None());
3255   BuildVariableAssignment(new_target_var, object, Token::INIT_CONST,
3256                           VectorSlotPair(), BailoutId::None(), states);
3257   return object;
3258 }
3259
3260
3261 Node* AstGraphBuilder::BuildHoleCheckSilent(Node* value, Node* for_hole,
3262                                             Node* not_hole) {
3263   Node* the_hole = jsgraph()->TheHoleConstant();
3264   Node* check = NewNode(javascript()->StrictEqual(), value, the_hole);
3265   return NewNode(common()->Select(kMachAnyTagged, BranchHint::kFalse), check,
3266                  for_hole, not_hole);
3267 }
3268
3269
3270 Node* AstGraphBuilder::BuildHoleCheckThenThrow(Node* value, Variable* variable,
3271                                                Node* not_hole,
3272                                                BailoutId bailout_id) {
3273   IfBuilder hole_check(this);
3274   Node* the_hole = jsgraph()->TheHoleConstant();
3275   Node* check = NewNode(javascript()->StrictEqual(), value, the_hole);
3276   hole_check.If(check);
3277   hole_check.Then();
3278   Node* error = BuildThrowReferenceError(variable, bailout_id);
3279   environment()->Push(error);
3280   hole_check.Else();
3281   environment()->Push(not_hole);
3282   hole_check.End();
3283   return environment()->Pop();
3284 }
3285
3286
3287 Node* AstGraphBuilder::BuildHoleCheckElseThrow(Node* value, Variable* variable,
3288                                                Node* for_hole,
3289                                                BailoutId bailout_id) {
3290   IfBuilder hole_check(this);
3291   Node* the_hole = jsgraph()->TheHoleConstant();
3292   Node* check = NewNode(javascript()->StrictEqual(), value, the_hole);
3293   hole_check.If(check);
3294   hole_check.Then();
3295   environment()->Push(for_hole);
3296   hole_check.Else();
3297   Node* error = BuildThrowReferenceError(variable, bailout_id);
3298   environment()->Push(error);
3299   hole_check.End();
3300   return environment()->Pop();
3301 }
3302
3303
3304 Node* AstGraphBuilder::BuildThrowIfStaticPrototype(Node* name,
3305                                                    BailoutId bailout_id) {
3306   IfBuilder prototype_check(this);
3307   Node* prototype_string =
3308       jsgraph()->Constant(isolate()->factory()->prototype_string());
3309   Node* check = NewNode(javascript()->StrictEqual(), name, prototype_string);
3310   prototype_check.If(check);
3311   prototype_check.Then();
3312   Node* error = BuildThrowStaticPrototypeError(bailout_id);
3313   environment()->Push(error);
3314   prototype_check.Else();
3315   environment()->Push(name);
3316   prototype_check.End();
3317   return environment()->Pop();
3318 }
3319
3320
3321 Node* AstGraphBuilder::BuildVariableLoad(Variable* variable,
3322                                          BailoutId bailout_id,
3323                                          FrameStateBeforeAndAfter& states,
3324                                          const VectorSlotPair& feedback,
3325                                          OutputFrameStateCombine combine,
3326                                          TypeofMode typeof_mode) {
3327   Node* the_hole = jsgraph()->TheHoleConstant();
3328   VariableMode mode = variable->mode();
3329   switch (variable->location()) {
3330     case VariableLocation::GLOBAL:
3331     case VariableLocation::UNALLOCATED: {
3332       // Global var, const, or let variable.
3333       Node* script_context = current_context();
3334       int slot_index = -1;
3335       if (variable->index() > 0) {
3336         DCHECK(variable->IsStaticGlobalObjectProperty());
3337         slot_index = variable->index();
3338         int depth = current_scope()->ContextChainLength(variable->scope());
3339         if (depth > 0) {
3340           const Operator* op = javascript()->LoadContext(
3341               depth - 1, Context::PREVIOUS_INDEX, true);
3342           script_context = NewNode(op, current_context());
3343         }
3344       }
3345       Node* global = BuildLoadGlobalObject();
3346       Handle<Name> name = variable->name();
3347       Node* value = BuildGlobalLoad(script_context, global, name, feedback,
3348                                     typeof_mode, slot_index);
3349       states.AddToNode(value, bailout_id, combine);
3350       return value;
3351     }
3352     case VariableLocation::PARAMETER:
3353     case VariableLocation::LOCAL: {
3354       // Local var, const, or let variable.
3355       Node* value = environment()->Lookup(variable);
3356       if (mode == CONST_LEGACY) {
3357         // Perform check for uninitialized legacy const variables.
3358         if (value->op() == the_hole->op()) {
3359           value = jsgraph()->UndefinedConstant();
3360         } else if (value->opcode() == IrOpcode::kPhi) {
3361           Node* undefined = jsgraph()->UndefinedConstant();
3362           value = BuildHoleCheckSilent(value, undefined, value);
3363         }
3364       } else if (mode == LET || mode == CONST) {
3365         // Perform check for uninitialized let/const variables.
3366         if (value->op() == the_hole->op()) {
3367           value = BuildThrowReferenceError(variable, bailout_id);
3368         } else if (value->opcode() == IrOpcode::kPhi) {
3369           value = BuildHoleCheckThenThrow(value, variable, value, bailout_id);
3370         }
3371       }
3372       return value;
3373     }
3374     case VariableLocation::CONTEXT: {
3375       // Context variable (potentially up the context chain).
3376       int depth = current_scope()->ContextChainLength(variable->scope());
3377       bool immutable = variable->maybe_assigned() == kNotAssigned;
3378       const Operator* op =
3379           javascript()->LoadContext(depth, variable->index(), immutable);
3380       Node* value = NewNode(op, current_context());
3381       // TODO(titzer): initialization checks are redundant for already
3382       // initialized immutable context loads, but only specialization knows.
3383       // Maybe specializer should be a parameter to the graph builder?
3384       if (mode == CONST_LEGACY) {
3385         // Perform check for uninitialized legacy const variables.
3386         Node* undefined = jsgraph()->UndefinedConstant();
3387         value = BuildHoleCheckSilent(value, undefined, value);
3388       } else if (mode == LET || mode == CONST) {
3389         // Perform check for uninitialized let/const variables.
3390         value = BuildHoleCheckThenThrow(value, variable, value, bailout_id);
3391       }
3392       return value;
3393     }
3394     case VariableLocation::LOOKUP: {
3395       // Dynamic lookup of context variable (anywhere in the chain).
3396       Node* value = jsgraph()->TheHoleConstant();
3397       Handle<String> name = variable->name();
3398       if (mode == DYNAMIC_GLOBAL) {
3399         uint32_t check_bitset = ComputeBitsetForDynamicGlobal(variable);
3400         const Operator* op = javascript()->LoadDynamicGlobal(
3401             name, check_bitset, feedback, typeof_mode);
3402         value = NewNode(op, BuildLoadFeedbackVector(), current_context());
3403         states.AddToNode(value, bailout_id, combine);
3404       } else if (mode == DYNAMIC_LOCAL) {
3405         Variable* local = variable->local_if_not_shadowed();
3406         DCHECK(local->location() ==
3407                VariableLocation::CONTEXT);  // Must be context.
3408         int depth = current_scope()->ContextChainLength(local->scope());
3409         uint32_t check_bitset = ComputeBitsetForDynamicContext(variable);
3410         const Operator* op = javascript()->LoadDynamicContext(
3411             name, check_bitset, depth, local->index());
3412         value = NewNode(op, current_context());
3413         PrepareFrameState(value, bailout_id, combine);
3414         VariableMode local_mode = local->mode();
3415         if (local_mode == CONST_LEGACY) {
3416           // Perform check for uninitialized legacy const variables.
3417           Node* undefined = jsgraph()->UndefinedConstant();
3418           value = BuildHoleCheckSilent(value, undefined, value);
3419         } else if (local_mode == LET || local_mode == CONST) {
3420           // Perform check for uninitialized let/const variables.
3421           value = BuildHoleCheckThenThrow(value, local, value, bailout_id);
3422         }
3423       } else if (mode == DYNAMIC) {
3424         uint32_t check_bitset = DynamicGlobalAccess::kFullCheckRequired;
3425         const Operator* op = javascript()->LoadDynamicGlobal(
3426             name, check_bitset, feedback, typeof_mode);
3427         value = NewNode(op, BuildLoadFeedbackVector(), current_context());
3428         states.AddToNode(value, bailout_id, combine);
3429       }
3430       return value;
3431     }
3432   }
3433   UNREACHABLE();
3434   return NULL;
3435 }
3436
3437
3438 Node* AstGraphBuilder::BuildVariableDelete(Variable* variable,
3439                                            BailoutId bailout_id,
3440                                            OutputFrameStateCombine combine) {
3441   switch (variable->location()) {
3442     case VariableLocation::GLOBAL:
3443     case VariableLocation::UNALLOCATED: {
3444       // Global var, const, or let variable.
3445       Node* global = BuildLoadGlobalObject();
3446       Node* name = jsgraph()->Constant(variable->name());
3447       const Operator* op = javascript()->DeleteProperty(language_mode());
3448       Node* result = NewNode(op, global, name);
3449       PrepareFrameState(result, bailout_id, combine);
3450       return result;
3451     }
3452     case VariableLocation::PARAMETER:
3453     case VariableLocation::LOCAL:
3454     case VariableLocation::CONTEXT: {
3455       // Local var, const, or let variable or context variable.
3456       return jsgraph()->BooleanConstant(variable->HasThisName(isolate()));
3457     }
3458     case VariableLocation::LOOKUP: {
3459       // Dynamic lookup of context variable (anywhere in the chain).
3460       Node* name = jsgraph()->Constant(variable->name());
3461       const Operator* op =
3462           javascript()->CallRuntime(Runtime::kDeleteLookupSlot, 2);
3463       Node* result = NewNode(op, current_context(), name);
3464       PrepareFrameState(result, bailout_id, combine);
3465       return result;
3466     }
3467   }
3468   UNREACHABLE();
3469   return NULL;
3470 }
3471
3472
3473 Node* AstGraphBuilder::BuildVariableAssignment(
3474     Variable* variable, Node* value, Token::Value op,
3475     const VectorSlotPair& feedback, BailoutId bailout_id,
3476     FrameStateBeforeAndAfter& states, OutputFrameStateCombine combine) {
3477   Node* the_hole = jsgraph()->TheHoleConstant();
3478   VariableMode mode = variable->mode();
3479   switch (variable->location()) {
3480     case VariableLocation::GLOBAL:
3481     case VariableLocation::UNALLOCATED: {
3482       // Global var, const, or let variable.
3483       Node* script_context = current_context();
3484       int slot_index = -1;
3485       if (variable->index() > 0) {
3486         DCHECK(variable->IsStaticGlobalObjectProperty());
3487         slot_index = variable->index();
3488         int depth = current_scope()->ContextChainLength(variable->scope());
3489         if (depth > 0) {
3490           const Operator* op = javascript()->LoadContext(
3491               depth - 1, Context::PREVIOUS_INDEX, true);
3492           script_context = NewNode(op, current_context());
3493         }
3494       }
3495       Node* global = BuildLoadGlobalObject();
3496       Handle<Name> name = variable->name();
3497       Node* store =
3498           BuildGlobalStore(script_context, global, name, value, feedback,
3499                            TypeFeedbackId::None(), slot_index);
3500       states.AddToNode(store, bailout_id, combine);
3501       return store;
3502     }
3503     case VariableLocation::PARAMETER:
3504     case VariableLocation::LOCAL:
3505       // Local var, const, or let variable.
3506       if (mode == CONST_LEGACY && op == Token::INIT_CONST_LEGACY) {
3507         // Perform an initialization check for legacy const variables.
3508         Node* current = environment()->Lookup(variable);
3509         if (current->op() != the_hole->op()) {
3510           value = BuildHoleCheckSilent(current, value, current);
3511         }
3512       } else if (mode == CONST_LEGACY && op != Token::INIT_CONST_LEGACY) {
3513         // Non-initializing assignment to legacy const is
3514         // - exception in strict mode.
3515         // - ignored in sloppy mode.
3516         if (is_strict(language_mode())) {
3517           return BuildThrowConstAssignError(bailout_id);
3518         }
3519         return value;
3520       } else if (mode == LET && op != Token::INIT_LET) {
3521         // Perform an initialization check for let declared variables.
3522         // Also note that the dynamic hole-check is only done to ensure that
3523         // this does not break in the presence of do-expressions within the
3524         // temporal dead zone of a let declared variable.
3525         Node* current = environment()->Lookup(variable);
3526         if (current->op() == the_hole->op()) {
3527           value = BuildThrowReferenceError(variable, bailout_id);
3528         } else if (value->opcode() == IrOpcode::kPhi) {
3529           value = BuildHoleCheckThenThrow(current, variable, value, bailout_id);
3530         }
3531       } else if (mode == CONST && op == Token::INIT_CONST) {
3532         // Perform an initialization check for const {this} variables.
3533         // Note that the {this} variable is the only const variable being able
3534         // to trigger bind operations outside the TDZ, via {super} calls.
3535         Node* current = environment()->Lookup(variable);
3536         if (current->op() != the_hole->op() && variable->is_this()) {
3537           value = BuildHoleCheckElseThrow(current, variable, value, bailout_id);
3538         }
3539       } else if (mode == CONST && op != Token::INIT_CONST) {
3540         // Assignment to const is exception in all modes.
3541         Node* current = environment()->Lookup(variable);
3542         if (current->op() == the_hole->op()) {
3543           return BuildThrowReferenceError(variable, bailout_id);
3544         } else if (value->opcode() == IrOpcode::kPhi) {
3545           BuildHoleCheckThenThrow(current, variable, value, bailout_id);
3546         }
3547         return BuildThrowConstAssignError(bailout_id);
3548       }
3549       environment()->Bind(variable, value);
3550       return value;
3551     case VariableLocation::CONTEXT: {
3552       // Context variable (potentially up the context chain).
3553       int depth = current_scope()->ContextChainLength(variable->scope());
3554       if (mode == CONST_LEGACY && op == Token::INIT_CONST_LEGACY) {
3555         // Perform an initialization check for legacy const variables.
3556         const Operator* op =
3557             javascript()->LoadContext(depth, variable->index(), false);
3558         Node* current = NewNode(op, current_context());
3559         value = BuildHoleCheckSilent(current, value, current);
3560       } else if (mode == CONST_LEGACY && op != Token::INIT_CONST_LEGACY) {
3561         // Non-initializing assignment to legacy const is
3562         // - exception in strict mode.
3563         // - ignored in sloppy mode.
3564         if (is_strict(language_mode())) {
3565           return BuildThrowConstAssignError(bailout_id);
3566         }
3567         return value;
3568       } else if (mode == LET && op != Token::INIT_LET) {
3569         // Perform an initialization check for let declared variables.
3570         const Operator* op =
3571             javascript()->LoadContext(depth, variable->index(), false);
3572         Node* current = NewNode(op, current_context());
3573         value = BuildHoleCheckThenThrow(current, variable, value, bailout_id);
3574       } else if (mode == CONST && op == Token::INIT_CONST) {
3575         // Perform an initialization check for const {this} variables.
3576         // Note that the {this} variable is the only const variable being able
3577         // to trigger bind operations outside the TDZ, via {super} calls.
3578         if (variable->is_this()) {
3579           const Operator* op =
3580               javascript()->LoadContext(depth, variable->index(), false);
3581           Node* current = NewNode(op, current_context());
3582           value = BuildHoleCheckElseThrow(current, variable, value, bailout_id);
3583         }
3584       } else if (mode == CONST && op != Token::INIT_CONST) {
3585         // Assignment to const is exception in all modes.
3586         const Operator* op =
3587             javascript()->LoadContext(depth, variable->index(), false);
3588         Node* current = NewNode(op, current_context());
3589         BuildHoleCheckThenThrow(current, variable, value, bailout_id);
3590         return BuildThrowConstAssignError(bailout_id);
3591       }
3592       const Operator* op = javascript()->StoreContext(depth, variable->index());
3593       return NewNode(op, current_context(), value);
3594     }
3595     case VariableLocation::LOOKUP: {
3596       // Dynamic lookup of context variable (anywhere in the chain).
3597       Node* name = jsgraph()->Constant(variable->name());
3598       Node* language = jsgraph()->Constant(language_mode());
3599       // TODO(mstarzinger): Use Runtime::kInitializeLegacyConstLookupSlot for
3600       // initializations of const declarations.
3601       const Operator* op =
3602           javascript()->CallRuntime(Runtime::kStoreLookupSlot, 4);
3603       Node* store = NewNode(op, value, current_context(), name, language);
3604       PrepareFrameState(store, bailout_id, combine);
3605       return store;
3606     }
3607   }
3608   UNREACHABLE();
3609   return NULL;
3610 }
3611
3612
3613 static inline Node* Record(JSTypeFeedbackTable* js_type_feedback, Node* node,
3614                            FeedbackVectorICSlot slot) {
3615   if (js_type_feedback) {
3616     js_type_feedback->Record(node, slot);
3617   }
3618   return node;
3619 }
3620
3621
3622 static inline Node* Record(JSTypeFeedbackTable* js_type_feedback, Node* node,
3623                            TypeFeedbackId id) {
3624   if (js_type_feedback) {
3625     js_type_feedback->Record(node, id);
3626   }
3627   return node;
3628 }
3629
3630
3631 Node* AstGraphBuilder::BuildKeyedLoad(Node* object, Node* key,
3632                                       const VectorSlotPair& feedback) {
3633   const Operator* op = javascript()->LoadProperty(feedback, language_mode());
3634   Node* node = NewNode(op, object, key, BuildLoadFeedbackVector());
3635   return Record(js_type_feedback_, node, feedback.slot());
3636 }
3637
3638
3639 Node* AstGraphBuilder::BuildNamedLoad(Node* object, Handle<Name> name,
3640                                       const VectorSlotPair& feedback) {
3641   const Operator* op =
3642       javascript()->LoadNamed(MakeUnique(name), feedback, language_mode());
3643   Node* node = NewNode(op, object, BuildLoadFeedbackVector());
3644   return Record(js_type_feedback_, node, feedback.slot());
3645 }
3646
3647
3648 Node* AstGraphBuilder::BuildKeyedStore(Node* object, Node* key, Node* value,
3649                                        const VectorSlotPair& feedback,
3650                                        TypeFeedbackId id) {
3651   const Operator* op = javascript()->StoreProperty(language_mode(), feedback);
3652   Node* node = NewNode(op, object, key, value, BuildLoadFeedbackVector());
3653   if (FLAG_vector_stores) {
3654     return Record(js_type_feedback_, node, feedback.slot());
3655   }
3656   return Record(js_type_feedback_, node, id);
3657 }
3658
3659
3660 Node* AstGraphBuilder::BuildNamedStore(Node* object, Handle<Name> name,
3661                                        Node* value,
3662                                        const VectorSlotPair& feedback,
3663                                        TypeFeedbackId id) {
3664   const Operator* op =
3665       javascript()->StoreNamed(language_mode(), MakeUnique(name), feedback);
3666   Node* node = NewNode(op, object, value, BuildLoadFeedbackVector());
3667   if (FLAG_vector_stores) {
3668     return Record(js_type_feedback_, node, feedback.slot());
3669   }
3670   return Record(js_type_feedback_, node, id);
3671 }
3672
3673
3674 Node* AstGraphBuilder::BuildNamedSuperLoad(Node* receiver, Node* home_object,
3675                                            Handle<Name> name,
3676                                            const VectorSlotPair& feedback) {
3677   Node* name_node = jsgraph()->Constant(name);
3678   Node* language = jsgraph()->Constant(language_mode());
3679   const Operator* op = javascript()->CallRuntime(Runtime::kLoadFromSuper, 4);
3680   Node* node = NewNode(op, receiver, home_object, name_node, language);
3681   return Record(js_type_feedback_, node, feedback.slot());
3682 }
3683
3684
3685 Node* AstGraphBuilder::BuildKeyedSuperLoad(Node* receiver, Node* home_object,
3686                                            Node* key,
3687                                            const VectorSlotPair& feedback) {
3688   Node* language = jsgraph()->Constant(language_mode());
3689   const Operator* op =
3690       javascript()->CallRuntime(Runtime::kLoadKeyedFromSuper, 4);
3691   Node* node = NewNode(op, receiver, home_object, key, language);
3692   return Record(js_type_feedback_, node, feedback.slot());
3693 }
3694
3695
3696 Node* AstGraphBuilder::BuildKeyedSuperStore(Node* receiver, Node* home_object,
3697                                             Node* key, Node* value,
3698                                             TypeFeedbackId id) {
3699   Runtime::FunctionId function_id = is_strict(language_mode())
3700                                         ? Runtime::kStoreKeyedToSuper_Strict
3701                                         : Runtime::kStoreKeyedToSuper_Sloppy;
3702   const Operator* op = javascript()->CallRuntime(function_id, 4);
3703   Node* node = NewNode(op, receiver, home_object, key, value);
3704   return Record(js_type_feedback_, node, id);
3705 }
3706
3707
3708 Node* AstGraphBuilder::BuildNamedSuperStore(Node* receiver, Node* home_object,
3709                                             Handle<Name> name, Node* value,
3710                                             TypeFeedbackId id) {
3711   Node* name_node = jsgraph()->Constant(name);
3712   Runtime::FunctionId function_id = is_strict(language_mode())
3713                                         ? Runtime::kStoreToSuper_Strict
3714                                         : Runtime::kStoreToSuper_Sloppy;
3715   const Operator* op = javascript()->CallRuntime(function_id, 4);
3716   Node* node = NewNode(op, receiver, home_object, name_node, value);
3717   return Record(js_type_feedback_, node, id);
3718 }
3719
3720
3721 Node* AstGraphBuilder::BuildGlobalLoad(Node* script_context, Node* global,
3722                                        Handle<Name> name,
3723                                        const VectorSlotPair& feedback,
3724                                        TypeofMode typeof_mode, int slot_index) {
3725   const Operator* op = javascript()->LoadGlobal(MakeUnique(name), feedback,
3726                                                 typeof_mode, slot_index);
3727   Node* node = NewNode(op, script_context, global, BuildLoadFeedbackVector());
3728   return Record(js_type_feedback_, node, feedback.slot());
3729 }
3730
3731
3732 Node* AstGraphBuilder::BuildGlobalStore(Node* script_context, Node* global,
3733                                         Handle<Name> name, Node* value,
3734                                         const VectorSlotPair& feedback,
3735                                         TypeFeedbackId id, int slot_index) {
3736   const Operator* op = javascript()->StoreGlobal(
3737       language_mode(), MakeUnique(name), feedback, slot_index);
3738   Node* node =
3739       NewNode(op, script_context, global, value, BuildLoadFeedbackVector());
3740   if (FLAG_vector_stores) {
3741     return Record(js_type_feedback_, node, feedback.slot());
3742   }
3743   return Record(js_type_feedback_, node, id);
3744 }
3745
3746
3747 Node* AstGraphBuilder::BuildLoadObjectField(Node* object, int offset) {
3748   return NewNode(jsgraph()->machine()->Load(kMachAnyTagged), object,
3749                  jsgraph()->IntPtrConstant(offset - kHeapObjectTag));
3750 }
3751
3752
3753 Node* AstGraphBuilder::BuildLoadImmutableObjectField(Node* object, int offset) {
3754   return graph()->NewNode(jsgraph()->machine()->Load(kMachAnyTagged), object,
3755                           jsgraph()->IntPtrConstant(offset - kHeapObjectTag),
3756                           graph()->start(), graph()->start());
3757 }
3758
3759
3760 Node* AstGraphBuilder::BuildLoadBuiltinsObject() {
3761   Node* global = BuildLoadGlobalObject();
3762   Node* builtins =
3763       BuildLoadObjectField(global, JSGlobalObject::kBuiltinsOffset);
3764   return builtins;
3765 }
3766
3767
3768 Node* AstGraphBuilder::BuildLoadGlobalObject() {
3769   const Operator* load_op =
3770       javascript()->LoadContext(0, Context::GLOBAL_OBJECT_INDEX, true);
3771   return NewNode(load_op, GetFunctionContext());
3772 }
3773
3774
3775 Node* AstGraphBuilder::BuildLoadGlobalProxy() {
3776   Node* global = BuildLoadGlobalObject();
3777   Node* proxy =
3778       BuildLoadObjectField(global, JSGlobalObject::kGlobalProxyOffset);
3779   return proxy;
3780 }
3781
3782
3783 Node* AstGraphBuilder::BuildLoadFeedbackVector() {
3784   if (!feedback_vector_.is_set()) {
3785     Node* closure = GetFunctionClosure();
3786     Node* shared = BuildLoadImmutableObjectField(
3787         closure, JSFunction::kSharedFunctionInfoOffset);
3788     Node* vector = BuildLoadImmutableObjectField(
3789         shared, SharedFunctionInfo::kFeedbackVectorOffset);
3790     feedback_vector_.set(vector);
3791   }
3792   return feedback_vector_.get();
3793 }
3794
3795
3796 Node* AstGraphBuilder::BuildLoadExternal(ExternalReference reference,
3797                                          MachineType type) {
3798   return NewNode(jsgraph()->machine()->Load(type),
3799                  jsgraph()->ExternalConstant(reference),
3800                  jsgraph()->IntPtrConstant(0));
3801 }
3802
3803
3804 Node* AstGraphBuilder::BuildStoreExternal(ExternalReference reference,
3805                                           MachineType type, Node* value) {
3806   StoreRepresentation representation(type, kNoWriteBarrier);
3807   return NewNode(jsgraph()->machine()->Store(representation),
3808                  jsgraph()->ExternalConstant(reference),
3809                  jsgraph()->IntPtrConstant(0), value);
3810 }
3811
3812
3813 Node* AstGraphBuilder::BuildToBoolean(Node* input) {
3814   // TODO(bmeurer, mstarzinger): Refactor this into a separate optimization
3815   // method.
3816   switch (input->opcode()) {
3817     case IrOpcode::kNumberConstant: {
3818       NumberMatcher m(input);
3819       return jsgraph_->BooleanConstant(!m.Is(0) && !m.IsNaN());
3820     }
3821     case IrOpcode::kHeapConstant: {
3822       Handle<HeapObject> object = HeapObjectMatcher(input).Value().handle();
3823       return jsgraph_->BooleanConstant(object->BooleanValue());
3824     }
3825     case IrOpcode::kJSEqual:
3826     case IrOpcode::kJSNotEqual:
3827     case IrOpcode::kJSStrictEqual:
3828     case IrOpcode::kJSStrictNotEqual:
3829     case IrOpcode::kJSLessThan:
3830     case IrOpcode::kJSLessThanOrEqual:
3831     case IrOpcode::kJSGreaterThan:
3832     case IrOpcode::kJSGreaterThanOrEqual:
3833     case IrOpcode::kJSUnaryNot:
3834     case IrOpcode::kJSToBoolean:
3835     case IrOpcode::kJSDeleteProperty:
3836     case IrOpcode::kJSHasProperty:
3837     case IrOpcode::kJSInstanceOf:
3838       return input;
3839     default:
3840       break;
3841   }
3842   return NewNode(javascript()->ToBoolean(), input);
3843 }
3844
3845
3846 Node* AstGraphBuilder::BuildToName(Node* input, BailoutId bailout_id) {
3847   // TODO(turbofan): Possible optimization is to NOP on name constants. But the
3848   // same caveat as with BuildToBoolean applies, and it should be factored out
3849   // into a JSOperatorReducer.
3850   Node* name = NewNode(javascript()->ToName(), input);
3851   PrepareFrameState(name, bailout_id);
3852   return name;
3853 }
3854
3855
3856 Node* AstGraphBuilder::BuildToObject(Node* input, BailoutId bailout_id) {
3857   Node* object = NewNode(javascript()->ToObject(), input);
3858   PrepareFrameState(object, bailout_id, OutputFrameStateCombine::Push());
3859   return object;
3860 }
3861
3862
3863 Node* AstGraphBuilder::BuildSetHomeObject(Node* value, Node* home_object,
3864                                           Expression* expr,
3865                                           const VectorSlotPair& feedback) {
3866   if (!FunctionLiteral::NeedsHomeObject(expr)) return value;
3867   Handle<Name> name = isolate()->factory()->home_object_symbol();
3868   FrameStateBeforeAndAfter states(this, BailoutId::None());
3869   Node* store = BuildNamedStore(value, name, home_object, feedback,
3870                                 TypeFeedbackId::None());
3871   states.AddToNode(store, BailoutId::None(), OutputFrameStateCombine::Ignore());
3872   return store;
3873 }
3874
3875
3876 Node* AstGraphBuilder::BuildThrowError(Node* exception, BailoutId bailout_id) {
3877   const Operator* op = javascript()->CallRuntime(Runtime::kThrow, 1);
3878   Node* call = NewNode(op, exception);
3879   PrepareFrameState(call, bailout_id);
3880   Node* control = NewNode(common()->Throw(), call);
3881   UpdateControlDependencyToLeaveFunction(control);
3882   return call;
3883 }
3884
3885
3886 Node* AstGraphBuilder::BuildThrowReferenceError(Variable* variable,
3887                                                 BailoutId bailout_id) {
3888   Node* variable_name = jsgraph()->Constant(variable->name());
3889   const Operator* op =
3890       javascript()->CallRuntime(Runtime::kThrowReferenceError, 1);
3891   Node* call = NewNode(op, variable_name);
3892   PrepareFrameState(call, bailout_id);
3893   Node* control = NewNode(common()->Throw(), call);
3894   UpdateControlDependencyToLeaveFunction(control);
3895   return call;
3896 }
3897
3898
3899 Node* AstGraphBuilder::BuildThrowConstAssignError(BailoutId bailout_id) {
3900   const Operator* op =
3901       javascript()->CallRuntime(Runtime::kThrowConstAssignError, 0);
3902   Node* call = NewNode(op);
3903   PrepareFrameState(call, bailout_id);
3904   Node* control = NewNode(common()->Throw(), call);
3905   UpdateControlDependencyToLeaveFunction(control);
3906   return call;
3907 }
3908
3909
3910 Node* AstGraphBuilder::BuildThrowStaticPrototypeError(BailoutId bailout_id) {
3911   const Operator* op =
3912       javascript()->CallRuntime(Runtime::kThrowStaticPrototypeError, 0);
3913   Node* call = NewNode(op);
3914   PrepareFrameState(call, bailout_id);
3915   Node* control = NewNode(common()->Throw(), call);
3916   UpdateControlDependencyToLeaveFunction(control);
3917   return call;
3918 }
3919
3920
3921 Node* AstGraphBuilder::BuildThrowUnsupportedSuperError(BailoutId bailout_id) {
3922   const Operator* op =
3923       javascript()->CallRuntime(Runtime::kThrowUnsupportedSuperError, 0);
3924   Node* call = NewNode(op);
3925   PrepareFrameState(call, bailout_id);
3926   Node* control = NewNode(common()->Throw(), call);
3927   UpdateControlDependencyToLeaveFunction(control);
3928   return call;
3929 }
3930
3931
3932 Node* AstGraphBuilder::BuildReturn(Node* return_value) {
3933   Node* control = NewNode(common()->Return(), return_value);
3934   UpdateControlDependencyToLeaveFunction(control);
3935   return control;
3936 }
3937
3938
3939 Node* AstGraphBuilder::BuildThrow(Node* exception_value) {
3940   NewNode(javascript()->CallRuntime(Runtime::kReThrow, 1), exception_value);
3941   Node* control = NewNode(common()->Throw(), exception_value);
3942   UpdateControlDependencyToLeaveFunction(control);
3943   return control;
3944 }
3945
3946
3947 Node* AstGraphBuilder::BuildBinaryOp(Node* left, Node* right, Token::Value op) {
3948   const Operator* js_op;
3949   switch (op) {
3950     case Token::BIT_OR:
3951       js_op = javascript()->BitwiseOr(language_mode());
3952       break;
3953     case Token::BIT_AND:
3954       js_op = javascript()->BitwiseAnd(language_mode());
3955       break;
3956     case Token::BIT_XOR:
3957       js_op = javascript()->BitwiseXor(language_mode());
3958       break;
3959     case Token::SHL:
3960       js_op = javascript()->ShiftLeft(language_mode());
3961       break;
3962     case Token::SAR:
3963       js_op = javascript()->ShiftRight(language_mode());
3964       break;
3965     case Token::SHR:
3966       js_op = javascript()->ShiftRightLogical(language_mode());
3967       break;
3968     case Token::ADD:
3969       js_op = javascript()->Add(language_mode());
3970       break;
3971     case Token::SUB:
3972       js_op = javascript()->Subtract(language_mode());
3973       break;
3974     case Token::MUL:
3975       js_op = javascript()->Multiply(language_mode());
3976       break;
3977     case Token::DIV:
3978       js_op = javascript()->Divide(language_mode());
3979       break;
3980     case Token::MOD:
3981       js_op = javascript()->Modulus(language_mode());
3982       break;
3983     default:
3984       UNREACHABLE();
3985       js_op = NULL;
3986   }
3987   return NewNode(js_op, left, right);
3988 }
3989
3990
3991 bool AstGraphBuilder::CheckOsrEntry(IterationStatement* stmt) {
3992   if (info()->osr_ast_id() == stmt->OsrEntryId()) {
3993     info()->set_osr_expr_stack_height(std::max(
3994         environment()->stack_height(), info()->osr_expr_stack_height()));
3995     return true;
3996   }
3997   return false;
3998 }
3999
4000
4001 void AstGraphBuilder::PrepareFrameState(Node* node, BailoutId ast_id,
4002                                         OutputFrameStateCombine combine) {
4003   if (OperatorProperties::GetFrameStateInputCount(node->op()) > 0) {
4004     DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
4005
4006     DCHECK_EQ(IrOpcode::kDead,
4007               NodeProperties::GetFrameStateInput(node, 0)->opcode());
4008     NodeProperties::ReplaceFrameStateInput(
4009         node, 0, environment()->Checkpoint(ast_id, combine));
4010   }
4011 }
4012
4013
4014 BitVector* AstGraphBuilder::GetVariablesAssignedInLoop(
4015     IterationStatement* stmt) {
4016   if (loop_assignment_analysis_ == NULL) return NULL;
4017   return loop_assignment_analysis_->GetVariablesAssignedInLoop(stmt);
4018 }
4019
4020
4021 Node** AstGraphBuilder::EnsureInputBufferSize(int size) {
4022   if (size > input_buffer_size_) {
4023     size = size + kInputBufferSizeIncrement + input_buffer_size_;
4024     input_buffer_ = local_zone()->NewArray<Node*>(size);
4025     input_buffer_size_ = size;
4026   }
4027   return input_buffer_;
4028 }
4029
4030
4031 Node* AstGraphBuilder::MakeNode(const Operator* op, int value_input_count,
4032                                 Node** value_inputs, bool incomplete) {
4033   DCHECK_EQ(op->ValueInputCount(), value_input_count);
4034
4035   bool has_context = OperatorProperties::HasContextInput(op);
4036   int frame_state_count = OperatorProperties::GetFrameStateInputCount(op);
4037   bool has_control = op->ControlInputCount() == 1;
4038   bool has_effect = op->EffectInputCount() == 1;
4039
4040   DCHECK(op->ControlInputCount() < 2);
4041   DCHECK(op->EffectInputCount() < 2);
4042
4043   Node* result = NULL;
4044   if (!has_context && frame_state_count == 0 && !has_control && !has_effect) {
4045     result = graph()->NewNode(op, value_input_count, value_inputs, incomplete);
4046   } else {
4047     bool inside_try_scope = try_nesting_level_ > 0;
4048     int input_count_with_deps = value_input_count;
4049     if (has_context) ++input_count_with_deps;
4050     input_count_with_deps += frame_state_count;
4051     if (has_control) ++input_count_with_deps;
4052     if (has_effect) ++input_count_with_deps;
4053     Node** buffer = EnsureInputBufferSize(input_count_with_deps);
4054     memcpy(buffer, value_inputs, kPointerSize * value_input_count);
4055     Node** current_input = buffer + value_input_count;
4056     if (has_context) {
4057       *current_input++ = current_context();
4058     }
4059     for (int i = 0; i < frame_state_count; i++) {
4060       // The frame state will be inserted later. Here we misuse
4061       // the {Dead} node as a sentinel to be later overwritten
4062       // with the real frame state.
4063       *current_input++ = jsgraph()->Dead();
4064     }
4065     if (has_effect) {
4066       *current_input++ = environment_->GetEffectDependency();
4067     }
4068     if (has_control) {
4069       *current_input++ = environment_->GetControlDependency();
4070     }
4071     result = graph()->NewNode(op, input_count_with_deps, buffer, incomplete);
4072     if (!environment()->IsMarkedAsUnreachable()) {
4073       // Update the current control dependency for control-producing nodes.
4074       if (NodeProperties::IsControl(result)) {
4075         environment_->UpdateControlDependency(result);
4076       }
4077       // Update the current effect dependency for effect-producing nodes.
4078       if (result->op()->EffectOutputCount() > 0) {
4079         environment_->UpdateEffectDependency(result);
4080       }
4081       // Add implicit exception continuation for throwing nodes.
4082       if (!result->op()->HasProperty(Operator::kNoThrow) && inside_try_scope) {
4083         // Conservative prediction whether caught locally.
4084         IfExceptionHint hint = try_catch_nesting_level_ > 0
4085                                    ? IfExceptionHint::kLocallyCaught
4086                                    : IfExceptionHint::kLocallyUncaught;
4087         // Copy the environment for the success continuation.
4088         Environment* success_env = environment()->CopyForConditional();
4089         const Operator* op = common()->IfException(hint);
4090         Node* effect = environment()->GetEffectDependency();
4091         Node* on_exception = graph()->NewNode(op, effect, result);
4092         environment_->UpdateControlDependency(on_exception);
4093         environment_->UpdateEffectDependency(on_exception);
4094         execution_control()->ThrowValue(on_exception);
4095         set_environment(success_env);
4096       }
4097       // Add implicit success continuation for throwing nodes.
4098       if (!result->op()->HasProperty(Operator::kNoThrow)) {
4099         const Operator* op = common()->IfSuccess();
4100         Node* on_success = graph()->NewNode(op, result);
4101         environment_->UpdateControlDependency(on_success);
4102       }
4103     }
4104   }
4105
4106   return result;
4107 }
4108
4109
4110 void AstGraphBuilder::UpdateControlDependencyToLeaveFunction(Node* exit) {
4111   if (environment()->IsMarkedAsUnreachable()) return;
4112   environment()->MarkAsUnreachable();
4113   exit_controls_.push_back(exit);
4114 }
4115
4116
4117 void AstGraphBuilder::Environment::Merge(Environment* other) {
4118   DCHECK(values_.size() == other->values_.size());
4119   DCHECK(contexts_.size() == other->contexts_.size());
4120
4121   // Nothing to do if the other environment is dead.
4122   if (other->IsMarkedAsUnreachable()) return;
4123
4124   // Resurrect a dead environment by copying the contents of the other one and
4125   // placing a singleton merge as the new control dependency.
4126   if (this->IsMarkedAsUnreachable()) {
4127     Node* other_control = other->control_dependency_;
4128     Node* inputs[] = {other_control};
4129     control_dependency_ =
4130         graph()->NewNode(common()->Merge(1), arraysize(inputs), inputs, true);
4131     effect_dependency_ = other->effect_dependency_;
4132     values_ = other->values_;
4133     contexts_ = other->contexts_;
4134     if (IsLivenessAnalysisEnabled()) {
4135       liveness_block_ =
4136           builder_->liveness_analyzer()->NewBlock(other->liveness_block());
4137     }
4138     return;
4139   }
4140
4141   // Record the merge for the local variable liveness calculation.
4142   // For loops, we are connecting a back edge into the existing block;
4143   // for merges, we create a new merged block.
4144   if (IsLivenessAnalysisEnabled()) {
4145     if (GetControlDependency()->opcode() != IrOpcode::kLoop) {
4146       liveness_block_ =
4147           builder_->liveness_analyzer()->NewBlock(liveness_block());
4148     }
4149     liveness_block()->AddPredecessor(other->liveness_block());
4150   }
4151
4152   // Create a merge of the control dependencies of both environments and update
4153   // the current environment's control dependency accordingly.
4154   Node* control = builder_->MergeControl(this->GetControlDependency(),
4155                                          other->GetControlDependency());
4156   UpdateControlDependency(control);
4157
4158   // Create a merge of the effect dependencies of both environments and update
4159   // the current environment's effect dependency accordingly.
4160   Node* effect = builder_->MergeEffect(this->GetEffectDependency(),
4161                                        other->GetEffectDependency(), control);
4162   UpdateEffectDependency(effect);
4163
4164   // Introduce Phi nodes for values that have differing input at merge points,
4165   // potentially extending an existing Phi node if possible.
4166   for (int i = 0; i < static_cast<int>(values_.size()); ++i) {
4167     values_[i] = builder_->MergeValue(values_[i], other->values_[i], control);
4168   }
4169   for (int i = 0; i < static_cast<int>(contexts_.size()); ++i) {
4170     contexts_[i] =
4171         builder_->MergeValue(contexts_[i], other->contexts_[i], control);
4172   }
4173 }
4174
4175
4176 void AstGraphBuilder::Environment::PrepareForLoop(BitVector* assigned,
4177                                                   bool is_osr) {
4178   int size = static_cast<int>(values()->size());
4179
4180   Node* control = builder_->NewLoop();
4181   if (assigned == nullptr) {
4182     // Assume that everything is updated in the loop.
4183     for (int i = 0; i < size; ++i) {
4184       values()->at(i) = builder_->NewPhi(1, values()->at(i), control);
4185     }
4186   } else {
4187     // Only build phis for those locals assigned in this loop.
4188     for (int i = 0; i < size; ++i) {
4189       if (i < assigned->length() && !assigned->Contains(i)) continue;
4190       Node* phi = builder_->NewPhi(1, values()->at(i), control);
4191       values()->at(i) = phi;
4192     }
4193   }
4194   Node* effect = builder_->NewEffectPhi(1, GetEffectDependency(), control);
4195   UpdateEffectDependency(effect);
4196
4197   // Connect the loop to end via Terminate if it's not marked as unreachable.
4198   if (!IsMarkedAsUnreachable()) {
4199     // Connect the Loop node to end via a Terminate node.
4200     Node* terminate = builder_->graph()->NewNode(
4201         builder_->common()->Terminate(), effect, control);
4202     builder_->exit_controls_.push_back(terminate);
4203   }
4204
4205   if (builder_->info()->is_osr()) {
4206     // Introduce phis for all context values in the case of an OSR graph.
4207     for (size_t i = 0; i < contexts()->size(); ++i) {
4208       Node* context = contexts()->at(i);
4209       contexts()->at(i) = builder_->NewPhi(1, context, control);
4210     }
4211   }
4212
4213   if (is_osr) {
4214     // Merge OSR values as inputs to the phis of the loop.
4215     Graph* graph = builder_->graph();
4216     Node* osr_loop_entry = builder_->graph()->NewNode(
4217         builder_->common()->OsrLoopEntry(), graph->start(), graph->start());
4218
4219     builder_->MergeControl(control, osr_loop_entry);
4220     builder_->MergeEffect(effect, osr_loop_entry, control);
4221
4222     for (int i = 0; i < size; ++i) {
4223       Node* value = values()->at(i);
4224       Node* osr_value =
4225           graph->NewNode(builder_->common()->OsrValue(i), osr_loop_entry);
4226       values()->at(i) = builder_->MergeValue(value, osr_value, control);
4227     }
4228
4229     // Rename all the contexts in the environment.
4230     // The innermost context is the OSR value, and the outer contexts are
4231     // reconstructed by dynamically walking up the context chain.
4232     Node* osr_context = nullptr;
4233     const Operator* op =
4234         builder_->javascript()->LoadContext(0, Context::PREVIOUS_INDEX, true);
4235     const Operator* op_inner =
4236         builder_->common()->OsrValue(Linkage::kOsrContextSpillSlotIndex);
4237     int last = static_cast<int>(contexts()->size() - 1);
4238     for (int i = last; i >= 0; i--) {
4239       Node* context = contexts()->at(i);
4240       osr_context = (i == last) ? graph->NewNode(op_inner, osr_loop_entry)
4241                                 : graph->NewNode(op, osr_context, osr_context,
4242                                                  osr_loop_entry);
4243       contexts()->at(i) = builder_->MergeValue(context, osr_context, control);
4244     }
4245   }
4246 }
4247
4248
4249 Node* AstGraphBuilder::NewPhi(int count, Node* input, Node* control) {
4250   const Operator* phi_op = common()->Phi(kMachAnyTagged, count);
4251   Node** buffer = EnsureInputBufferSize(count + 1);
4252   MemsetPointer(buffer, input, count);
4253   buffer[count] = control;
4254   return graph()->NewNode(phi_op, count + 1, buffer, true);
4255 }
4256
4257
4258 // TODO(mstarzinger): Revisit this once we have proper effect states.
4259 Node* AstGraphBuilder::NewEffectPhi(int count, Node* input, Node* control) {
4260   const Operator* phi_op = common()->EffectPhi(count);
4261   Node** buffer = EnsureInputBufferSize(count + 1);
4262   MemsetPointer(buffer, input, count);
4263   buffer[count] = control;
4264   return graph()->NewNode(phi_op, count + 1, buffer, true);
4265 }
4266
4267
4268 Node* AstGraphBuilder::MergeControl(Node* control, Node* other) {
4269   int inputs = control->op()->ControlInputCount() + 1;
4270   if (control->opcode() == IrOpcode::kLoop) {
4271     // Control node for loop exists, add input.
4272     const Operator* op = common()->Loop(inputs);
4273     control->AppendInput(graph_zone(), other);
4274     control->set_op(op);
4275   } else if (control->opcode() == IrOpcode::kMerge) {
4276     // Control node for merge exists, add input.
4277     const Operator* op = common()->Merge(inputs);
4278     control->AppendInput(graph_zone(), other);
4279     control->set_op(op);
4280   } else {
4281     // Control node is a singleton, introduce a merge.
4282     const Operator* op = common()->Merge(inputs);
4283     Node* inputs[] = {control, other};
4284     control = graph()->NewNode(op, arraysize(inputs), inputs, true);
4285   }
4286   return control;
4287 }
4288
4289
4290 Node* AstGraphBuilder::MergeEffect(Node* value, Node* other, Node* control) {
4291   int inputs = control->op()->ControlInputCount();
4292   if (value->opcode() == IrOpcode::kEffectPhi &&
4293       NodeProperties::GetControlInput(value) == control) {
4294     // Phi already exists, add input.
4295     value->set_op(common()->EffectPhi(inputs));
4296     value->InsertInput(graph_zone(), inputs - 1, other);
4297   } else if (value != other) {
4298     // Phi does not exist yet, introduce one.
4299     value = NewEffectPhi(inputs, value, control);
4300     value->ReplaceInput(inputs - 1, other);
4301   }
4302   return value;
4303 }
4304
4305
4306 Node* AstGraphBuilder::MergeValue(Node* value, Node* other, Node* control) {
4307   int inputs = control->op()->ControlInputCount();
4308   if (value->opcode() == IrOpcode::kPhi &&
4309       NodeProperties::GetControlInput(value) == control) {
4310     // Phi already exists, add input.
4311     value->set_op(common()->Phi(kMachAnyTagged, inputs));
4312     value->InsertInput(graph_zone(), inputs - 1, other);
4313   } else if (value != other) {
4314     // Phi does not exist yet, introduce one.
4315     value = NewPhi(inputs, value, control);
4316     value->ReplaceInput(inputs - 1, other);
4317   }
4318   return value;
4319 }
4320
4321 }  // namespace compiler
4322 }  // namespace internal
4323 }  // namespace v8