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