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