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