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