• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 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/interpreter/bytecode-generator.h"
6 
7 #include "src/ast/scopes.h"
8 #include "src/code-stubs.h"
9 #include "src/compiler.h"
10 #include "src/interpreter/bytecode-register-allocator.h"
11 #include "src/interpreter/control-flow-builders.h"
12 #include "src/objects.h"
13 #include "src/parsing/parser.h"
14 #include "src/parsing/token.h"
15 
16 namespace v8 {
17 namespace internal {
18 namespace interpreter {
19 
20 // Scoped class tracking context objects created by the visitor. Represents
21 // mutations of the context chain within the function body, allowing pushing and
22 // popping of the current {context_register} during visitation.
23 class BytecodeGenerator::ContextScope BASE_EMBEDDED {
24  public:
ContextScope(BytecodeGenerator * generator,Scope * scope,bool should_pop_context=true)25   ContextScope(BytecodeGenerator* generator, Scope* scope,
26                bool should_pop_context = true)
27       : generator_(generator),
28         scope_(scope),
29         outer_(generator_->execution_context()),
30         register_(Register::current_context()),
31         depth_(0),
32         should_pop_context_(should_pop_context) {
33     if (outer_) {
34       depth_ = outer_->depth_ + 1;
35 
36       // Push the outer context into a new context register.
37       Register outer_context_reg(builder()->first_context_register().index() +
38                                  outer_->depth_);
39       outer_->set_register(outer_context_reg);
40       generator_->builder()->PushContext(outer_context_reg);
41     }
42     generator_->set_execution_context(this);
43   }
44 
~ContextScope()45   ~ContextScope() {
46     if (outer_ && should_pop_context_) {
47       DCHECK_EQ(register_.index(), Register::current_context().index());
48       generator_->builder()->PopContext(outer_->reg());
49       outer_->set_register(register_);
50     }
51     generator_->set_execution_context(outer_);
52   }
53 
54   // Returns the depth of the given |scope| for the current execution context.
ContextChainDepth(Scope * scope)55   int ContextChainDepth(Scope* scope) {
56     return scope_->ContextChainLength(scope);
57   }
58 
59   // Returns the execution context at |depth| in the current context chain if it
60   // is a function local execution context, otherwise returns nullptr.
Previous(int depth)61   ContextScope* Previous(int depth) {
62     if (depth > depth_) {
63       return nullptr;
64     }
65 
66     ContextScope* previous = this;
67     for (int i = depth; i > 0; --i) {
68       previous = previous->outer_;
69     }
70     return previous;
71   }
72 
scope() const73   Scope* scope() const { return scope_; }
reg() const74   Register reg() const { return register_; }
ShouldPopContext()75   bool ShouldPopContext() { return should_pop_context_; }
76 
77  private:
builder() const78   const BytecodeArrayBuilder* builder() const { return generator_->builder(); }
79 
set_register(Register reg)80   void set_register(Register reg) { register_ = reg; }
81 
82   BytecodeGenerator* generator_;
83   Scope* scope_;
84   ContextScope* outer_;
85   Register register_;
86   int depth_;
87   bool should_pop_context_;
88 };
89 
90 // Scoped class for tracking control statements entered by the
91 // visitor. The pattern derives AstGraphBuilder::ControlScope.
92 class BytecodeGenerator::ControlScope BASE_EMBEDDED {
93  public:
ControlScope(BytecodeGenerator * generator)94   explicit ControlScope(BytecodeGenerator* generator)
95       : generator_(generator), outer_(generator->execution_control()),
96         context_(generator->execution_context()) {
97     generator_->set_execution_control(this);
98   }
~ControlScope()99   virtual ~ControlScope() { generator_->set_execution_control(outer()); }
100 
Break(Statement * stmt)101   void Break(Statement* stmt) { PerformCommand(CMD_BREAK, stmt); }
Continue(Statement * stmt)102   void Continue(Statement* stmt) { PerformCommand(CMD_CONTINUE, stmt); }
ReturnAccumulator()103   void ReturnAccumulator() { PerformCommand(CMD_RETURN, nullptr); }
ReThrowAccumulator()104   void ReThrowAccumulator() { PerformCommand(CMD_RETHROW, nullptr); }
105 
106   class DeferredCommands;
107 
108  protected:
109   enum Command { CMD_BREAK, CMD_CONTINUE, CMD_RETURN, CMD_RETHROW };
110   void PerformCommand(Command command, Statement* statement);
111   virtual bool Execute(Command command, Statement* statement) = 0;
112 
generator() const113   BytecodeGenerator* generator() const { return generator_; }
outer() const114   ControlScope* outer() const { return outer_; }
context() const115   ContextScope* context() const { return context_; }
116 
117  private:
118   BytecodeGenerator* generator_;
119   ControlScope* outer_;
120   ContextScope* context_;
121 
122   DISALLOW_COPY_AND_ASSIGN(ControlScope);
123 };
124 
125 // Helper class for a try-finally control scope. It can record intercepted
126 // control-flow commands that cause entry into a finally-block, and re-apply
127 // them after again leaving that block. Special tokens are used to identify
128 // paths going through the finally-block to dispatch after leaving the block.
129 class BytecodeGenerator::ControlScope::DeferredCommands final {
130  public:
DeferredCommands(BytecodeGenerator * generator,Register token_register,Register result_register)131   DeferredCommands(BytecodeGenerator* generator, Register token_register,
132                    Register result_register)
133       : generator_(generator),
134         deferred_(generator->zone()),
135         token_register_(token_register),
136         result_register_(result_register) {}
137 
138   // One recorded control-flow command.
139   struct Entry {
140     Command command;       // The command type being applied on this path.
141     Statement* statement;  // The target statement for the command or {nullptr}.
142     int token;             // A token identifying this particular path.
143   };
144 
145   // Records a control-flow command while entering the finally-block. This also
146   // generates a new dispatch token that identifies one particular path. This
147   // expects the result to be in the accumulator.
RecordCommand(Command command,Statement * statement)148   void RecordCommand(Command command, Statement* statement) {
149     int token = static_cast<int>(deferred_.size());
150     deferred_.push_back({command, statement, token});
151 
152     builder()->StoreAccumulatorInRegister(result_register_);
153     builder()->LoadLiteral(Smi::FromInt(token));
154     builder()->StoreAccumulatorInRegister(token_register_);
155   }
156 
157   // Records the dispatch token to be used to identify the re-throw path when
158   // the finally-block has been entered through the exception handler. This
159   // expects the exception to be in the accumulator.
RecordHandlerReThrowPath()160   void RecordHandlerReThrowPath() {
161     // The accumulator contains the exception object.
162     RecordCommand(CMD_RETHROW, nullptr);
163   }
164 
165   // Records the dispatch token to be used to identify the implicit fall-through
166   // path at the end of a try-block into the corresponding finally-block.
RecordFallThroughPath()167   void RecordFallThroughPath() {
168     builder()->LoadLiteral(Smi::FromInt(-1));
169     builder()->StoreAccumulatorInRegister(token_register_);
170   }
171 
172   // Applies all recorded control-flow commands after the finally-block again.
173   // This generates a dynamic dispatch on the token from the entry point.
ApplyDeferredCommands()174   void ApplyDeferredCommands() {
175     // The fall-through path is covered by the default case, hence +1 here.
176     SwitchBuilder dispatch(builder(), static_cast<int>(deferred_.size() + 1));
177     for (size_t i = 0; i < deferred_.size(); ++i) {
178       Entry& entry = deferred_[i];
179       builder()->LoadLiteral(Smi::FromInt(entry.token));
180       builder()->CompareOperation(Token::EQ_STRICT, token_register_);
181       dispatch.Case(static_cast<int>(i));
182     }
183     dispatch.DefaultAt(static_cast<int>(deferred_.size()));
184     for (size_t i = 0; i < deferred_.size(); ++i) {
185       Entry& entry = deferred_[i];
186       dispatch.SetCaseTarget(static_cast<int>(i));
187       builder()->LoadAccumulatorWithRegister(result_register_);
188       execution_control()->PerformCommand(entry.command, entry.statement);
189     }
190     dispatch.SetCaseTarget(static_cast<int>(deferred_.size()));
191   }
192 
builder()193   BytecodeArrayBuilder* builder() { return generator_->builder(); }
execution_control()194   ControlScope* execution_control() { return generator_->execution_control(); }
195 
196  private:
197   BytecodeGenerator* generator_;
198   ZoneVector<Entry> deferred_;
199   Register token_register_;
200   Register result_register_;
201 };
202 
203 // Scoped class for dealing with control flow reaching the function level.
204 class BytecodeGenerator::ControlScopeForTopLevel final
205     : public BytecodeGenerator::ControlScope {
206  public:
ControlScopeForTopLevel(BytecodeGenerator * generator)207   explicit ControlScopeForTopLevel(BytecodeGenerator* generator)
208       : ControlScope(generator) {}
209 
210  protected:
Execute(Command command,Statement * statement)211   bool Execute(Command command, Statement* statement) override {
212     switch (command) {
213       case CMD_BREAK:  // We should never see break/continue in top-level.
214       case CMD_CONTINUE:
215         UNREACHABLE();
216       case CMD_RETURN:
217         generator()->builder()->Return();
218         return true;
219       case CMD_RETHROW:
220         generator()->builder()->ReThrow();
221         return true;
222     }
223     return false;
224   }
225 };
226 
227 // Scoped class for enabling break inside blocks and switch blocks.
228 class BytecodeGenerator::ControlScopeForBreakable final
229     : public BytecodeGenerator::ControlScope {
230  public:
ControlScopeForBreakable(BytecodeGenerator * generator,BreakableStatement * statement,BreakableControlFlowBuilder * control_builder)231   ControlScopeForBreakable(BytecodeGenerator* generator,
232                            BreakableStatement* statement,
233                            BreakableControlFlowBuilder* control_builder)
234       : ControlScope(generator),
235         statement_(statement),
236         control_builder_(control_builder) {}
237 
238  protected:
Execute(Command command,Statement * statement)239   bool Execute(Command command, Statement* statement) override {
240     if (statement != statement_) return false;
241     switch (command) {
242       case CMD_BREAK:
243         control_builder_->Break();
244         return true;
245       case CMD_CONTINUE:
246       case CMD_RETURN:
247       case CMD_RETHROW:
248         break;
249     }
250     return false;
251   }
252 
253  private:
254   Statement* statement_;
255   BreakableControlFlowBuilder* control_builder_;
256 };
257 
258 // Scoped class for enabling 'break' and 'continue' in iteration
259 // constructs, e.g. do...while, while..., for...
260 class BytecodeGenerator::ControlScopeForIteration final
261     : public BytecodeGenerator::ControlScope {
262  public:
ControlScopeForIteration(BytecodeGenerator * generator,IterationStatement * statement,LoopBuilder * loop_builder)263   ControlScopeForIteration(BytecodeGenerator* generator,
264                            IterationStatement* statement,
265                            LoopBuilder* loop_builder)
266       : ControlScope(generator),
267         statement_(statement),
268         loop_builder_(loop_builder) {}
269 
270  protected:
Execute(Command command,Statement * statement)271   bool Execute(Command command, Statement* statement) override {
272     if (statement != statement_) return false;
273     switch (command) {
274       case CMD_BREAK:
275         loop_builder_->Break();
276         return true;
277       case CMD_CONTINUE:
278         loop_builder_->Continue();
279         return true;
280       case CMD_RETURN:
281       case CMD_RETHROW:
282         break;
283     }
284     return false;
285   }
286 
287  private:
288   Statement* statement_;
289   LoopBuilder* loop_builder_;
290 };
291 
292 // Scoped class for enabling 'throw' in try-catch constructs.
293 class BytecodeGenerator::ControlScopeForTryCatch final
294     : public BytecodeGenerator::ControlScope {
295  public:
ControlScopeForTryCatch(BytecodeGenerator * generator,TryCatchBuilder * try_catch_builder)296   ControlScopeForTryCatch(BytecodeGenerator* generator,
297                           TryCatchBuilder* try_catch_builder)
298       : ControlScope(generator) {
299     generator->try_catch_nesting_level_++;
300   }
~ControlScopeForTryCatch()301   virtual ~ControlScopeForTryCatch() {
302     generator()->try_catch_nesting_level_--;
303   }
304 
305  protected:
Execute(Command command,Statement * statement)306   bool Execute(Command command, Statement* statement) override {
307     switch (command) {
308       case CMD_BREAK:
309       case CMD_CONTINUE:
310       case CMD_RETURN:
311         break;
312       case CMD_RETHROW:
313         generator()->builder()->ReThrow();
314         return true;
315     }
316     return false;
317   }
318 };
319 
320 // Scoped class for enabling control flow through try-finally constructs.
321 class BytecodeGenerator::ControlScopeForTryFinally final
322     : public BytecodeGenerator::ControlScope {
323  public:
ControlScopeForTryFinally(BytecodeGenerator * generator,TryFinallyBuilder * try_finally_builder,DeferredCommands * commands)324   ControlScopeForTryFinally(BytecodeGenerator* generator,
325                             TryFinallyBuilder* try_finally_builder,
326                             DeferredCommands* commands)
327       : ControlScope(generator),
328         try_finally_builder_(try_finally_builder),
329         commands_(commands) {
330     generator->try_finally_nesting_level_++;
331   }
~ControlScopeForTryFinally()332   virtual ~ControlScopeForTryFinally() {
333     generator()->try_finally_nesting_level_--;
334   }
335 
336  protected:
Execute(Command command,Statement * statement)337   bool Execute(Command command, Statement* statement) override {
338     switch (command) {
339       case CMD_BREAK:
340       case CMD_CONTINUE:
341       case CMD_RETURN:
342       case CMD_RETHROW:
343         commands_->RecordCommand(command, statement);
344         try_finally_builder_->LeaveTry();
345         return true;
346     }
347     return false;
348   }
349 
350  private:
351   TryFinallyBuilder* try_finally_builder_;
352   DeferredCommands* commands_;
353 };
354 
PerformCommand(Command command,Statement * statement)355 void BytecodeGenerator::ControlScope::PerformCommand(Command command,
356                                                      Statement* statement) {
357   ControlScope* current = this;
358   ContextScope* context = generator()->execution_context();
359   // Pop context to the expected depth but do not pop the outermost context.
360   if (context != current->context() && context->ShouldPopContext()) {
361     generator()->builder()->PopContext(current->context()->reg());
362   }
363   do {
364     if (current->Execute(command, statement)) {
365       return;
366     }
367     current = current->outer();
368     if (current->context() != context) {
369       // Pop context to the expected depth.
370       // TODO(rmcilroy): Only emit a single context pop.
371       generator()->builder()->PopContext(current->context()->reg());
372     }
373   } while (current != nullptr);
374   UNREACHABLE();
375 }
376 
377 class BytecodeGenerator::RegisterAllocationScope {
378  public:
RegisterAllocationScope(BytecodeGenerator * generator)379   explicit RegisterAllocationScope(BytecodeGenerator* generator)
380       : generator_(generator),
381         outer_(generator->register_allocator()),
382         allocator_(builder()->zone(),
383                    builder()->temporary_register_allocator()) {
384     generator_->set_register_allocator(this);
385   }
386 
~RegisterAllocationScope()387   virtual ~RegisterAllocationScope() {
388     generator_->set_register_allocator(outer_);
389   }
390 
NewRegister()391   Register NewRegister() {
392     RegisterAllocationScope* current_scope = generator()->register_allocator();
393     if ((current_scope == this) ||
394         (current_scope->outer() == this &&
395          !current_scope->allocator_.HasConsecutiveAllocations())) {
396       // Regular case - Allocating registers in current or outer context.
397       // VisitForRegisterValue allocates register in outer context.
398       return allocator_.NewRegister();
399     } else {
400       // If it is required to allocate a register other than current or outer
401       // scopes, allocate a new temporary register. It might be expensive to
402       // walk the full context chain and compute the list of consecutive
403       // reservations in the innerscopes.
404       UNIMPLEMENTED();
405       return Register::invalid_value();
406     }
407   }
408 
PrepareForConsecutiveAllocations(int count)409   void PrepareForConsecutiveAllocations(int count) {
410     allocator_.PrepareForConsecutiveAllocations(count);
411   }
412 
NextConsecutiveRegister()413   Register NextConsecutiveRegister() {
414     return allocator_.NextConsecutiveRegister();
415   }
416 
RegisterIsAllocatedInThisScope(Register reg) const417   bool RegisterIsAllocatedInThisScope(Register reg) const {
418     return allocator_.RegisterIsAllocatedInThisScope(reg);
419   }
420 
outer() const421   RegisterAllocationScope* outer() const { return outer_; }
422 
423  private:
generator() const424   BytecodeGenerator* generator() const { return generator_; }
builder() const425   BytecodeArrayBuilder* builder() const { return generator_->builder(); }
426 
427   BytecodeGenerator* generator_;
428   RegisterAllocationScope* outer_;
429   BytecodeRegisterAllocator allocator_;
430 
431   DISALLOW_COPY_AND_ASSIGN(RegisterAllocationScope);
432 };
433 
434 // Scoped base class for determining where the result of an expression
435 // is stored.
436 class BytecodeGenerator::ExpressionResultScope {
437  public:
ExpressionResultScope(BytecodeGenerator * generator,Expression::Context kind)438   ExpressionResultScope(BytecodeGenerator* generator, Expression::Context kind)
439       : generator_(generator),
440         kind_(kind),
441         outer_(generator->execution_result()),
442         allocator_(generator),
443         result_identified_(false) {
444     generator_->set_execution_result(this);
445   }
446 
~ExpressionResultScope()447   virtual ~ExpressionResultScope() {
448     generator_->set_execution_result(outer_);
449     DCHECK(result_identified() || generator_->HasStackOverflow());
450   }
451 
IsEffect() const452   bool IsEffect() const { return kind_ == Expression::kEffect; }
IsValue() const453   bool IsValue() const { return kind_ == Expression::kValue; }
454 
455   virtual void SetResultInAccumulator() = 0;
456   virtual void SetResultInRegister(Register reg) = 0;
457 
458  protected:
outer() const459   ExpressionResultScope* outer() const { return outer_; }
builder() const460   BytecodeArrayBuilder* builder() const { return generator_->builder(); }
generator() const461   BytecodeGenerator* generator() const { return generator_; }
allocator() const462   const RegisterAllocationScope* allocator() const { return &allocator_; }
463 
set_result_identified()464   void set_result_identified() {
465     DCHECK(!result_identified());
466     result_identified_ = true;
467   }
468 
result_identified() const469   bool result_identified() const { return result_identified_; }
470 
471  private:
472   BytecodeGenerator* generator_;
473   Expression::Context kind_;
474   ExpressionResultScope* outer_;
475   RegisterAllocationScope allocator_;
476   bool result_identified_;
477 
478   DISALLOW_COPY_AND_ASSIGN(ExpressionResultScope);
479 };
480 
481 // Scoped class used when the result of the current expression is not
482 // expected to produce a result.
483 class BytecodeGenerator::EffectResultScope final
484     : public ExpressionResultScope {
485  public:
EffectResultScope(BytecodeGenerator * generator)486   explicit EffectResultScope(BytecodeGenerator* generator)
487       : ExpressionResultScope(generator, Expression::kEffect) {
488     set_result_identified();
489   }
490 
SetResultInAccumulator()491   virtual void SetResultInAccumulator() {}
SetResultInRegister(Register reg)492   virtual void SetResultInRegister(Register reg) {}
493 };
494 
495 // Scoped class used when the result of the current expression to be
496 // evaluated should go into the interpreter's accumulator register.
497 class BytecodeGenerator::AccumulatorResultScope final
498     : public ExpressionResultScope {
499  public:
AccumulatorResultScope(BytecodeGenerator * generator)500   explicit AccumulatorResultScope(BytecodeGenerator* generator)
501       : ExpressionResultScope(generator, Expression::kValue) {}
502 
SetResultInAccumulator()503   virtual void SetResultInAccumulator() { set_result_identified(); }
504 
SetResultInRegister(Register reg)505   virtual void SetResultInRegister(Register reg) {
506     builder()->LoadAccumulatorWithRegister(reg);
507     set_result_identified();
508   }
509 };
510 
511 // Scoped class used when the result of the current expression to be
512 // evaluated should go into an interpreter register.
513 class BytecodeGenerator::RegisterResultScope final
514     : public ExpressionResultScope {
515  public:
RegisterResultScope(BytecodeGenerator * generator)516   explicit RegisterResultScope(BytecodeGenerator* generator)
517       : ExpressionResultScope(generator, Expression::kValue) {}
518 
SetResultInAccumulator()519   virtual void SetResultInAccumulator() {
520     result_register_ = allocator()->outer()->NewRegister();
521     builder()->StoreAccumulatorInRegister(result_register_);
522     set_result_identified();
523   }
524 
SetResultInRegister(Register reg)525   virtual void SetResultInRegister(Register reg) {
526     DCHECK(builder()->RegisterIsParameterOrLocal(reg) ||
527            (builder()->TemporaryRegisterIsLive(reg) &&
528             !allocator()->RegisterIsAllocatedInThisScope(reg)));
529     result_register_ = reg;
530     set_result_identified();
531   }
532 
ResultRegister()533   Register ResultRegister() {
534     if (generator()->HasStackOverflow() && !result_identified()) {
535       SetResultInAccumulator();
536     }
537     return result_register_;
538   }
539 
540  private:
541   Register result_register_;
542 };
543 
BytecodeGenerator(CompilationInfo * info)544 BytecodeGenerator::BytecodeGenerator(CompilationInfo* info)
545     : isolate_(info->isolate()),
546       zone_(info->zone()),
547       builder_(new (zone()) BytecodeArrayBuilder(
548           info->isolate(), info->zone(), info->num_parameters_including_this(),
549           info->scope()->MaxNestedContextChainLength(),
550           info->scope()->num_stack_slots(), info->literal())),
551       info_(info),
552       scope_(info->scope()),
553       globals_(0, info->zone()),
554       execution_control_(nullptr),
555       execution_context_(nullptr),
556       execution_result_(nullptr),
557       register_allocator_(nullptr),
558       generator_resume_points_(info->literal()->yield_count(), info->zone()),
559       generator_state_(),
560       try_catch_nesting_level_(0),
561       try_finally_nesting_level_(0) {
562   InitializeAstVisitor(isolate());
563 }
564 
MakeBytecode()565 Handle<BytecodeArray> BytecodeGenerator::MakeBytecode() {
566   // Initialize the incoming context.
567   ContextScope incoming_context(this, scope(), false);
568 
569   // Initialize control scope.
570   ControlScopeForTopLevel control(this);
571 
572   RegisterAllocationScope register_scope(this);
573 
574   if (IsResumableFunction(info()->literal()->kind())) {
575     generator_state_ = register_allocator()->NewRegister();
576     VisitGeneratorPrologue();
577   }
578 
579   // Build function context only if there are context allocated variables.
580   if (scope()->NeedsContext()) {
581     // Push a new inner context scope for the function.
582     VisitNewLocalFunctionContext();
583     ContextScope local_function_context(this, scope(), false);
584     VisitBuildLocalActivationContext();
585     MakeBytecodeBody();
586   } else {
587     MakeBytecodeBody();
588   }
589 
590   // In generator functions, we may not have visited every yield in the AST
591   // since we skip some obviously dead code. Hence the generated bytecode may
592   // contain jumps to unbound labels (resume points that will never be used).
593   // We bind these now.
594   for (auto& label : generator_resume_points_) {
595     if (!label.is_bound()) builder()->Bind(&label);
596   }
597 
598   builder()->EnsureReturn();
599   return builder()->ToBytecodeArray();
600 }
601 
MakeBytecodeBody()602 void BytecodeGenerator::MakeBytecodeBody() {
603   // Build the arguments object if it is used.
604   VisitArgumentsObject(scope()->arguments());
605 
606   // Build rest arguments array if it is used.
607   int rest_index;
608   Variable* rest_parameter = scope()->rest_parameter(&rest_index);
609   VisitRestArgumentsArray(rest_parameter);
610 
611   // Build assignment to {.this_function} variable if it is used.
612   VisitThisFunctionVariable(scope()->this_function_var());
613 
614   // Build assignment to {new.target} variable if it is used.
615   VisitNewTargetVariable(scope()->new_target_var());
616 
617   // TODO(rmcilroy): Emit tracing call if requested to do so.
618   if (FLAG_trace) {
619     UNIMPLEMENTED();
620   }
621 
622   // Visit declarations within the function scope.
623   VisitDeclarations(scope()->declarations());
624 
625   // Perform a stack-check before the body.
626   builder()->StackCheck(info()->literal()->start_position());
627 
628   // Visit statements in the function body.
629   VisitStatements(info()->literal()->body());
630 }
631 
BuildIndexedJump(Register index,size_t start_index,size_t size,ZoneVector<BytecodeLabel> & targets)632 void BytecodeGenerator::BuildIndexedJump(Register index, size_t start_index,
633                                          size_t size,
634                                          ZoneVector<BytecodeLabel>& targets) {
635   // TODO(neis): Optimize this by using a proper jump table.
636   for (size_t i = start_index; i < start_index + size; i++) {
637     DCHECK(0 <= i && i < targets.size());
638     builder()
639         ->LoadLiteral(Smi::FromInt(static_cast<int>(i)))
640         .CompareOperation(Token::Value::EQ_STRICT, index)
641         .JumpIfTrue(&(targets[i]));
642   }
643 
644   BuildAbort(BailoutReason::kInvalidJumpTableIndex);
645 }
646 
VisitIterationHeader(IterationStatement * stmt,LoopBuilder * loop_builder)647 void BytecodeGenerator::VisitIterationHeader(IterationStatement* stmt,
648                                              LoopBuilder* loop_builder) {
649   // Recall that stmt->yield_count() is always zero inside ordinary
650   // (i.e. non-generator) functions.
651 
652   // Collect all labels for generator resume points within the loop (if any) so
653   // that they can be bound to the loop header below. Also create fresh labels
654   // for these resume points, to be used inside the loop.
655   ZoneVector<BytecodeLabel> resume_points_in_loop(zone());
656   size_t first_yield = stmt->first_yield_id();
657   for (size_t id = first_yield; id < first_yield + stmt->yield_count(); id++) {
658     DCHECK(0 <= id && id < generator_resume_points_.size());
659     auto& label = generator_resume_points_[id];
660     resume_points_in_loop.push_back(label);
661     generator_resume_points_[id] = BytecodeLabel();
662   }
663 
664   loop_builder->LoopHeader(&resume_points_in_loop);
665 
666   if (stmt->yield_count() > 0) {
667     // If we are not resuming, fall through to loop body.
668     // If we are resuming, perform state dispatch.
669     BytecodeLabel not_resuming;
670     builder()
671         ->LoadLiteral(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting))
672         .CompareOperation(Token::Value::EQ, generator_state_)
673         .JumpIfTrue(&not_resuming);
674     BuildIndexedJump(generator_state_, first_yield,
675         stmt->yield_count(), generator_resume_points_);
676     builder()->Bind(&not_resuming);
677   }
678 }
679 
VisitGeneratorPrologue()680 void BytecodeGenerator::VisitGeneratorPrologue() {
681   // The generator resume trampoline abuses the new.target register both to
682   // indicate that this is a resume call and to pass in the generator object.
683   // In ordinary calls, new.target is always undefined because generator
684   // functions are non-constructable.
685   Register generator_object = Register::new_target();
686   BytecodeLabel regular_call;
687   builder()
688       ->LoadAccumulatorWithRegister(generator_object)
689       .JumpIfUndefined(&regular_call);
690 
691   // This is a resume call. Restore registers and perform state dispatch.
692   // (The current context has already been restored by the trampoline.)
693   builder()
694       ->ResumeGenerator(generator_object)
695       .StoreAccumulatorInRegister(generator_state_);
696   BuildIndexedJump(generator_state_, 0, generator_resume_points_.size(),
697                    generator_resume_points_);
698 
699   builder()
700       ->Bind(&regular_call)
701       .LoadLiteral(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting))
702       .StoreAccumulatorInRegister(generator_state_);
703   // This is a regular call. Fall through to the ordinary function prologue,
704   // after which we will run into the generator object creation and other extra
705   // code inserted by the parser.
706 }
707 
VisitBlock(Block * stmt)708 void BytecodeGenerator::VisitBlock(Block* stmt) {
709   // Visit declarations and statements.
710   if (stmt->scope() != nullptr && stmt->scope()->NeedsContext()) {
711     VisitNewLocalBlockContext(stmt->scope());
712     ContextScope scope(this, stmt->scope());
713     VisitBlockDeclarationsAndStatements(stmt);
714   } else {
715     VisitBlockDeclarationsAndStatements(stmt);
716   }
717 }
718 
VisitBlockDeclarationsAndStatements(Block * stmt)719 void BytecodeGenerator::VisitBlockDeclarationsAndStatements(Block* stmt) {
720   BlockBuilder block_builder(builder());
721   ControlScopeForBreakable execution_control(this, stmt, &block_builder);
722   if (stmt->scope() != nullptr) {
723     VisitDeclarations(stmt->scope()->declarations());
724   }
725   VisitStatements(stmt->statements());
726   if (stmt->labels() != nullptr) block_builder.EndBlock();
727 }
728 
VisitVariableDeclaration(VariableDeclaration * decl)729 void BytecodeGenerator::VisitVariableDeclaration(VariableDeclaration* decl) {
730   Variable* variable = decl->proxy()->var();
731   VariableMode mode = decl->mode();
732   // Const and let variables are initialized with the hole so that we can
733   // check that they are only assigned once.
734   bool hole_init = mode == CONST || mode == LET;
735   switch (variable->location()) {
736     case VariableLocation::GLOBAL:
737     case VariableLocation::UNALLOCATED:
738       DCHECK(!variable->binding_needs_init());
739       globals()->push_back(variable->name());
740       globals()->push_back(isolate()->factory()->undefined_value());
741       break;
742     case VariableLocation::LOCAL:
743       if (hole_init) {
744         Register destination(variable->index());
745         builder()->LoadTheHole().StoreAccumulatorInRegister(destination);
746       }
747       break;
748     case VariableLocation::PARAMETER:
749       if (hole_init) {
750         // The parameter indices are shifted by 1 (receiver is variable
751         // index -1 but is parameter index 0 in BytecodeArrayBuilder).
752         Register destination(builder()->Parameter(variable->index() + 1));
753         builder()->LoadTheHole().StoreAccumulatorInRegister(destination);
754       }
755       break;
756     case VariableLocation::CONTEXT:
757       if (hole_init) {
758         builder()->LoadTheHole().StoreContextSlot(execution_context()->reg(),
759                                                   variable->index());
760       }
761       break;
762     case VariableLocation::LOOKUP: {
763       DCHECK_EQ(VAR, mode);
764       DCHECK(!hole_init);
765 
766       Register name = register_allocator()->NewRegister();
767 
768       builder()
769           ->LoadLiteral(variable->name())
770           .StoreAccumulatorInRegister(name)
771           .CallRuntime(Runtime::kDeclareEvalVar, name, 1);
772       break;
773     }
774   }
775 }
776 
VisitFunctionDeclaration(FunctionDeclaration * decl)777 void BytecodeGenerator::VisitFunctionDeclaration(FunctionDeclaration* decl) {
778   Variable* variable = decl->proxy()->var();
779   switch (variable->location()) {
780     case VariableLocation::GLOBAL:
781     case VariableLocation::UNALLOCATED: {
782       Handle<SharedFunctionInfo> function = Compiler::GetSharedFunctionInfo(
783           decl->fun(), info()->script(), info());
784       // Check for stack-overflow exception.
785       if (function.is_null()) return SetStackOverflow();
786       globals()->push_back(variable->name());
787       globals()->push_back(function);
788       break;
789     }
790     case VariableLocation::PARAMETER:
791     case VariableLocation::LOCAL: {
792       VisitForAccumulatorValue(decl->fun());
793       DCHECK(variable->mode() == LET || variable->mode() == VAR ||
794              variable->mode() == CONST);
795       VisitVariableAssignment(variable, Token::INIT,
796                               FeedbackVectorSlot::Invalid());
797       break;
798     }
799     case VariableLocation::CONTEXT: {
800       DCHECK_EQ(0, execution_context()->ContextChainDepth(variable->scope()));
801       VisitForAccumulatorValue(decl->fun());
802       builder()->StoreContextSlot(execution_context()->reg(),
803                                   variable->index());
804       break;
805     }
806     case VariableLocation::LOOKUP: {
807       register_allocator()->PrepareForConsecutiveAllocations(2);
808       Register name = register_allocator()->NextConsecutiveRegister();
809       Register literal = register_allocator()->NextConsecutiveRegister();
810       builder()->LoadLiteral(variable->name()).StoreAccumulatorInRegister(name);
811 
812       VisitForAccumulatorValue(decl->fun());
813       builder()->StoreAccumulatorInRegister(literal).CallRuntime(
814           Runtime::kDeclareEvalFunction, name, 2);
815     }
816   }
817 }
818 
VisitImportDeclaration(ImportDeclaration * decl)819 void BytecodeGenerator::VisitImportDeclaration(ImportDeclaration* decl) {
820   UNIMPLEMENTED();
821 }
822 
VisitExportDeclaration(ExportDeclaration * decl)823 void BytecodeGenerator::VisitExportDeclaration(ExportDeclaration* decl) {
824   UNIMPLEMENTED();
825 }
826 
VisitDeclarations(ZoneList<Declaration * > * declarations)827 void BytecodeGenerator::VisitDeclarations(
828     ZoneList<Declaration*>* declarations) {
829   RegisterAllocationScope register_scope(this);
830   DCHECK(globals()->empty());
831   for (int i = 0; i < declarations->length(); i++) {
832     RegisterAllocationScope register_scope(this);
833     Visit(declarations->at(i));
834   }
835   if (globals()->empty()) return;
836   int array_index = 0;
837   Handle<FixedArray> data = isolate()->factory()->NewFixedArray(
838       static_cast<int>(globals()->size()), TENURED);
839   for (Handle<Object> obj : *globals()) data->set(array_index++, *obj);
840   int encoded_flags = info()->GetDeclareGlobalsFlags();
841 
842   Register pairs = register_allocator()->NewRegister();
843   builder()->LoadLiteral(data);
844   builder()->StoreAccumulatorInRegister(pairs);
845 
846   Register flags = register_allocator()->NewRegister();
847   builder()->LoadLiteral(Smi::FromInt(encoded_flags));
848   builder()->StoreAccumulatorInRegister(flags);
849   DCHECK(flags.index() == pairs.index() + 1);
850 
851   builder()->CallRuntime(Runtime::kDeclareGlobals, pairs, 2);
852   globals()->clear();
853 }
854 
VisitStatements(ZoneList<Statement * > * statements)855 void BytecodeGenerator::VisitStatements(ZoneList<Statement*>* statements) {
856   for (int i = 0; i < statements->length(); i++) {
857     // Allocate an outer register allocations scope for the statement.
858     RegisterAllocationScope allocation_scope(this);
859     Statement* stmt = statements->at(i);
860     Visit(stmt);
861     if (stmt->IsJump()) break;
862   }
863 }
864 
VisitExpressionStatement(ExpressionStatement * stmt)865 void BytecodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) {
866   builder()->SetStatementPosition(stmt);
867   VisitForEffect(stmt->expression());
868 }
869 
VisitEmptyStatement(EmptyStatement * stmt)870 void BytecodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) {
871 }
872 
VisitIfStatement(IfStatement * stmt)873 void BytecodeGenerator::VisitIfStatement(IfStatement* stmt) {
874   builder()->SetStatementPosition(stmt);
875   BytecodeLabel else_label, end_label;
876   if (stmt->condition()->ToBooleanIsTrue()) {
877     // Generate then block unconditionally as always true.
878     Visit(stmt->then_statement());
879   } else if (stmt->condition()->ToBooleanIsFalse()) {
880     // Generate else block unconditionally if it exists.
881     if (stmt->HasElseStatement()) {
882       Visit(stmt->else_statement());
883     }
884   } else {
885     // TODO(oth): If then statement is BreakStatement or
886     // ContinueStatement we can reduce number of generated
887     // jump/jump_ifs here. See BasicLoops test.
888     VisitForAccumulatorValue(stmt->condition());
889     builder()->JumpIfFalse(&else_label);
890     Visit(stmt->then_statement());
891     if (stmt->HasElseStatement()) {
892       builder()->Jump(&end_label);
893       builder()->Bind(&else_label);
894       Visit(stmt->else_statement());
895     } else {
896       builder()->Bind(&else_label);
897     }
898     builder()->Bind(&end_label);
899   }
900 }
901 
VisitSloppyBlockFunctionStatement(SloppyBlockFunctionStatement * stmt)902 void BytecodeGenerator::VisitSloppyBlockFunctionStatement(
903     SloppyBlockFunctionStatement* stmt) {
904   Visit(stmt->statement());
905 }
906 
VisitContinueStatement(ContinueStatement * stmt)907 void BytecodeGenerator::VisitContinueStatement(ContinueStatement* stmt) {
908   builder()->SetStatementPosition(stmt);
909   execution_control()->Continue(stmt->target());
910 }
911 
VisitBreakStatement(BreakStatement * stmt)912 void BytecodeGenerator::VisitBreakStatement(BreakStatement* stmt) {
913   builder()->SetStatementPosition(stmt);
914   execution_control()->Break(stmt->target());
915 }
916 
VisitReturnStatement(ReturnStatement * stmt)917 void BytecodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
918   builder()->SetStatementPosition(stmt);
919   VisitForAccumulatorValue(stmt->expression());
920   execution_control()->ReturnAccumulator();
921 }
922 
VisitWithStatement(WithStatement * stmt)923 void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) {
924   builder()->SetStatementPosition(stmt);
925   VisitForAccumulatorValue(stmt->expression());
926   builder()->CastAccumulatorToJSObject();
927   VisitNewLocalWithContext();
928   VisitInScope(stmt->statement(), stmt->scope());
929 }
930 
VisitSwitchStatement(SwitchStatement * stmt)931 void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
932   // We need this scope because we visit for register values. We have to
933   // maintain a execution result scope where registers can be allocated.
934   ZoneList<CaseClause*>* clauses = stmt->cases();
935   SwitchBuilder switch_builder(builder(), clauses->length());
936   ControlScopeForBreakable scope(this, stmt, &switch_builder);
937   int default_index = -1;
938 
939   builder()->SetStatementPosition(stmt);
940 
941   // Keep the switch value in a register until a case matches.
942   Register tag = VisitForRegisterValue(stmt->tag());
943 
944   // Iterate over all cases and create nodes for label comparison.
945   BytecodeLabel done_label;
946   for (int i = 0; i < clauses->length(); i++) {
947     CaseClause* clause = clauses->at(i);
948 
949     // The default is not a test, remember index.
950     if (clause->is_default()) {
951       default_index = i;
952       continue;
953     }
954 
955     // Perform label comparison as if via '===' with tag.
956     VisitForAccumulatorValue(clause->label());
957     builder()->CompareOperation(Token::Value::EQ_STRICT, tag);
958     switch_builder.Case(i);
959   }
960 
961   if (default_index >= 0) {
962     // Emit default jump if there is a default case.
963     switch_builder.DefaultAt(default_index);
964   } else {
965     // Otherwise if we have reached here none of the cases matched, so jump to
966     // done.
967     builder()->Jump(&done_label);
968   }
969 
970   // Iterate over all cases and create the case bodies.
971   for (int i = 0; i < clauses->length(); i++) {
972     CaseClause* clause = clauses->at(i);
973     switch_builder.SetCaseTarget(i);
974     VisitStatements(clause->statements());
975   }
976   builder()->Bind(&done_label);
977 
978   switch_builder.SetBreakTarget(done_label);
979 }
980 
VisitCaseClause(CaseClause * clause)981 void BytecodeGenerator::VisitCaseClause(CaseClause* clause) {
982   // Handled entirely in VisitSwitchStatement.
983   UNREACHABLE();
984 }
985 
VisitIterationBody(IterationStatement * stmt,LoopBuilder * loop_builder)986 void BytecodeGenerator::VisitIterationBody(IterationStatement* stmt,
987                                            LoopBuilder* loop_builder) {
988   ControlScopeForIteration execution_control(this, stmt, loop_builder);
989   builder()->StackCheck(stmt->position());
990   Visit(stmt->body());
991   loop_builder->SetContinueTarget();
992 }
993 
VisitDoWhileStatement(DoWhileStatement * stmt)994 void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
995   LoopBuilder loop_builder(builder());
996   VisitIterationHeader(stmt, &loop_builder);
997   if (stmt->cond()->ToBooleanIsFalse()) {
998     VisitIterationBody(stmt, &loop_builder);
999   } else if (stmt->cond()->ToBooleanIsTrue()) {
1000     VisitIterationBody(stmt, &loop_builder);
1001     loop_builder.JumpToHeader();
1002   } else {
1003     VisitIterationBody(stmt, &loop_builder);
1004     builder()->SetExpressionAsStatementPosition(stmt->cond());
1005     VisitForAccumulatorValue(stmt->cond());
1006     loop_builder.JumpToHeaderIfTrue();
1007   }
1008   loop_builder.EndLoop();
1009 }
1010 
VisitWhileStatement(WhileStatement * stmt)1011 void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
1012   if (stmt->cond()->ToBooleanIsFalse()) {
1013     // If the condition is false there is no need to generate the loop.
1014     return;
1015   }
1016 
1017   LoopBuilder loop_builder(builder());
1018   VisitIterationHeader(stmt, &loop_builder);
1019   if (!stmt->cond()->ToBooleanIsTrue()) {
1020     builder()->SetExpressionAsStatementPosition(stmt->cond());
1021     VisitForAccumulatorValue(stmt->cond());
1022     loop_builder.BreakIfFalse();
1023   }
1024   VisitIterationBody(stmt, &loop_builder);
1025   loop_builder.JumpToHeader();
1026   loop_builder.EndLoop();
1027 }
1028 
VisitForStatement(ForStatement * stmt)1029 void BytecodeGenerator::VisitForStatement(ForStatement* stmt) {
1030   if (stmt->init() != nullptr) {
1031     Visit(stmt->init());
1032   }
1033   if (stmt->cond() && stmt->cond()->ToBooleanIsFalse()) {
1034     // If the condition is known to be false there is no need to generate
1035     // body, next or condition blocks. Init block should be generated.
1036     return;
1037   }
1038 
1039   LoopBuilder loop_builder(builder());
1040   VisitIterationHeader(stmt, &loop_builder);
1041   if (stmt->cond() && !stmt->cond()->ToBooleanIsTrue()) {
1042     builder()->SetExpressionAsStatementPosition(stmt->cond());
1043     VisitForAccumulatorValue(stmt->cond());
1044     loop_builder.BreakIfFalse();
1045   }
1046   VisitIterationBody(stmt, &loop_builder);
1047   if (stmt->next() != nullptr) {
1048     builder()->SetStatementPosition(stmt->next());
1049     Visit(stmt->next());
1050   }
1051   loop_builder.JumpToHeader();
1052   loop_builder.EndLoop();
1053 }
1054 
VisitForInAssignment(Expression * expr,FeedbackVectorSlot slot)1055 void BytecodeGenerator::VisitForInAssignment(Expression* expr,
1056                                              FeedbackVectorSlot slot) {
1057   DCHECK(expr->IsValidReferenceExpression());
1058 
1059   // Evaluate assignment starting with the value to be stored in the
1060   // accumulator.
1061   Property* property = expr->AsProperty();
1062   LhsKind assign_type = Property::GetAssignType(property);
1063   switch (assign_type) {
1064     case VARIABLE: {
1065       Variable* variable = expr->AsVariableProxy()->var();
1066       VisitVariableAssignment(variable, Token::ASSIGN, slot);
1067       break;
1068     }
1069     case NAMED_PROPERTY: {
1070       RegisterAllocationScope register_scope(this);
1071       Register value = register_allocator()->NewRegister();
1072       builder()->StoreAccumulatorInRegister(value);
1073       Register object = VisitForRegisterValue(property->obj());
1074       Handle<String> name = property->key()->AsLiteral()->AsPropertyName();
1075       builder()->LoadAccumulatorWithRegister(value);
1076       builder()->StoreNamedProperty(object, name, feedback_index(slot),
1077                                     language_mode());
1078       break;
1079     }
1080     case KEYED_PROPERTY: {
1081       RegisterAllocationScope register_scope(this);
1082       Register value = register_allocator()->NewRegister();
1083       builder()->StoreAccumulatorInRegister(value);
1084       Register object = VisitForRegisterValue(property->obj());
1085       Register key = VisitForRegisterValue(property->key());
1086       builder()->LoadAccumulatorWithRegister(value);
1087       builder()->StoreKeyedProperty(object, key, feedback_index(slot),
1088                                     language_mode());
1089       break;
1090     }
1091     case NAMED_SUPER_PROPERTY: {
1092       RegisterAllocationScope register_scope(this);
1093       register_allocator()->PrepareForConsecutiveAllocations(4);
1094       Register receiver = register_allocator()->NextConsecutiveRegister();
1095       Register home_object = register_allocator()->NextConsecutiveRegister();
1096       Register name = register_allocator()->NextConsecutiveRegister();
1097       Register value = register_allocator()->NextConsecutiveRegister();
1098       builder()->StoreAccumulatorInRegister(value);
1099       SuperPropertyReference* super_property =
1100           property->obj()->AsSuperPropertyReference();
1101       VisitForRegisterValue(super_property->this_var(), receiver);
1102       VisitForRegisterValue(super_property->home_object(), home_object);
1103       builder()
1104           ->LoadLiteral(property->key()->AsLiteral()->AsPropertyName())
1105           .StoreAccumulatorInRegister(name);
1106       BuildNamedSuperPropertyStore(receiver, home_object, name, value);
1107       break;
1108     }
1109     case KEYED_SUPER_PROPERTY: {
1110       RegisterAllocationScope register_scope(this);
1111       register_allocator()->PrepareForConsecutiveAllocations(4);
1112       Register receiver = register_allocator()->NextConsecutiveRegister();
1113       Register home_object = register_allocator()->NextConsecutiveRegister();
1114       Register key = register_allocator()->NextConsecutiveRegister();
1115       Register value = register_allocator()->NextConsecutiveRegister();
1116       builder()->StoreAccumulatorInRegister(value);
1117       SuperPropertyReference* super_property =
1118           property->obj()->AsSuperPropertyReference();
1119       VisitForRegisterValue(super_property->this_var(), receiver);
1120       VisitForRegisterValue(super_property->home_object(), home_object);
1121       VisitForRegisterValue(property->key(), key);
1122       BuildKeyedSuperPropertyStore(receiver, home_object, key, value);
1123       break;
1124     }
1125   }
1126 }
1127 
VisitForInStatement(ForInStatement * stmt)1128 void BytecodeGenerator::VisitForInStatement(ForInStatement* stmt) {
1129   if (stmt->subject()->IsNullLiteral() ||
1130       stmt->subject()->IsUndefinedLiteral()) {
1131     // ForIn generates lots of code, skip if it wouldn't produce any effects.
1132     return;
1133   }
1134 
1135   LoopBuilder loop_builder(builder());
1136   BytecodeLabel subject_null_label, subject_undefined_label;
1137 
1138   // Prepare the state for executing ForIn.
1139   builder()->SetExpressionAsStatementPosition(stmt->subject());
1140   VisitForAccumulatorValue(stmt->subject());
1141   builder()->JumpIfUndefined(&subject_undefined_label);
1142   builder()->JumpIfNull(&subject_null_label);
1143   Register receiver = register_allocator()->NewRegister();
1144   builder()->CastAccumulatorToJSObject();
1145   builder()->StoreAccumulatorInRegister(receiver);
1146 
1147   register_allocator()->PrepareForConsecutiveAllocations(3);
1148   Register cache_type = register_allocator()->NextConsecutiveRegister();
1149   Register cache_array = register_allocator()->NextConsecutiveRegister();
1150   Register cache_length = register_allocator()->NextConsecutiveRegister();
1151   // Used as kRegTriple and kRegPair in ForInPrepare and ForInNext.
1152   USE(cache_array);
1153   builder()->ForInPrepare(cache_type);
1154 
1155   // Set up loop counter
1156   Register index = register_allocator()->NewRegister();
1157   builder()->LoadLiteral(Smi::FromInt(0));
1158   builder()->StoreAccumulatorInRegister(index);
1159 
1160   // The loop
1161   VisitIterationHeader(stmt, &loop_builder);
1162   builder()->SetExpressionAsStatementPosition(stmt->each());
1163   builder()->ForInDone(index, cache_length);
1164   loop_builder.BreakIfTrue();
1165   DCHECK(Register::AreContiguous(cache_type, cache_array));
1166   FeedbackVectorSlot slot = stmt->ForInFeedbackSlot();
1167   builder()->ForInNext(receiver, index, cache_type, feedback_index(slot));
1168   loop_builder.ContinueIfUndefined();
1169   VisitForInAssignment(stmt->each(), stmt->EachFeedbackSlot());
1170   VisitIterationBody(stmt, &loop_builder);
1171   builder()->ForInStep(index);
1172   builder()->StoreAccumulatorInRegister(index);
1173   loop_builder.JumpToHeader();
1174   loop_builder.EndLoop();
1175   builder()->Bind(&subject_null_label);
1176   builder()->Bind(&subject_undefined_label);
1177 }
1178 
VisitForOfStatement(ForOfStatement * stmt)1179 void BytecodeGenerator::VisitForOfStatement(ForOfStatement* stmt) {
1180   LoopBuilder loop_builder(builder());
1181   ControlScopeForIteration control_scope(this, stmt, &loop_builder);
1182 
1183   builder()->SetExpressionAsStatementPosition(stmt->assign_iterator());
1184   VisitForEffect(stmt->assign_iterator());
1185 
1186   VisitIterationHeader(stmt, &loop_builder);
1187   builder()->SetExpressionAsStatementPosition(stmt->next_result());
1188   VisitForEffect(stmt->next_result());
1189   VisitForAccumulatorValue(stmt->result_done());
1190   loop_builder.BreakIfTrue();
1191 
1192   VisitForEffect(stmt->assign_each());
1193   VisitIterationBody(stmt, &loop_builder);
1194   loop_builder.JumpToHeader();
1195   loop_builder.EndLoop();
1196 }
1197 
VisitTryCatchStatement(TryCatchStatement * stmt)1198 void BytecodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) {
1199   TryCatchBuilder try_control_builder(builder());
1200   Register no_reg;
1201 
1202   // Preserve the context in a dedicated register, so that it can be restored
1203   // when the handler is entered by the stack-unwinding machinery.
1204   // TODO(mstarzinger): Be smarter about register allocation.
1205   Register context = register_allocator()->NewRegister();
1206   builder()->MoveRegister(Register::current_context(), context);
1207 
1208   // Evaluate the try-block inside a control scope. This simulates a handler
1209   // that is intercepting 'throw' control commands.
1210   try_control_builder.BeginTry(context);
1211   {
1212     ControlScopeForTryCatch scope(this, &try_control_builder);
1213     Visit(stmt->try_block());
1214   }
1215   try_control_builder.EndTry();
1216 
1217   // Create a catch scope that binds the exception.
1218   VisitNewLocalCatchContext(stmt->variable());
1219   builder()->StoreAccumulatorInRegister(context);
1220 
1221   // If requested, clear message object as we enter the catch block.
1222   if (stmt->clear_pending_message()) {
1223     builder()->CallRuntime(Runtime::kInterpreterClearPendingMessage, no_reg, 0);
1224   }
1225 
1226   // Load the catch context into the accumulator.
1227   builder()->LoadAccumulatorWithRegister(context);
1228 
1229   // Evaluate the catch-block.
1230   VisitInScope(stmt->catch_block(), stmt->scope());
1231   try_control_builder.EndCatch();
1232 }
1233 
VisitTryFinallyStatement(TryFinallyStatement * stmt)1234 void BytecodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
1235   TryFinallyBuilder try_control_builder(builder(), IsInsideTryCatch());
1236   Register no_reg;
1237 
1238   // We keep a record of all paths that enter the finally-block to be able to
1239   // dispatch to the correct continuation point after the statements in the
1240   // finally-block have been evaluated.
1241   //
1242   // The try-finally construct can enter the finally-block in three ways:
1243   // 1. By exiting the try-block normally, falling through at the end.
1244   // 2. By exiting the try-block with a function-local control flow transfer
1245   //    (i.e. through break/continue/return statements).
1246   // 3. By exiting the try-block with a thrown exception.
1247   //
1248   // The result register semantics depend on how the block was entered:
1249   //  - ReturnStatement: It represents the return value being returned.
1250   //  - ThrowStatement: It represents the exception being thrown.
1251   //  - BreakStatement/ContinueStatement: Undefined and not used.
1252   //  - Falling through into finally-block: Undefined and not used.
1253   Register token = register_allocator()->NewRegister();
1254   Register result = register_allocator()->NewRegister();
1255   ControlScope::DeferredCommands commands(this, token, result);
1256 
1257   // Preserve the context in a dedicated register, so that it can be restored
1258   // when the handler is entered by the stack-unwinding machinery.
1259   // TODO(mstarzinger): Be smarter about register allocation.
1260   Register context = register_allocator()->NewRegister();
1261   builder()->MoveRegister(Register::current_context(), context);
1262 
1263   // Evaluate the try-block inside a control scope. This simulates a handler
1264   // that is intercepting all control commands.
1265   try_control_builder.BeginTry(context);
1266   {
1267     ControlScopeForTryFinally scope(this, &try_control_builder, &commands);
1268     Visit(stmt->try_block());
1269   }
1270   try_control_builder.EndTry();
1271 
1272   // Record fall-through and exception cases.
1273   commands.RecordFallThroughPath();
1274   try_control_builder.LeaveTry();
1275   try_control_builder.BeginHandler();
1276   commands.RecordHandlerReThrowPath();
1277 
1278   // Pending message object is saved on entry.
1279   try_control_builder.BeginFinally();
1280   Register message = context;  // Reuse register.
1281 
1282   // Clear message object as we enter the finally block.
1283   builder()
1284       ->CallRuntime(Runtime::kInterpreterClearPendingMessage, no_reg, 0)
1285       .StoreAccumulatorInRegister(message);
1286 
1287   // Evaluate the finally-block.
1288   Visit(stmt->finally_block());
1289   try_control_builder.EndFinally();
1290 
1291   // Pending message object is restored on exit.
1292   builder()->CallRuntime(Runtime::kInterpreterSetPendingMessage, message, 1);
1293 
1294   // Dynamic dispatch after the finally-block.
1295   commands.ApplyDeferredCommands();
1296 }
1297 
VisitDebuggerStatement(DebuggerStatement * stmt)1298 void BytecodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) {
1299   builder()->SetStatementPosition(stmt);
1300   builder()->Debugger();
1301 }
1302 
VisitFunctionLiteral(FunctionLiteral * expr)1303 void BytecodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
1304   // Find or build a shared function info.
1305   Handle<SharedFunctionInfo> shared_info =
1306       Compiler::GetSharedFunctionInfo(expr, info()->script(), info());
1307   if (shared_info.is_null()) {
1308     return SetStackOverflow();
1309   }
1310   builder()->CreateClosure(shared_info,
1311                            expr->pretenure() ? TENURED : NOT_TENURED);
1312   execution_result()->SetResultInAccumulator();
1313 }
1314 
VisitClassLiteral(ClassLiteral * expr)1315 void BytecodeGenerator::VisitClassLiteral(ClassLiteral* expr) {
1316   if (expr->scope()->ContextLocalCount() > 0) {
1317     VisitNewLocalBlockContext(expr->scope());
1318     ContextScope scope(this, expr->scope());
1319     VisitDeclarations(expr->scope()->declarations());
1320     VisitClassLiteralContents(expr);
1321   } else {
1322     VisitDeclarations(expr->scope()->declarations());
1323     VisitClassLiteralContents(expr);
1324   }
1325 }
1326 
VisitClassLiteralContents(ClassLiteral * expr)1327 void BytecodeGenerator::VisitClassLiteralContents(ClassLiteral* expr) {
1328   VisitClassLiteralForRuntimeDefinition(expr);
1329 
1330   // Load the "prototype" from the constructor.
1331   register_allocator()->PrepareForConsecutiveAllocations(2);
1332   Register literal = register_allocator()->NextConsecutiveRegister();
1333   Register prototype = register_allocator()->NextConsecutiveRegister();
1334   Handle<String> name = isolate()->factory()->prototype_string();
1335   FeedbackVectorSlot slot = expr->PrototypeSlot();
1336   builder()
1337       ->StoreAccumulatorInRegister(literal)
1338       .LoadNamedProperty(literal, name, feedback_index(slot))
1339       .StoreAccumulatorInRegister(prototype);
1340 
1341   VisitClassLiteralProperties(expr, literal, prototype);
1342   builder()->CallRuntime(Runtime::kToFastProperties, literal, 1);
1343   // Assign to class variable.
1344   if (expr->class_variable_proxy() != nullptr) {
1345     Variable* var = expr->class_variable_proxy()->var();
1346     FeedbackVectorSlot slot = expr->NeedsProxySlot()
1347                                   ? expr->ProxySlot()
1348                                   : FeedbackVectorSlot::Invalid();
1349     VisitVariableAssignment(var, Token::INIT, slot);
1350   }
1351   execution_result()->SetResultInAccumulator();
1352 }
1353 
VisitClassLiteralForRuntimeDefinition(ClassLiteral * expr)1354 void BytecodeGenerator::VisitClassLiteralForRuntimeDefinition(
1355     ClassLiteral* expr) {
1356   AccumulatorResultScope result_scope(this);
1357   register_allocator()->PrepareForConsecutiveAllocations(4);
1358   Register extends = register_allocator()->NextConsecutiveRegister();
1359   Register constructor = register_allocator()->NextConsecutiveRegister();
1360   Register start_position = register_allocator()->NextConsecutiveRegister();
1361   Register end_position = register_allocator()->NextConsecutiveRegister();
1362 
1363   VisitForAccumulatorValueOrTheHole(expr->extends());
1364   builder()->StoreAccumulatorInRegister(extends);
1365 
1366   VisitForAccumulatorValue(expr->constructor());
1367   builder()
1368       ->StoreAccumulatorInRegister(constructor)
1369       .LoadLiteral(Smi::FromInt(expr->start_position()))
1370       .StoreAccumulatorInRegister(start_position)
1371       .LoadLiteral(Smi::FromInt(expr->end_position()))
1372       .StoreAccumulatorInRegister(end_position)
1373       .CallRuntime(Runtime::kDefineClass, extends, 4);
1374   result_scope.SetResultInAccumulator();
1375 }
1376 
VisitClassLiteralProperties(ClassLiteral * expr,Register literal,Register prototype)1377 void BytecodeGenerator::VisitClassLiteralProperties(ClassLiteral* expr,
1378                                                     Register literal,
1379                                                     Register prototype) {
1380   RegisterAllocationScope register_scope(this);
1381   register_allocator()->PrepareForConsecutiveAllocations(5);
1382   Register receiver = register_allocator()->NextConsecutiveRegister();
1383   Register key = register_allocator()->NextConsecutiveRegister();
1384   Register value = register_allocator()->NextConsecutiveRegister();
1385   Register attr = register_allocator()->NextConsecutiveRegister();
1386   Register set_function_name = register_allocator()->NextConsecutiveRegister();
1387 
1388   bool attr_assigned = false;
1389   Register old_receiver = Register::invalid_value();
1390 
1391   // Create nodes to store method values into the literal.
1392   for (int i = 0; i < expr->properties()->length(); i++) {
1393     ObjectLiteral::Property* property = expr->properties()->at(i);
1394 
1395     // Set-up receiver.
1396     Register new_receiver = property->is_static() ? literal : prototype;
1397     if (new_receiver != old_receiver) {
1398       builder()->MoveRegister(new_receiver, receiver);
1399       old_receiver = new_receiver;
1400     }
1401 
1402     VisitForAccumulatorValue(property->key());
1403     builder()->CastAccumulatorToName().StoreAccumulatorInRegister(key);
1404     // The static prototype property is read only. We handle the non computed
1405     // property name case in the parser. Since this is the only case where we
1406     // need to check for an own read only property we special case this so we do
1407     // not need to do this for every property.
1408     if (property->is_static() && property->is_computed_name()) {
1409       VisitClassLiteralStaticPrototypeWithComputedName(key);
1410     }
1411     VisitForAccumulatorValue(property->value());
1412     builder()->StoreAccumulatorInRegister(value);
1413 
1414     VisitSetHomeObject(value, receiver, property);
1415 
1416     if (!attr_assigned) {
1417       builder()
1418           ->LoadLiteral(Smi::FromInt(DONT_ENUM))
1419           .StoreAccumulatorInRegister(attr);
1420       attr_assigned = true;
1421     }
1422 
1423     switch (property->kind()) {
1424       case ObjectLiteral::Property::CONSTANT:
1425       case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1426       case ObjectLiteral::Property::PROTOTYPE:
1427         // Invalid properties for ES6 classes.
1428         UNREACHABLE();
1429         break;
1430       case ObjectLiteral::Property::COMPUTED: {
1431         builder()
1432             ->LoadLiteral(Smi::FromInt(property->NeedsSetFunctionName()))
1433             .StoreAccumulatorInRegister(set_function_name);
1434         builder()->CallRuntime(Runtime::kDefineDataPropertyInLiteral, receiver,
1435                                5);
1436         break;
1437       }
1438       case ObjectLiteral::Property::GETTER: {
1439         builder()->CallRuntime(Runtime::kDefineGetterPropertyUnchecked,
1440                                receiver, 4);
1441         break;
1442       }
1443       case ObjectLiteral::Property::SETTER: {
1444         builder()->CallRuntime(Runtime::kDefineSetterPropertyUnchecked,
1445                                receiver, 4);
1446         break;
1447       }
1448     }
1449   }
1450 }
1451 
VisitClassLiteralStaticPrototypeWithComputedName(Register key)1452 void BytecodeGenerator::VisitClassLiteralStaticPrototypeWithComputedName(
1453     Register key) {
1454   BytecodeLabel done;
1455   builder()
1456       ->LoadLiteral(isolate()->factory()->prototype_string())
1457       .CompareOperation(Token::Value::EQ_STRICT, key)
1458       .JumpIfFalse(&done)
1459       .CallRuntime(Runtime::kThrowStaticPrototypeError, Register(0), 0)
1460       .Bind(&done);
1461 }
1462 
VisitNativeFunctionLiteral(NativeFunctionLiteral * expr)1463 void BytecodeGenerator::VisitNativeFunctionLiteral(
1464     NativeFunctionLiteral* expr) {
1465   // Find or build a shared function info for the native function template.
1466   Handle<SharedFunctionInfo> shared_info =
1467       Compiler::GetSharedFunctionInfoForNative(expr->extension(), expr->name());
1468   builder()->CreateClosure(shared_info, NOT_TENURED);
1469   execution_result()->SetResultInAccumulator();
1470 }
1471 
VisitDoExpression(DoExpression * expr)1472 void BytecodeGenerator::VisitDoExpression(DoExpression* expr) {
1473   VisitBlock(expr->block());
1474   VisitVariableProxy(expr->result());
1475 }
1476 
VisitConditional(Conditional * expr)1477 void BytecodeGenerator::VisitConditional(Conditional* expr) {
1478   // TODO(rmcilroy): Spot easy cases where there code would not need to
1479   // emit the then block or the else block, e.g. condition is
1480   // obviously true/1/false/0.
1481 
1482   BytecodeLabel else_label, end_label;
1483 
1484   VisitForAccumulatorValue(expr->condition());
1485   builder()->JumpIfFalse(&else_label);
1486 
1487   VisitForAccumulatorValue(expr->then_expression());
1488   builder()->Jump(&end_label);
1489 
1490   builder()->Bind(&else_label);
1491   VisitForAccumulatorValue(expr->else_expression());
1492   builder()->Bind(&end_label);
1493 
1494   execution_result()->SetResultInAccumulator();
1495 }
1496 
VisitLiteral(Literal * expr)1497 void BytecodeGenerator::VisitLiteral(Literal* expr) {
1498   if (!execution_result()->IsEffect()) {
1499     Handle<Object> value = expr->value();
1500     if (value->IsSmi()) {
1501       builder()->LoadLiteral(Smi::cast(*value));
1502     } else if (value->IsUndefined(isolate())) {
1503       builder()->LoadUndefined();
1504     } else if (value->IsTrue(isolate())) {
1505       builder()->LoadTrue();
1506     } else if (value->IsFalse(isolate())) {
1507       builder()->LoadFalse();
1508     } else if (value->IsNull(isolate())) {
1509       builder()->LoadNull();
1510     } else if (value->IsTheHole(isolate())) {
1511       builder()->LoadTheHole();
1512     } else {
1513       builder()->LoadLiteral(value);
1514     }
1515     execution_result()->SetResultInAccumulator();
1516   }
1517 }
1518 
VisitRegExpLiteral(RegExpLiteral * expr)1519 void BytecodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
1520   // Materialize a regular expression literal.
1521   builder()->CreateRegExpLiteral(expr->pattern(), expr->literal_index(),
1522                                  expr->flags());
1523   execution_result()->SetResultInAccumulator();
1524 }
1525 
VisitObjectLiteral(ObjectLiteral * expr)1526 void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
1527   // Copy the literal boilerplate.
1528   int fast_clone_properties_count = 0;
1529   if (FastCloneShallowObjectStub::IsSupported(expr)) {
1530     STATIC_ASSERT(
1531         FastCloneShallowObjectStub::kMaximumClonedProperties <=
1532         1 << CreateObjectLiteralFlags::FastClonePropertiesCountBits::kShift);
1533     fast_clone_properties_count =
1534         FastCloneShallowObjectStub::PropertiesCount(expr->properties_count());
1535   }
1536   uint8_t flags =
1537       CreateObjectLiteralFlags::FlagsBits::encode(expr->ComputeFlags()) |
1538       CreateObjectLiteralFlags::FastClonePropertiesCountBits::encode(
1539           fast_clone_properties_count);
1540   builder()->CreateObjectLiteral(expr->constant_properties(),
1541                                  expr->literal_index(), flags);
1542 
1543   // Allocate in the outer scope since this register is used to return the
1544   // expression's results to the caller.
1545   Register literal = register_allocator()->outer()->NewRegister();
1546   builder()->StoreAccumulatorInRegister(literal);
1547 
1548   // Store computed values into the literal.
1549   int property_index = 0;
1550   AccessorTable accessor_table(zone());
1551   for (; property_index < expr->properties()->length(); property_index++) {
1552     ObjectLiteral::Property* property = expr->properties()->at(property_index);
1553     if (property->is_computed_name()) break;
1554     if (property->IsCompileTimeValue()) continue;
1555 
1556     RegisterAllocationScope inner_register_scope(this);
1557     Literal* literal_key = property->key()->AsLiteral();
1558     switch (property->kind()) {
1559       case ObjectLiteral::Property::CONSTANT:
1560         UNREACHABLE();
1561       case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1562         DCHECK(!CompileTimeValue::IsCompileTimeValue(property->value()));
1563       // Fall through.
1564       case ObjectLiteral::Property::COMPUTED: {
1565         // It is safe to use [[Put]] here because the boilerplate already
1566         // contains computed properties with an uninitialized value.
1567         if (literal_key->value()->IsInternalizedString()) {
1568           if (property->emit_store()) {
1569             VisitForAccumulatorValue(property->value());
1570             if (FunctionLiteral::NeedsHomeObject(property->value())) {
1571               RegisterAllocationScope register_scope(this);
1572               Register value = register_allocator()->NewRegister();
1573               builder()->StoreAccumulatorInRegister(value);
1574               builder()->StoreNamedProperty(
1575                   literal, literal_key->AsPropertyName(),
1576                   feedback_index(property->GetSlot(0)), language_mode());
1577               VisitSetHomeObject(value, literal, property, 1);
1578             } else {
1579               builder()->StoreNamedProperty(
1580                   literal, literal_key->AsPropertyName(),
1581                   feedback_index(property->GetSlot(0)), language_mode());
1582             }
1583           } else {
1584             VisitForEffect(property->value());
1585           }
1586         } else {
1587           register_allocator()->PrepareForConsecutiveAllocations(4);
1588           Register literal_argument =
1589               register_allocator()->NextConsecutiveRegister();
1590           Register key = register_allocator()->NextConsecutiveRegister();
1591           Register value = register_allocator()->NextConsecutiveRegister();
1592           Register language = register_allocator()->NextConsecutiveRegister();
1593 
1594           builder()->MoveRegister(literal, literal_argument);
1595           VisitForAccumulatorValue(property->key());
1596           builder()->StoreAccumulatorInRegister(key);
1597           VisitForAccumulatorValue(property->value());
1598           builder()->StoreAccumulatorInRegister(value);
1599           if (property->emit_store()) {
1600             builder()
1601                 ->LoadLiteral(Smi::FromInt(SLOPPY))
1602                 .StoreAccumulatorInRegister(language)
1603                 .CallRuntime(Runtime::kSetProperty, literal_argument, 4);
1604             VisitSetHomeObject(value, literal, property);
1605           }
1606         }
1607         break;
1608       }
1609       case ObjectLiteral::Property::PROTOTYPE: {
1610         DCHECK(property->emit_store());
1611         register_allocator()->PrepareForConsecutiveAllocations(2);
1612         Register literal_argument =
1613             register_allocator()->NextConsecutiveRegister();
1614         Register value = register_allocator()->NextConsecutiveRegister();
1615 
1616         builder()->MoveRegister(literal, literal_argument);
1617         VisitForAccumulatorValue(property->value());
1618         builder()->StoreAccumulatorInRegister(value).CallRuntime(
1619             Runtime::kInternalSetPrototype, literal_argument, 2);
1620         break;
1621       }
1622       case ObjectLiteral::Property::GETTER:
1623         if (property->emit_store()) {
1624           accessor_table.lookup(literal_key)->second->getter = property;
1625         }
1626         break;
1627       case ObjectLiteral::Property::SETTER:
1628         if (property->emit_store()) {
1629           accessor_table.lookup(literal_key)->second->setter = property;
1630         }
1631         break;
1632     }
1633   }
1634 
1635   // Define accessors, using only a single call to the runtime for each pair of
1636   // corresponding getters and setters.
1637   for (AccessorTable::Iterator it = accessor_table.begin();
1638        it != accessor_table.end(); ++it) {
1639     RegisterAllocationScope inner_register_scope(this);
1640     register_allocator()->PrepareForConsecutiveAllocations(5);
1641     Register literal_argument = register_allocator()->NextConsecutiveRegister();
1642     Register name = register_allocator()->NextConsecutiveRegister();
1643     Register getter = register_allocator()->NextConsecutiveRegister();
1644     Register setter = register_allocator()->NextConsecutiveRegister();
1645     Register attr = register_allocator()->NextConsecutiveRegister();
1646 
1647     builder()->MoveRegister(literal, literal_argument);
1648     VisitForAccumulatorValue(it->first);
1649     builder()->StoreAccumulatorInRegister(name);
1650     VisitObjectLiteralAccessor(literal, it->second->getter, getter);
1651     VisitObjectLiteralAccessor(literal, it->second->setter, setter);
1652     builder()
1653         ->LoadLiteral(Smi::FromInt(NONE))
1654         .StoreAccumulatorInRegister(attr)
1655         .CallRuntime(Runtime::kDefineAccessorPropertyUnchecked,
1656                      literal_argument, 5);
1657   }
1658 
1659   // Object literals have two parts. The "static" part on the left contains no
1660   // computed property names, and so we can compute its map ahead of time; see
1661   // Runtime_CreateObjectLiteralBoilerplate. The second "dynamic" part starts
1662   // with the first computed property name and continues with all properties to
1663   // its right. All the code from above initializes the static component of the
1664   // object literal, and arranges for the map of the result to reflect the
1665   // static order in which the keys appear. For the dynamic properties, we
1666   // compile them into a series of "SetOwnProperty" runtime calls. This will
1667   // preserve insertion order.
1668   for (; property_index < expr->properties()->length(); property_index++) {
1669     ObjectLiteral::Property* property = expr->properties()->at(property_index);
1670     RegisterAllocationScope inner_register_scope(this);
1671 
1672     if (property->kind() == ObjectLiteral::Property::PROTOTYPE) {
1673       DCHECK(property->emit_store());
1674       register_allocator()->PrepareForConsecutiveAllocations(2);
1675       Register literal_argument =
1676           register_allocator()->NextConsecutiveRegister();
1677       Register value = register_allocator()->NextConsecutiveRegister();
1678 
1679       builder()->MoveRegister(literal, literal_argument);
1680       VisitForAccumulatorValue(property->value());
1681       builder()->StoreAccumulatorInRegister(value).CallRuntime(
1682           Runtime::kInternalSetPrototype, literal_argument, 2);
1683       continue;
1684     }
1685 
1686     register_allocator()->PrepareForConsecutiveAllocations(5);
1687     Register literal_argument = register_allocator()->NextConsecutiveRegister();
1688     Register key = register_allocator()->NextConsecutiveRegister();
1689     Register value = register_allocator()->NextConsecutiveRegister();
1690     Register attr = register_allocator()->NextConsecutiveRegister();
1691     DCHECK(Register::AreContiguous(literal_argument, key, value, attr));
1692     Register set_function_name =
1693         register_allocator()->NextConsecutiveRegister();
1694 
1695     builder()->MoveRegister(literal, literal_argument);
1696     VisitForAccumulatorValue(property->key());
1697     builder()->CastAccumulatorToName().StoreAccumulatorInRegister(key);
1698     VisitForAccumulatorValue(property->value());
1699     builder()->StoreAccumulatorInRegister(value);
1700     VisitSetHomeObject(value, literal, property);
1701     builder()->LoadLiteral(Smi::FromInt(NONE)).StoreAccumulatorInRegister(attr);
1702     switch (property->kind()) {
1703       case ObjectLiteral::Property::CONSTANT:
1704       case ObjectLiteral::Property::COMPUTED:
1705       case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1706         builder()
1707             ->LoadLiteral(Smi::FromInt(property->NeedsSetFunctionName()))
1708             .StoreAccumulatorInRegister(set_function_name);
1709         builder()->CallRuntime(Runtime::kDefineDataPropertyInLiteral,
1710                                literal_argument, 5);
1711         break;
1712       case ObjectLiteral::Property::PROTOTYPE:
1713         UNREACHABLE();  // Handled specially above.
1714         break;
1715       case ObjectLiteral::Property::GETTER:
1716         builder()->CallRuntime(Runtime::kDefineGetterPropertyUnchecked,
1717                                literal_argument, 4);
1718         break;
1719       case ObjectLiteral::Property::SETTER:
1720         builder()->CallRuntime(Runtime::kDefineSetterPropertyUnchecked,
1721                                literal_argument, 4);
1722         break;
1723     }
1724   }
1725 
1726   execution_result()->SetResultInRegister(literal);
1727 }
1728 
VisitArrayLiteral(ArrayLiteral * expr)1729 void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
1730   // Deep-copy the literal boilerplate.
1731   builder()->CreateArrayLiteral(expr->constant_elements(),
1732                                 expr->literal_index(),
1733                                 expr->ComputeFlags(true));
1734   Register index, literal;
1735 
1736   // Evaluate all the non-constant subexpressions and store them into the
1737   // newly cloned array.
1738   bool literal_in_accumulator = true;
1739   for (int array_index = 0; array_index < expr->values()->length();
1740        array_index++) {
1741     Expression* subexpr = expr->values()->at(array_index);
1742     if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
1743     DCHECK(!subexpr->IsSpread());
1744 
1745     if (literal_in_accumulator) {
1746       index = register_allocator()->NewRegister();
1747       literal = register_allocator()->NewRegister();
1748       builder()->StoreAccumulatorInRegister(literal);
1749       literal_in_accumulator = false;
1750     }
1751 
1752     FeedbackVectorSlot slot = expr->LiteralFeedbackSlot();
1753     builder()
1754         ->LoadLiteral(Smi::FromInt(array_index))
1755         .StoreAccumulatorInRegister(index);
1756     VisitForAccumulatorValue(subexpr);
1757     builder()->StoreKeyedProperty(literal, index, feedback_index(slot),
1758                                   language_mode());
1759   }
1760 
1761   if (!literal_in_accumulator) {
1762     // Restore literal array into accumulator.
1763     builder()->LoadAccumulatorWithRegister(literal);
1764   }
1765   execution_result()->SetResultInAccumulator();
1766 }
1767 
VisitVariableProxy(VariableProxy * proxy)1768 void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) {
1769   builder()->SetExpressionPosition(proxy);
1770   VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot());
1771 }
1772 
BuildHoleCheckForVariableLoad(VariableMode mode,Handle<String> name)1773 void BytecodeGenerator::BuildHoleCheckForVariableLoad(VariableMode mode,
1774                                                       Handle<String> name) {
1775   if (mode == LET || mode == CONST) {
1776     BuildThrowIfHole(name);
1777   }
1778 }
1779 
VisitVariableLoad(Variable * variable,FeedbackVectorSlot slot,TypeofMode typeof_mode)1780 void BytecodeGenerator::VisitVariableLoad(Variable* variable,
1781                                           FeedbackVectorSlot slot,
1782                                           TypeofMode typeof_mode) {
1783   VariableMode mode = variable->mode();
1784   switch (variable->location()) {
1785     case VariableLocation::LOCAL: {
1786       Register source(Register(variable->index()));
1787       builder()->LoadAccumulatorWithRegister(source);
1788       BuildHoleCheckForVariableLoad(mode, variable->name());
1789       execution_result()->SetResultInAccumulator();
1790       break;
1791     }
1792     case VariableLocation::PARAMETER: {
1793       // The parameter indices are shifted by 1 (receiver is variable
1794       // index -1 but is parameter index 0 in BytecodeArrayBuilder).
1795       Register source = builder()->Parameter(variable->index() + 1);
1796       builder()->LoadAccumulatorWithRegister(source);
1797       BuildHoleCheckForVariableLoad(mode, variable->name());
1798       execution_result()->SetResultInAccumulator();
1799       break;
1800     }
1801     case VariableLocation::GLOBAL:
1802     case VariableLocation::UNALLOCATED: {
1803       builder()->LoadGlobal(feedback_index(slot), typeof_mode);
1804       execution_result()->SetResultInAccumulator();
1805       break;
1806     }
1807     case VariableLocation::CONTEXT: {
1808       int depth = execution_context()->ContextChainDepth(variable->scope());
1809       ContextScope* context = execution_context()->Previous(depth);
1810       Register context_reg;
1811       if (context) {
1812         context_reg = context->reg();
1813       } else {
1814         context_reg = register_allocator()->NewRegister();
1815         // Walk the context chain to find the context at the given depth.
1816         // TODO(rmcilroy): Perform this work in a bytecode handler once we have
1817         // a generic mechanism for performing jumps in interpreter.cc.
1818         // TODO(mythria): Also update bytecode graph builder with correct depth
1819         // when this changes.
1820         builder()
1821             ->LoadAccumulatorWithRegister(execution_context()->reg())
1822             .StoreAccumulatorInRegister(context_reg);
1823         for (int i = 0; i < depth; ++i) {
1824           builder()
1825               ->LoadContextSlot(context_reg, Context::PREVIOUS_INDEX)
1826               .StoreAccumulatorInRegister(context_reg);
1827         }
1828       }
1829 
1830       builder()->LoadContextSlot(context_reg, variable->index());
1831       BuildHoleCheckForVariableLoad(mode, variable->name());
1832       execution_result()->SetResultInAccumulator();
1833       break;
1834     }
1835     case VariableLocation::LOOKUP: {
1836       builder()->LoadLookupSlot(variable->name(), typeof_mode);
1837       execution_result()->SetResultInAccumulator();
1838       break;
1839     }
1840   }
1841 }
1842 
VisitVariableLoadForAccumulatorValue(Variable * variable,FeedbackVectorSlot slot,TypeofMode typeof_mode)1843 void BytecodeGenerator::VisitVariableLoadForAccumulatorValue(
1844     Variable* variable, FeedbackVectorSlot slot, TypeofMode typeof_mode) {
1845   AccumulatorResultScope accumulator_result(this);
1846   VisitVariableLoad(variable, slot, typeof_mode);
1847 }
1848 
VisitVariableLoadForRegisterValue(Variable * variable,FeedbackVectorSlot slot,TypeofMode typeof_mode)1849 Register BytecodeGenerator::VisitVariableLoadForRegisterValue(
1850     Variable* variable, FeedbackVectorSlot slot, TypeofMode typeof_mode) {
1851   RegisterResultScope register_scope(this);
1852   VisitVariableLoad(variable, slot, typeof_mode);
1853   return register_scope.ResultRegister();
1854 }
1855 
BuildNamedSuperPropertyLoad(Register receiver,Register home_object,Register name)1856 void BytecodeGenerator::BuildNamedSuperPropertyLoad(Register receiver,
1857                                                     Register home_object,
1858                                                     Register name) {
1859   DCHECK(Register::AreContiguous(receiver, home_object, name));
1860   builder()->CallRuntime(Runtime::kLoadFromSuper, receiver, 3);
1861 }
1862 
BuildKeyedSuperPropertyLoad(Register receiver,Register home_object,Register key)1863 void BytecodeGenerator::BuildKeyedSuperPropertyLoad(Register receiver,
1864                                                     Register home_object,
1865                                                     Register key) {
1866   DCHECK(Register::AreContiguous(receiver, home_object, key));
1867   builder()->CallRuntime(Runtime::kLoadKeyedFromSuper, receiver, 3);
1868 }
1869 
BuildNamedSuperPropertyStore(Register receiver,Register home_object,Register name,Register value)1870 void BytecodeGenerator::BuildNamedSuperPropertyStore(Register receiver,
1871                                                      Register home_object,
1872                                                      Register name,
1873                                                      Register value) {
1874   DCHECK(Register::AreContiguous(receiver, home_object, name, value));
1875   Runtime::FunctionId function_id = is_strict(language_mode())
1876                                         ? Runtime::kStoreToSuper_Strict
1877                                         : Runtime::kStoreToSuper_Sloppy;
1878   builder()->CallRuntime(function_id, receiver, 4);
1879 }
1880 
BuildKeyedSuperPropertyStore(Register receiver,Register home_object,Register key,Register value)1881 void BytecodeGenerator::BuildKeyedSuperPropertyStore(Register receiver,
1882                                                      Register home_object,
1883                                                      Register key,
1884                                                      Register value) {
1885   DCHECK(Register::AreContiguous(receiver, home_object, key, value));
1886   Runtime::FunctionId function_id = is_strict(language_mode())
1887                                         ? Runtime::kStoreKeyedToSuper_Strict
1888                                         : Runtime::kStoreKeyedToSuper_Sloppy;
1889   builder()->CallRuntime(function_id, receiver, 4);
1890 }
1891 
BuildAbort(BailoutReason bailout_reason)1892 void BytecodeGenerator::BuildAbort(BailoutReason bailout_reason) {
1893   RegisterAllocationScope register_scope(this);
1894   Register reason = register_allocator()->NewRegister();
1895   builder()
1896       ->LoadLiteral(Smi::FromInt(static_cast<int>(bailout_reason)))
1897       .StoreAccumulatorInRegister(reason)
1898       .CallRuntime(Runtime::kAbort, reason, 1);
1899 }
1900 
BuildThrowReferenceError(Handle<String> name)1901 void BytecodeGenerator::BuildThrowReferenceError(Handle<String> name) {
1902   RegisterAllocationScope register_scope(this);
1903   Register name_reg = register_allocator()->NewRegister();
1904   builder()->LoadLiteral(name).StoreAccumulatorInRegister(name_reg).CallRuntime(
1905       Runtime::kThrowReferenceError, name_reg, 1);
1906 }
1907 
BuildThrowIfHole(Handle<String> name)1908 void BytecodeGenerator::BuildThrowIfHole(Handle<String> name) {
1909   // TODO(interpreter): Can the parser reduce the number of checks
1910   // performed? Or should there be a ThrowIfHole bytecode.
1911   BytecodeLabel no_reference_error;
1912   builder()->JumpIfNotHole(&no_reference_error);
1913   BuildThrowReferenceError(name);
1914   builder()->Bind(&no_reference_error);
1915 }
1916 
BuildThrowIfNotHole(Handle<String> name)1917 void BytecodeGenerator::BuildThrowIfNotHole(Handle<String> name) {
1918   // TODO(interpreter): Can the parser reduce the number of checks
1919   // performed? Or should there be a ThrowIfNotHole bytecode.
1920   BytecodeLabel no_reference_error, reference_error;
1921   builder()
1922       ->JumpIfNotHole(&reference_error)
1923       .Jump(&no_reference_error)
1924       .Bind(&reference_error);
1925   BuildThrowReferenceError(name);
1926   builder()->Bind(&no_reference_error);
1927 }
1928 
BuildThrowReassignConstant(Handle<String> name)1929 void BytecodeGenerator::BuildThrowReassignConstant(Handle<String> name) {
1930   // TODO(mythria): This will be replaced by a new bytecode that throws an
1931   // appropriate error depending on the whether the value is a hole or not.
1932   BytecodeLabel const_assign_error;
1933   builder()->JumpIfNotHole(&const_assign_error);
1934   BuildThrowReferenceError(name);
1935   builder()
1936       ->Bind(&const_assign_error)
1937       .CallRuntime(Runtime::kThrowConstAssignError, Register(), 0);
1938 }
1939 
BuildHoleCheckForVariableAssignment(Variable * variable,Token::Value op)1940 void BytecodeGenerator::BuildHoleCheckForVariableAssignment(Variable* variable,
1941                                                             Token::Value op) {
1942   VariableMode mode = variable->mode();
1943   DCHECK(mode != CONST_LEGACY);
1944   if (mode == CONST && op != Token::INIT) {
1945     // Non-intializing assignments to constant is not allowed.
1946     BuildThrowReassignConstant(variable->name());
1947   } else if (mode == LET && op != Token::INIT) {
1948     // Perform an initialization check for let declared variables.
1949     // E.g. let x = (x = 20); is not allowed.
1950     BuildThrowIfHole(variable->name());
1951   } else {
1952     DCHECK(variable->is_this() && mode == CONST && op == Token::INIT);
1953     // Perform an initialization check for 'this'. 'this' variable is the
1954     // only variable able to trigger bind operations outside the TDZ
1955     // via 'super' calls.
1956     BuildThrowIfNotHole(variable->name());
1957   }
1958 }
1959 
VisitVariableAssignment(Variable * variable,Token::Value op,FeedbackVectorSlot slot)1960 void BytecodeGenerator::VisitVariableAssignment(Variable* variable,
1961                                                 Token::Value op,
1962                                                 FeedbackVectorSlot slot) {
1963   VariableMode mode = variable->mode();
1964   RegisterAllocationScope assignment_register_scope(this);
1965   BytecodeLabel end_label;
1966   bool hole_check_required =
1967       (mode == LET && op != Token::INIT) ||
1968       (mode == CONST && op != Token::INIT) ||
1969       (mode == CONST && op == Token::INIT && variable->is_this());
1970   switch (variable->location()) {
1971     case VariableLocation::PARAMETER:
1972     case VariableLocation::LOCAL: {
1973       Register destination;
1974       if (VariableLocation::PARAMETER == variable->location()) {
1975         destination = Register(builder()->Parameter(variable->index() + 1));
1976       } else {
1977         destination = Register(variable->index());
1978       }
1979 
1980       if (mode == CONST_LEGACY && op != Token::INIT) {
1981         if (is_strict(language_mode())) {
1982           builder()->CallRuntime(Runtime::kThrowConstAssignError, Register(),
1983                                  0);
1984         }
1985         // Non-initializing assignments to legacy constants are ignored
1986         // in sloppy mode. Break here to avoid storing into variable.
1987         break;
1988       }
1989 
1990       if (hole_check_required) {
1991         // Load destination to check for hole.
1992         Register value_temp = register_allocator()->NewRegister();
1993         builder()
1994             ->StoreAccumulatorInRegister(value_temp)
1995             .LoadAccumulatorWithRegister(destination);
1996 
1997         BuildHoleCheckForVariableAssignment(variable, op);
1998         builder()->LoadAccumulatorWithRegister(value_temp);
1999       }
2000       builder()->StoreAccumulatorInRegister(destination);
2001       break;
2002     }
2003     case VariableLocation::GLOBAL:
2004     case VariableLocation::UNALLOCATED: {
2005       builder()->StoreGlobal(variable->name(), feedback_index(slot),
2006                              language_mode());
2007       break;
2008     }
2009     case VariableLocation::CONTEXT: {
2010       int depth = execution_context()->ContextChainDepth(variable->scope());
2011       ContextScope* context = execution_context()->Previous(depth);
2012       Register context_reg;
2013 
2014       if (context) {
2015         context_reg = context->reg();
2016       } else {
2017         Register value_temp = register_allocator()->NewRegister();
2018         context_reg = register_allocator()->NewRegister();
2019         // Walk the context chain to find the context at the given depth.
2020         // TODO(rmcilroy): Perform this work in a bytecode handler once we have
2021         // a generic mechanism for performing jumps in interpreter.cc.
2022         // TODO(mythria): Also update bytecode graph builder with correct depth
2023         // when this changes.
2024         builder()
2025             ->StoreAccumulatorInRegister(value_temp)
2026             .LoadAccumulatorWithRegister(execution_context()->reg())
2027             .StoreAccumulatorInRegister(context_reg);
2028         for (int i = 0; i < depth; ++i) {
2029           builder()
2030               ->LoadContextSlot(context_reg, Context::PREVIOUS_INDEX)
2031               .StoreAccumulatorInRegister(context_reg);
2032         }
2033         builder()->LoadAccumulatorWithRegister(value_temp);
2034       }
2035 
2036       if (mode == CONST_LEGACY && op != Token::INIT) {
2037         if (is_strict(language_mode())) {
2038           builder()->CallRuntime(Runtime::kThrowConstAssignError, Register(),
2039                                  0);
2040         }
2041         // Non-initializing assignments to legacy constants are ignored
2042         // in sloppy mode. Break here to avoid storing into variable.
2043         break;
2044       }
2045 
2046       if (hole_check_required) {
2047         // Load destination to check for hole.
2048         Register value_temp = register_allocator()->NewRegister();
2049         builder()
2050             ->StoreAccumulatorInRegister(value_temp)
2051             .LoadContextSlot(context_reg, variable->index());
2052 
2053         BuildHoleCheckForVariableAssignment(variable, op);
2054         builder()->LoadAccumulatorWithRegister(value_temp);
2055       }
2056 
2057       builder()->StoreContextSlot(context_reg, variable->index());
2058       break;
2059     }
2060     case VariableLocation::LOOKUP: {
2061       DCHECK_NE(CONST_LEGACY, variable->mode());
2062       builder()->StoreLookupSlot(variable->name(), language_mode());
2063       break;
2064     }
2065   }
2066 }
2067 
VisitAssignment(Assignment * expr)2068 void BytecodeGenerator::VisitAssignment(Assignment* expr) {
2069   DCHECK(expr->target()->IsValidReferenceExpressionOrThis());
2070   Register object, key, home_object, value;
2071   Handle<String> name;
2072 
2073   // Left-hand side can only be a property, a global or a variable slot.
2074   Property* property = expr->target()->AsProperty();
2075   LhsKind assign_type = Property::GetAssignType(property);
2076 
2077   // Evaluate LHS expression.
2078   switch (assign_type) {
2079     case VARIABLE:
2080       // Nothing to do to evaluate variable assignment LHS.
2081       break;
2082     case NAMED_PROPERTY: {
2083       object = VisitForRegisterValue(property->obj());
2084       name = property->key()->AsLiteral()->AsPropertyName();
2085       break;
2086     }
2087     case KEYED_PROPERTY: {
2088       object = VisitForRegisterValue(property->obj());
2089       if (expr->is_compound()) {
2090         // Use VisitForAccumulator and store to register so that the key is
2091         // still in the accumulator for loading the old value below.
2092         key = register_allocator()->NewRegister();
2093         VisitForAccumulatorValue(property->key());
2094         builder()->StoreAccumulatorInRegister(key);
2095       } else {
2096         key = VisitForRegisterValue(property->key());
2097       }
2098       break;
2099     }
2100     case NAMED_SUPER_PROPERTY: {
2101       register_allocator()->PrepareForConsecutiveAllocations(4);
2102       object = register_allocator()->NextConsecutiveRegister();
2103       home_object = register_allocator()->NextConsecutiveRegister();
2104       key = register_allocator()->NextConsecutiveRegister();
2105       value = register_allocator()->NextConsecutiveRegister();
2106       SuperPropertyReference* super_property =
2107           property->obj()->AsSuperPropertyReference();
2108       VisitForRegisterValue(super_property->this_var(), object);
2109       VisitForRegisterValue(super_property->home_object(), home_object);
2110       builder()
2111           ->LoadLiteral(property->key()->AsLiteral()->AsPropertyName())
2112           .StoreAccumulatorInRegister(key);
2113       break;
2114     }
2115     case KEYED_SUPER_PROPERTY: {
2116       register_allocator()->PrepareForConsecutiveAllocations(4);
2117       object = register_allocator()->NextConsecutiveRegister();
2118       home_object = register_allocator()->NextConsecutiveRegister();
2119       key = register_allocator()->NextConsecutiveRegister();
2120       value = register_allocator()->NextConsecutiveRegister();
2121       builder()->StoreAccumulatorInRegister(value);
2122       SuperPropertyReference* super_property =
2123           property->obj()->AsSuperPropertyReference();
2124       VisitForRegisterValue(super_property->this_var(), object);
2125       VisitForRegisterValue(super_property->home_object(), home_object);
2126       VisitForRegisterValue(property->key(), key);
2127       break;
2128     }
2129   }
2130 
2131   // Evaluate the value and potentially handle compound assignments by loading
2132   // the left-hand side value and performing a binary operation.
2133   if (expr->is_compound()) {
2134     Register old_value;
2135     switch (assign_type) {
2136       case VARIABLE: {
2137         VariableProxy* proxy = expr->target()->AsVariableProxy();
2138         old_value = VisitVariableLoadForRegisterValue(
2139             proxy->var(), proxy->VariableFeedbackSlot());
2140         break;
2141       }
2142       case NAMED_PROPERTY: {
2143         FeedbackVectorSlot slot = property->PropertyFeedbackSlot();
2144         old_value = register_allocator()->NewRegister();
2145         builder()
2146             ->LoadNamedProperty(object, name, feedback_index(slot))
2147             .StoreAccumulatorInRegister(old_value);
2148         break;
2149       }
2150       case KEYED_PROPERTY: {
2151         // Key is already in accumulator at this point due to evaluating the
2152         // LHS above.
2153         FeedbackVectorSlot slot = property->PropertyFeedbackSlot();
2154         old_value = register_allocator()->NewRegister();
2155         builder()
2156             ->LoadKeyedProperty(object, feedback_index(slot))
2157             .StoreAccumulatorInRegister(old_value);
2158         break;
2159       }
2160       case NAMED_SUPER_PROPERTY: {
2161         old_value = register_allocator()->NewRegister();
2162         BuildNamedSuperPropertyLoad(object, home_object, key);
2163         builder()->StoreAccumulatorInRegister(old_value);
2164         break;
2165       }
2166       case KEYED_SUPER_PROPERTY: {
2167         old_value = register_allocator()->NewRegister();
2168         BuildKeyedSuperPropertyLoad(object, home_object, key);
2169         builder()->StoreAccumulatorInRegister(old_value);
2170         break;
2171       }
2172     }
2173     VisitForAccumulatorValue(expr->value());
2174     builder()->BinaryOperation(expr->binary_op(), old_value);
2175   } else {
2176     VisitForAccumulatorValue(expr->value());
2177   }
2178 
2179   // Store the value.
2180   builder()->SetExpressionPosition(expr);
2181   FeedbackVectorSlot slot = expr->AssignmentSlot();
2182   switch (assign_type) {
2183     case VARIABLE: {
2184       // TODO(oth): The VisitVariableAssignment() call is hard to reason about.
2185       // Is the value in the accumulator safe? Yes, but scary.
2186       Variable* variable = expr->target()->AsVariableProxy()->var();
2187       VisitVariableAssignment(variable, expr->op(), slot);
2188       break;
2189     }
2190     case NAMED_PROPERTY:
2191       builder()->StoreNamedProperty(object, name, feedback_index(slot),
2192                                     language_mode());
2193       break;
2194     case KEYED_PROPERTY:
2195       builder()->StoreKeyedProperty(object, key, feedback_index(slot),
2196                                     language_mode());
2197       break;
2198     case NAMED_SUPER_PROPERTY: {
2199       builder()->StoreAccumulatorInRegister(value);
2200       BuildNamedSuperPropertyStore(object, home_object, key, value);
2201       break;
2202     }
2203     case KEYED_SUPER_PROPERTY: {
2204       builder()->StoreAccumulatorInRegister(value);
2205       BuildKeyedSuperPropertyStore(object, home_object, key, value);
2206       break;
2207     }
2208   }
2209   execution_result()->SetResultInAccumulator();
2210 }
2211 
VisitYield(Yield * expr)2212 void BytecodeGenerator::VisitYield(Yield* expr) {
2213   builder()->SetExpressionPosition(expr);
2214   Register value = VisitForRegisterValue(expr->expression());
2215 
2216   Register generator = VisitForRegisterValue(expr->generator_object());
2217 
2218   // Save context, registers, and state. Then return.
2219   builder()
2220       ->LoadLiteral(Smi::FromInt(expr->yield_id()))
2221       .SuspendGenerator(generator)
2222       .LoadAccumulatorWithRegister(value)
2223       .Return();  // Hard return (ignore any finally blocks).
2224 
2225   builder()->Bind(&(generator_resume_points_[expr->yield_id()]));
2226   // Upon resume, we continue here.
2227 
2228   {
2229     RegisterAllocationScope register_scope(this);
2230 
2231     // Update state to indicate that we have finished resuming. Loop headers
2232     // rely on this.
2233     builder()
2234         ->LoadLiteral(Smi::FromInt(JSGeneratorObject::kGeneratorExecuting))
2235         .StoreAccumulatorInRegister(generator_state_);
2236 
2237     Register input = register_allocator()->NewRegister();
2238     builder()
2239         ->CallRuntime(Runtime::kInlineGeneratorGetInputOrDebugPos, generator, 1)
2240         .StoreAccumulatorInRegister(input);
2241 
2242     Register resume_mode = register_allocator()->NewRegister();
2243     builder()
2244         ->CallRuntime(Runtime::kInlineGeneratorGetResumeMode, generator, 1)
2245         .StoreAccumulatorInRegister(resume_mode);
2246 
2247     // Now dispatch on resume mode.
2248 
2249     BytecodeLabel resume_with_next;
2250     BytecodeLabel resume_with_return;
2251     BytecodeLabel resume_with_throw;
2252 
2253     builder()
2254         ->LoadLiteral(Smi::FromInt(JSGeneratorObject::kNext))
2255         .CompareOperation(Token::EQ_STRICT, resume_mode)
2256         .JumpIfTrue(&resume_with_next)
2257         .LoadLiteral(Smi::FromInt(JSGeneratorObject::kThrow))
2258         .CompareOperation(Token::EQ_STRICT, resume_mode)
2259         .JumpIfTrue(&resume_with_throw)
2260         .Jump(&resume_with_return);
2261 
2262     builder()->Bind(&resume_with_return);
2263     {
2264       register_allocator()->PrepareForConsecutiveAllocations(2);
2265       Register value = register_allocator()->NextConsecutiveRegister();
2266       Register done = register_allocator()->NextConsecutiveRegister();
2267       builder()
2268           ->MoveRegister(input, value)
2269           .LoadTrue()
2270           .StoreAccumulatorInRegister(done)
2271           .CallRuntime(Runtime::kInlineCreateIterResultObject, value, 2);
2272       execution_control()->ReturnAccumulator();
2273     }
2274 
2275     builder()->Bind(&resume_with_throw);
2276     builder()->SetExpressionPosition(expr);
2277     builder()->LoadAccumulatorWithRegister(input).Throw();
2278 
2279     builder()->Bind(&resume_with_next);
2280     builder()->LoadAccumulatorWithRegister(input);
2281   }
2282   execution_result()->SetResultInAccumulator();
2283 }
2284 
VisitThrow(Throw * expr)2285 void BytecodeGenerator::VisitThrow(Throw* expr) {
2286   VisitForAccumulatorValue(expr->exception());
2287   builder()->SetExpressionPosition(expr);
2288   builder()->Throw();
2289   // Throw statements are modeled as expressions instead of statements. These
2290   // are converted from assignment statements in Rewriter::ReWrite pass. An
2291   // assignment statement expects a value in the accumulator. This is a hack to
2292   // avoid DCHECK fails assert accumulator has been set.
2293   execution_result()->SetResultInAccumulator();
2294 }
2295 
VisitPropertyLoad(Register obj,Property * expr)2296 void BytecodeGenerator::VisitPropertyLoad(Register obj, Property* expr) {
2297   LhsKind property_kind = Property::GetAssignType(expr);
2298   FeedbackVectorSlot slot = expr->PropertyFeedbackSlot();
2299   builder()->SetExpressionPosition(expr);
2300   switch (property_kind) {
2301     case VARIABLE:
2302       UNREACHABLE();
2303     case NAMED_PROPERTY: {
2304       builder()->LoadNamedProperty(obj,
2305                                    expr->key()->AsLiteral()->AsPropertyName(),
2306                                    feedback_index(slot));
2307       break;
2308     }
2309     case KEYED_PROPERTY: {
2310       VisitForAccumulatorValue(expr->key());
2311       builder()->LoadKeyedProperty(obj, feedback_index(slot));
2312       break;
2313     }
2314     case NAMED_SUPER_PROPERTY:
2315       VisitNamedSuperPropertyLoad(expr, Register::invalid_value());
2316       break;
2317     case KEYED_SUPER_PROPERTY:
2318       VisitKeyedSuperPropertyLoad(expr, Register::invalid_value());
2319       break;
2320   }
2321   execution_result()->SetResultInAccumulator();
2322 }
2323 
VisitPropertyLoadForAccumulator(Register obj,Property * expr)2324 void BytecodeGenerator::VisitPropertyLoadForAccumulator(Register obj,
2325                                                         Property* expr) {
2326   AccumulatorResultScope result_scope(this);
2327   VisitPropertyLoad(obj, expr);
2328 }
2329 
VisitNamedSuperPropertyLoad(Property * property,Register opt_receiver_out)2330 void BytecodeGenerator::VisitNamedSuperPropertyLoad(Property* property,
2331                                                     Register opt_receiver_out) {
2332   RegisterAllocationScope register_scope(this);
2333   register_allocator()->PrepareForConsecutiveAllocations(3);
2334 
2335   Register receiver, home_object, name;
2336   receiver = register_allocator()->NextConsecutiveRegister();
2337   home_object = register_allocator()->NextConsecutiveRegister();
2338   name = register_allocator()->NextConsecutiveRegister();
2339   SuperPropertyReference* super_property =
2340       property->obj()->AsSuperPropertyReference();
2341   VisitForRegisterValue(super_property->this_var(), receiver);
2342   VisitForRegisterValue(super_property->home_object(), home_object);
2343   builder()
2344       ->LoadLiteral(property->key()->AsLiteral()->AsPropertyName())
2345       .StoreAccumulatorInRegister(name);
2346   BuildNamedSuperPropertyLoad(receiver, home_object, name);
2347 
2348   if (opt_receiver_out.is_valid()) {
2349     builder()->MoveRegister(receiver, opt_receiver_out);
2350   }
2351 }
2352 
VisitKeyedSuperPropertyLoad(Property * property,Register opt_receiver_out)2353 void BytecodeGenerator::VisitKeyedSuperPropertyLoad(Property* property,
2354                                                     Register opt_receiver_out) {
2355   RegisterAllocationScope register_scope(this);
2356   register_allocator()->PrepareForConsecutiveAllocations(3);
2357 
2358   Register receiver, home_object, key;
2359   receiver = register_allocator()->NextConsecutiveRegister();
2360   home_object = register_allocator()->NextConsecutiveRegister();
2361   key = register_allocator()->NextConsecutiveRegister();
2362   SuperPropertyReference* super_property =
2363       property->obj()->AsSuperPropertyReference();
2364   VisitForRegisterValue(super_property->this_var(), receiver);
2365   VisitForRegisterValue(super_property->home_object(), home_object);
2366   VisitForRegisterValue(property->key(), key);
2367   BuildKeyedSuperPropertyLoad(receiver, home_object, key);
2368 
2369   if (opt_receiver_out.is_valid()) {
2370     builder()->MoveRegister(receiver, opt_receiver_out);
2371   }
2372 }
2373 
VisitProperty(Property * expr)2374 void BytecodeGenerator::VisitProperty(Property* expr) {
2375   LhsKind property_kind = Property::GetAssignType(expr);
2376   if (property_kind != NAMED_SUPER_PROPERTY &&
2377       property_kind != KEYED_SUPER_PROPERTY) {
2378     Register obj = VisitForRegisterValue(expr->obj());
2379     VisitPropertyLoad(obj, expr);
2380   } else {
2381     VisitPropertyLoad(Register::invalid_value(), expr);
2382   }
2383 }
2384 
VisitArguments(ZoneList<Expression * > * args)2385 Register BytecodeGenerator::VisitArguments(ZoneList<Expression*>* args) {
2386   if (args->length() == 0) {
2387     return Register();
2388   }
2389 
2390   // Visit arguments and place in a contiguous block of temporary
2391   // registers.  Return the first temporary register corresponding to
2392   // the first argument.
2393   //
2394   // NB the caller may have already called
2395   // PrepareForConsecutiveAllocations() with args->length() + N. The
2396   // second call here will be a no-op provided there have been N or
2397   // less calls to NextConsecutiveRegister(). Otherwise, the arguments
2398   // here will be consecutive, but they will not be consecutive with
2399   // earlier consecutive allocations made by the caller.
2400   register_allocator()->PrepareForConsecutiveAllocations(args->length());
2401 
2402   // Visit for first argument that goes into returned register
2403   Register first_arg = register_allocator()->NextConsecutiveRegister();
2404   VisitForAccumulatorValue(args->at(0));
2405   builder()->StoreAccumulatorInRegister(first_arg);
2406 
2407   // Visit remaining arguments
2408   for (int i = 1; i < static_cast<int>(args->length()); i++) {
2409     Register ith_arg = register_allocator()->NextConsecutiveRegister();
2410     VisitForAccumulatorValue(args->at(i));
2411     builder()->StoreAccumulatorInRegister(ith_arg);
2412     DCHECK(ith_arg.index() - i == first_arg.index());
2413   }
2414   return first_arg;
2415 }
2416 
VisitCall(Call * expr)2417 void BytecodeGenerator::VisitCall(Call* expr) {
2418   Expression* callee_expr = expr->expression();
2419   Call::CallType call_type = expr->GetCallType(isolate());
2420 
2421   if (call_type == Call::SUPER_CALL) {
2422     return VisitCallSuper(expr);
2423   }
2424 
2425   // Prepare the callee and the receiver to the function call. This depends on
2426   // the semantics of the underlying call type.
2427 
2428   // The receiver and arguments need to be allocated consecutively for
2429   // Call(). We allocate the callee and receiver consecutively for calls to
2430   // %LoadLookupSlotForCall. Future optimizations could avoid this there are
2431   // no arguments or the receiver and arguments are already consecutive.
2432   ZoneList<Expression*>* args = expr->arguments();
2433   register_allocator()->PrepareForConsecutiveAllocations(args->length() + 2);
2434   Register callee = register_allocator()->NextConsecutiveRegister();
2435   Register receiver = register_allocator()->NextConsecutiveRegister();
2436 
2437   switch (call_type) {
2438     case Call::NAMED_PROPERTY_CALL:
2439     case Call::KEYED_PROPERTY_CALL: {
2440       Property* property = callee_expr->AsProperty();
2441       VisitForAccumulatorValue(property->obj());
2442       builder()->StoreAccumulatorInRegister(receiver);
2443       VisitPropertyLoadForAccumulator(receiver, property);
2444       builder()->StoreAccumulatorInRegister(callee);
2445       break;
2446     }
2447     case Call::GLOBAL_CALL: {
2448       // Receiver is undefined for global calls.
2449       builder()->LoadUndefined().StoreAccumulatorInRegister(receiver);
2450       // Load callee as a global variable.
2451       VariableProxy* proxy = callee_expr->AsVariableProxy();
2452       VisitVariableLoadForAccumulatorValue(proxy->var(),
2453                                            proxy->VariableFeedbackSlot());
2454       builder()->StoreAccumulatorInRegister(callee);
2455       break;
2456     }
2457     case Call::LOOKUP_SLOT_CALL:
2458     case Call::POSSIBLY_EVAL_CALL: {
2459       if (callee_expr->AsVariableProxy()->var()->IsLookupSlot()) {
2460         RegisterAllocationScope inner_register_scope(this);
2461         Register name = register_allocator()->NewRegister();
2462 
2463         // Call %LoadLookupSlotForCall to get the callee and receiver.
2464         DCHECK(Register::AreContiguous(callee, receiver));
2465         Variable* variable = callee_expr->AsVariableProxy()->var();
2466         builder()
2467             ->LoadLiteral(variable->name())
2468             .StoreAccumulatorInRegister(name)
2469             .CallRuntimeForPair(Runtime::kLoadLookupSlotForCall, name, 1,
2470                                 callee);
2471         break;
2472       }
2473       // Fall through.
2474       DCHECK_EQ(call_type, Call::POSSIBLY_EVAL_CALL);
2475     }
2476     case Call::OTHER_CALL: {
2477       builder()->LoadUndefined().StoreAccumulatorInRegister(receiver);
2478       VisitForAccumulatorValue(callee_expr);
2479       builder()->StoreAccumulatorInRegister(callee);
2480       break;
2481     }
2482     case Call::NAMED_SUPER_PROPERTY_CALL: {
2483       Property* property = callee_expr->AsProperty();
2484       VisitNamedSuperPropertyLoad(property, receiver);
2485       builder()->StoreAccumulatorInRegister(callee);
2486       break;
2487     }
2488     case Call::KEYED_SUPER_PROPERTY_CALL: {
2489       Property* property = callee_expr->AsProperty();
2490       VisitKeyedSuperPropertyLoad(property, receiver);
2491       builder()->StoreAccumulatorInRegister(callee);
2492       break;
2493     }
2494     case Call::SUPER_CALL:
2495       UNREACHABLE();
2496       break;
2497   }
2498 
2499   // Evaluate all arguments to the function call and store in sequential
2500   // registers.
2501   Register arg = VisitArguments(args);
2502   CHECK(args->length() == 0 || arg.index() == receiver.index() + 1);
2503 
2504   // Resolve callee for a potential direct eval call. This block will mutate the
2505   // callee value.
2506   if (call_type == Call::POSSIBLY_EVAL_CALL && args->length() > 0) {
2507     RegisterAllocationScope inner_register_scope(this);
2508     register_allocator()->PrepareForConsecutiveAllocations(6);
2509     Register callee_for_eval = register_allocator()->NextConsecutiveRegister();
2510     Register source = register_allocator()->NextConsecutiveRegister();
2511     Register function = register_allocator()->NextConsecutiveRegister();
2512     Register language = register_allocator()->NextConsecutiveRegister();
2513     Register eval_scope_position =
2514         register_allocator()->NextConsecutiveRegister();
2515     Register eval_position = register_allocator()->NextConsecutiveRegister();
2516 
2517     // Set up arguments for ResolvePossiblyDirectEval by copying callee, source
2518     // strings and function closure, and loading language and
2519     // position.
2520     builder()
2521         ->MoveRegister(callee, callee_for_eval)
2522         .MoveRegister(arg, source)
2523         .MoveRegister(Register::function_closure(), function)
2524         .LoadLiteral(Smi::FromInt(language_mode()))
2525         .StoreAccumulatorInRegister(language)
2526         .LoadLiteral(
2527             Smi::FromInt(execution_context()->scope()->start_position()))
2528         .StoreAccumulatorInRegister(eval_scope_position)
2529         .LoadLiteral(Smi::FromInt(expr->position()))
2530         .StoreAccumulatorInRegister(eval_position);
2531 
2532     // Call ResolvePossiblyDirectEval and modify the callee.
2533     builder()
2534         ->CallRuntime(Runtime::kResolvePossiblyDirectEval, callee_for_eval, 6)
2535         .StoreAccumulatorInRegister(callee);
2536   }
2537 
2538   builder()->SetExpressionPosition(expr);
2539   builder()->Call(callee, receiver, 1 + args->length(),
2540                   feedback_index(expr->CallFeedbackICSlot()),
2541                   expr->tail_call_mode());
2542   execution_result()->SetResultInAccumulator();
2543 }
2544 
VisitCallSuper(Call * expr)2545 void BytecodeGenerator::VisitCallSuper(Call* expr) {
2546   RegisterAllocationScope register_scope(this);
2547   SuperCallReference* super = expr->expression()->AsSuperCallReference();
2548 
2549   // Prepare the constructor to the super call.
2550   Register this_function = register_allocator()->NewRegister();
2551   VisitForAccumulatorValue(super->this_function_var());
2552   builder()
2553       ->StoreAccumulatorInRegister(this_function)
2554       .CallRuntime(Runtime::kInlineGetSuperConstructor, this_function, 1);
2555 
2556   Register constructor = this_function;  // Re-use dead this_function register.
2557   builder()->StoreAccumulatorInRegister(constructor);
2558 
2559   ZoneList<Expression*>* args = expr->arguments();
2560   Register first_arg = VisitArguments(args);
2561 
2562   // The new target is loaded into the accumulator from the
2563   // {new.target} variable.
2564   VisitForAccumulatorValue(super->new_target_var());
2565 
2566   // Call construct.
2567   builder()->SetExpressionPosition(expr);
2568   builder()->New(constructor, first_arg, args->length());
2569   execution_result()->SetResultInAccumulator();
2570 }
2571 
VisitCallNew(CallNew * expr)2572 void BytecodeGenerator::VisitCallNew(CallNew* expr) {
2573   Register constructor = register_allocator()->NewRegister();
2574   VisitForAccumulatorValue(expr->expression());
2575   builder()->StoreAccumulatorInRegister(constructor);
2576 
2577   ZoneList<Expression*>* args = expr->arguments();
2578   Register first_arg = VisitArguments(args);
2579 
2580   builder()->SetExpressionPosition(expr);
2581   // The accumulator holds new target which is the same as the
2582   // constructor for CallNew.
2583   builder()
2584       ->LoadAccumulatorWithRegister(constructor)
2585       .New(constructor, first_arg, args->length());
2586   execution_result()->SetResultInAccumulator();
2587 }
2588 
VisitCallRuntime(CallRuntime * expr)2589 void BytecodeGenerator::VisitCallRuntime(CallRuntime* expr) {
2590   ZoneList<Expression*>* args = expr->arguments();
2591   if (expr->is_jsruntime()) {
2592     // Allocate a register for the receiver and load it with undefined.
2593     register_allocator()->PrepareForConsecutiveAllocations(1 + args->length());
2594     Register receiver = register_allocator()->NextConsecutiveRegister();
2595     builder()->LoadUndefined().StoreAccumulatorInRegister(receiver);
2596     Register first_arg = VisitArguments(args);
2597     CHECK(args->length() == 0 || first_arg.index() == receiver.index() + 1);
2598     builder()->CallJSRuntime(expr->context_index(), receiver,
2599                              1 + args->length());
2600   } else {
2601     // Evaluate all arguments to the runtime call.
2602     Register first_arg = VisitArguments(args);
2603     Runtime::FunctionId function_id = expr->function()->function_id;
2604     builder()->CallRuntime(function_id, first_arg, args->length());
2605   }
2606   execution_result()->SetResultInAccumulator();
2607 }
2608 
VisitVoid(UnaryOperation * expr)2609 void BytecodeGenerator::VisitVoid(UnaryOperation* expr) {
2610   VisitForEffect(expr->expression());
2611   builder()->LoadUndefined();
2612   execution_result()->SetResultInAccumulator();
2613 }
2614 
VisitTypeOf(UnaryOperation * expr)2615 void BytecodeGenerator::VisitTypeOf(UnaryOperation* expr) {
2616   if (expr->expression()->IsVariableProxy()) {
2617     // Typeof does not throw a reference error on global variables, hence we
2618     // perform a non-contextual load in case the operand is a variable proxy.
2619     VariableProxy* proxy = expr->expression()->AsVariableProxy();
2620     VisitVariableLoadForAccumulatorValue(
2621         proxy->var(), proxy->VariableFeedbackSlot(), INSIDE_TYPEOF);
2622   } else {
2623     VisitForAccumulatorValue(expr->expression());
2624   }
2625   builder()->TypeOf();
2626   execution_result()->SetResultInAccumulator();
2627 }
2628 
VisitNot(UnaryOperation * expr)2629 void BytecodeGenerator::VisitNot(UnaryOperation* expr) {
2630   VisitForAccumulatorValue(expr->expression());
2631   builder()->LogicalNot();
2632   execution_result()->SetResultInAccumulator();
2633 }
2634 
VisitUnaryOperation(UnaryOperation * expr)2635 void BytecodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
2636   switch (expr->op()) {
2637     case Token::Value::NOT:
2638       VisitNot(expr);
2639       break;
2640     case Token::Value::TYPEOF:
2641       VisitTypeOf(expr);
2642       break;
2643     case Token::Value::VOID:
2644       VisitVoid(expr);
2645       break;
2646     case Token::Value::DELETE:
2647       VisitDelete(expr);
2648       break;
2649     case Token::Value::BIT_NOT:
2650     case Token::Value::ADD:
2651     case Token::Value::SUB:
2652       // These operators are converted to an equivalent binary operators in
2653       // the parser. These operators are not expected to be visited here.
2654       UNREACHABLE();
2655     default:
2656       UNREACHABLE();
2657   }
2658 }
2659 
VisitDelete(UnaryOperation * expr)2660 void BytecodeGenerator::VisitDelete(UnaryOperation* expr) {
2661   if (expr->expression()->IsProperty()) {
2662     // Delete of an object property is allowed both in sloppy
2663     // and strict modes.
2664     Property* property = expr->expression()->AsProperty();
2665     Register object = VisitForRegisterValue(property->obj());
2666     VisitForAccumulatorValue(property->key());
2667     builder()->Delete(object, language_mode());
2668   } else if (expr->expression()->IsVariableProxy()) {
2669     // Delete of an unqualified identifier is allowed in sloppy mode but is
2670     // not allowed in strict mode. Deleting 'this' is allowed in both modes.
2671     VariableProxy* proxy = expr->expression()->AsVariableProxy();
2672     Variable* variable = proxy->var();
2673     DCHECK(is_sloppy(language_mode()) || variable->HasThisName(isolate()));
2674     switch (variable->location()) {
2675       case VariableLocation::GLOBAL:
2676       case VariableLocation::UNALLOCATED: {
2677         // Global var, let, const or variables not explicitly declared.
2678         Register native_context = register_allocator()->NewRegister();
2679         Register global_object = register_allocator()->NewRegister();
2680         builder()
2681             ->LoadContextSlot(execution_context()->reg(),
2682                               Context::NATIVE_CONTEXT_INDEX)
2683             .StoreAccumulatorInRegister(native_context)
2684             .LoadContextSlot(native_context, Context::EXTENSION_INDEX)
2685             .StoreAccumulatorInRegister(global_object)
2686             .LoadLiteral(variable->name())
2687             .Delete(global_object, language_mode());
2688         break;
2689       }
2690       case VariableLocation::PARAMETER:
2691       case VariableLocation::LOCAL:
2692       case VariableLocation::CONTEXT: {
2693         // Deleting local var/let/const, context variables, and arguments
2694         // does not have any effect.
2695         if (variable->HasThisName(isolate())) {
2696           builder()->LoadTrue();
2697         } else {
2698           builder()->LoadFalse();
2699         }
2700         break;
2701       }
2702       case VariableLocation::LOOKUP: {
2703         Register name_reg = register_allocator()->NewRegister();
2704         builder()
2705             ->LoadLiteral(variable->name())
2706             .StoreAccumulatorInRegister(name_reg)
2707             .CallRuntime(Runtime::kDeleteLookupSlot, name_reg, 1);
2708         break;
2709       }
2710       default:
2711         UNREACHABLE();
2712     }
2713   } else {
2714     // Delete of an unresolvable reference returns true.
2715     VisitForEffect(expr->expression());
2716     builder()->LoadTrue();
2717   }
2718   execution_result()->SetResultInAccumulator();
2719 }
2720 
VisitCountOperation(CountOperation * expr)2721 void BytecodeGenerator::VisitCountOperation(CountOperation* expr) {
2722   DCHECK(expr->expression()->IsValidReferenceExpressionOrThis());
2723 
2724   // Left-hand side can only be a property, a global or a variable slot.
2725   Property* property = expr->expression()->AsProperty();
2726   LhsKind assign_type = Property::GetAssignType(property);
2727 
2728   // TODO(rmcilroy): Set is_postfix to false if visiting for effect.
2729   bool is_postfix = expr->is_postfix();
2730 
2731   // Evaluate LHS expression and get old value.
2732   Register object, home_object, key, old_value, value;
2733   Handle<String> name;
2734   switch (assign_type) {
2735     case VARIABLE: {
2736       VariableProxy* proxy = expr->expression()->AsVariableProxy();
2737       VisitVariableLoadForAccumulatorValue(proxy->var(),
2738                                            proxy->VariableFeedbackSlot());
2739       break;
2740     }
2741     case NAMED_PROPERTY: {
2742       FeedbackVectorSlot slot = property->PropertyFeedbackSlot();
2743       object = VisitForRegisterValue(property->obj());
2744       name = property->key()->AsLiteral()->AsPropertyName();
2745       builder()->LoadNamedProperty(object, name, feedback_index(slot));
2746       break;
2747     }
2748     case KEYED_PROPERTY: {
2749       FeedbackVectorSlot slot = property->PropertyFeedbackSlot();
2750       object = VisitForRegisterValue(property->obj());
2751       // Use visit for accumulator here since we need the key in the accumulator
2752       // for the LoadKeyedProperty.
2753       key = register_allocator()->NewRegister();
2754       VisitForAccumulatorValue(property->key());
2755       builder()->StoreAccumulatorInRegister(key).LoadKeyedProperty(
2756           object, feedback_index(slot));
2757       break;
2758     }
2759     case NAMED_SUPER_PROPERTY: {
2760       register_allocator()->PrepareForConsecutiveAllocations(4);
2761       object = register_allocator()->NextConsecutiveRegister();
2762       home_object = register_allocator()->NextConsecutiveRegister();
2763       key = register_allocator()->NextConsecutiveRegister();
2764       value = register_allocator()->NextConsecutiveRegister();
2765       SuperPropertyReference* super_property =
2766           property->obj()->AsSuperPropertyReference();
2767       VisitForRegisterValue(super_property->this_var(), object);
2768       VisitForRegisterValue(super_property->home_object(), home_object);
2769       builder()
2770           ->LoadLiteral(property->key()->AsLiteral()->AsPropertyName())
2771           .StoreAccumulatorInRegister(key);
2772       BuildNamedSuperPropertyLoad(object, home_object, key);
2773       break;
2774     }
2775     case KEYED_SUPER_PROPERTY: {
2776       register_allocator()->PrepareForConsecutiveAllocations(4);
2777       object = register_allocator()->NextConsecutiveRegister();
2778       home_object = register_allocator()->NextConsecutiveRegister();
2779       key = register_allocator()->NextConsecutiveRegister();
2780       value = register_allocator()->NextConsecutiveRegister();
2781       builder()->StoreAccumulatorInRegister(value);
2782       SuperPropertyReference* super_property =
2783           property->obj()->AsSuperPropertyReference();
2784       VisitForRegisterValue(super_property->this_var(), object);
2785       VisitForRegisterValue(super_property->home_object(), home_object);
2786       VisitForRegisterValue(property->key(), key);
2787       BuildKeyedSuperPropertyLoad(object, home_object, key);
2788       break;
2789     }
2790   }
2791 
2792   // Save result for postfix expressions.
2793   if (is_postfix) {
2794     old_value = register_allocator()->outer()->NewRegister();
2795 
2796     // Convert old value into a number before saving it.
2797     builder()->CastAccumulatorToNumber().StoreAccumulatorInRegister(old_value);
2798   }
2799 
2800   // Perform +1/-1 operation.
2801   builder()->CountOperation(expr->binary_op());
2802 
2803   // Store the value.
2804   builder()->SetExpressionPosition(expr);
2805   FeedbackVectorSlot feedback_slot = expr->CountSlot();
2806   switch (assign_type) {
2807     case VARIABLE: {
2808       Variable* variable = expr->expression()->AsVariableProxy()->var();
2809       VisitVariableAssignment(variable, expr->op(), feedback_slot);
2810       break;
2811     }
2812     case NAMED_PROPERTY: {
2813       builder()->StoreNamedProperty(object, name, feedback_index(feedback_slot),
2814                                     language_mode());
2815       break;
2816     }
2817     case KEYED_PROPERTY: {
2818       builder()->StoreKeyedProperty(object, key, feedback_index(feedback_slot),
2819                                     language_mode());
2820       break;
2821     }
2822     case NAMED_SUPER_PROPERTY: {
2823       builder()->StoreAccumulatorInRegister(value);
2824       BuildNamedSuperPropertyStore(object, home_object, key, value);
2825       break;
2826     }
2827     case KEYED_SUPER_PROPERTY: {
2828       builder()->StoreAccumulatorInRegister(value);
2829       BuildKeyedSuperPropertyStore(object, home_object, key, value);
2830       break;
2831     }
2832   }
2833 
2834   // Restore old value for postfix expressions.
2835   if (is_postfix) {
2836     execution_result()->SetResultInRegister(old_value);
2837   } else {
2838     execution_result()->SetResultInAccumulator();
2839   }
2840 }
2841 
VisitBinaryOperation(BinaryOperation * binop)2842 void BytecodeGenerator::VisitBinaryOperation(BinaryOperation* binop) {
2843   switch (binop->op()) {
2844     case Token::COMMA:
2845       VisitCommaExpression(binop);
2846       break;
2847     case Token::OR:
2848       VisitLogicalOrExpression(binop);
2849       break;
2850     case Token::AND:
2851       VisitLogicalAndExpression(binop);
2852       break;
2853     default:
2854       VisitArithmeticExpression(binop);
2855       break;
2856   }
2857 }
2858 
VisitCompareOperation(CompareOperation * expr)2859 void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) {
2860   Register lhs = VisitForRegisterValue(expr->left());
2861   VisitForAccumulatorValue(expr->right());
2862   builder()->SetExpressionPosition(expr);
2863   builder()->CompareOperation(expr->op(), lhs);
2864   execution_result()->SetResultInAccumulator();
2865 }
2866 
VisitArithmeticExpression(BinaryOperation * expr)2867 void BytecodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) {
2868   Register lhs = VisitForRegisterValue(expr->left());
2869   VisitForAccumulatorValue(expr->right());
2870   builder()->BinaryOperation(expr->op(), lhs);
2871   execution_result()->SetResultInAccumulator();
2872 }
2873 
VisitSpread(Spread * expr)2874 void BytecodeGenerator::VisitSpread(Spread* expr) { UNREACHABLE(); }
2875 
VisitEmptyParentheses(EmptyParentheses * expr)2876 void BytecodeGenerator::VisitEmptyParentheses(EmptyParentheses* expr) {
2877   UNREACHABLE();
2878 }
2879 
VisitThisFunction(ThisFunction * expr)2880 void BytecodeGenerator::VisitThisFunction(ThisFunction* expr) {
2881   execution_result()->SetResultInRegister(Register::function_closure());
2882 }
2883 
VisitSuperCallReference(SuperCallReference * expr)2884 void BytecodeGenerator::VisitSuperCallReference(SuperCallReference* expr) {
2885   // Handled by VisitCall().
2886   UNREACHABLE();
2887 }
2888 
VisitSuperPropertyReference(SuperPropertyReference * expr)2889 void BytecodeGenerator::VisitSuperPropertyReference(
2890     SuperPropertyReference* expr) {
2891   builder()->CallRuntime(Runtime::kThrowUnsupportedSuperError, Register(0), 0);
2892   execution_result()->SetResultInAccumulator();
2893 }
2894 
VisitCommaExpression(BinaryOperation * binop)2895 void BytecodeGenerator::VisitCommaExpression(BinaryOperation* binop) {
2896   VisitForEffect(binop->left());
2897   Visit(binop->right());
2898 }
2899 
VisitLogicalOrExpression(BinaryOperation * binop)2900 void BytecodeGenerator::VisitLogicalOrExpression(BinaryOperation* binop) {
2901   Expression* left = binop->left();
2902   Expression* right = binop->right();
2903 
2904   // Short-circuit evaluation- If it is known that left is always true,
2905   // no need to visit right
2906   if (left->ToBooleanIsTrue()) {
2907     VisitForAccumulatorValue(left);
2908   } else {
2909     BytecodeLabel end_label;
2910     VisitForAccumulatorValue(left);
2911     builder()->JumpIfTrue(&end_label);
2912     VisitForAccumulatorValue(right);
2913     builder()->Bind(&end_label);
2914   }
2915   execution_result()->SetResultInAccumulator();
2916 }
2917 
VisitLogicalAndExpression(BinaryOperation * binop)2918 void BytecodeGenerator::VisitLogicalAndExpression(BinaryOperation* binop) {
2919   Expression* left = binop->left();
2920   Expression* right = binop->right();
2921 
2922   // Short-circuit evaluation- If it is known that left is always false,
2923   // no need to visit right
2924   if (left->ToBooleanIsFalse()) {
2925     VisitForAccumulatorValue(left);
2926   } else {
2927     BytecodeLabel end_label;
2928     VisitForAccumulatorValue(left);
2929     builder()->JumpIfFalse(&end_label);
2930     VisitForAccumulatorValue(right);
2931     builder()->Bind(&end_label);
2932   }
2933   execution_result()->SetResultInAccumulator();
2934 }
2935 
VisitRewritableExpression(RewritableExpression * expr)2936 void BytecodeGenerator::VisitRewritableExpression(RewritableExpression* expr) {
2937   Visit(expr->expression());
2938 }
2939 
VisitNewLocalFunctionContext()2940 void BytecodeGenerator::VisitNewLocalFunctionContext() {
2941   AccumulatorResultScope accumulator_execution_result(this);
2942   Scope* scope = this->scope();
2943 
2944   // Allocate a new local context.
2945   if (scope->is_script_scope()) {
2946     RegisterAllocationScope register_scope(this);
2947     Register closure = register_allocator()->NewRegister();
2948     Register scope_info = register_allocator()->NewRegister();
2949     DCHECK(Register::AreContiguous(closure, scope_info));
2950     builder()
2951         ->LoadAccumulatorWithRegister(Register::function_closure())
2952         .StoreAccumulatorInRegister(closure)
2953         .LoadLiteral(scope->GetScopeInfo(isolate()))
2954         .StoreAccumulatorInRegister(scope_info)
2955         .CallRuntime(Runtime::kNewScriptContext, closure, 2);
2956   } else {
2957     builder()->CallRuntime(Runtime::kNewFunctionContext,
2958                            Register::function_closure(), 1);
2959   }
2960   execution_result()->SetResultInAccumulator();
2961 }
2962 
VisitBuildLocalActivationContext()2963 void BytecodeGenerator::VisitBuildLocalActivationContext() {
2964   Scope* scope = this->scope();
2965 
2966   if (scope->has_this_declaration() && scope->receiver()->IsContextSlot()) {
2967     Variable* variable = scope->receiver();
2968     Register receiver(builder()->Parameter(0));
2969     // Context variable (at bottom of the context chain).
2970     DCHECK_EQ(0, scope->ContextChainLength(variable->scope()));
2971     builder()->LoadAccumulatorWithRegister(receiver).StoreContextSlot(
2972         execution_context()->reg(), variable->index());
2973   }
2974 
2975   // Copy parameters into context if necessary.
2976   int num_parameters = scope->num_parameters();
2977   for (int i = 0; i < num_parameters; i++) {
2978     Variable* variable = scope->parameter(i);
2979     if (!variable->IsContextSlot()) continue;
2980 
2981     // The parameter indices are shifted by 1 (receiver is variable
2982     // index -1 but is parameter index 0 in BytecodeArrayBuilder).
2983     Register parameter(builder()->Parameter(i + 1));
2984     // Context variable (at bottom of the context chain).
2985     DCHECK_EQ(0, scope->ContextChainLength(variable->scope()));
2986     builder()->LoadAccumulatorWithRegister(parameter)
2987         .StoreContextSlot(execution_context()->reg(), variable->index());
2988   }
2989 }
2990 
VisitNewLocalBlockContext(Scope * scope)2991 void BytecodeGenerator::VisitNewLocalBlockContext(Scope* scope) {
2992   AccumulatorResultScope accumulator_execution_result(this);
2993   DCHECK(scope->is_block_scope());
2994 
2995   // Allocate a new local block context.
2996   register_allocator()->PrepareForConsecutiveAllocations(2);
2997   Register scope_info = register_allocator()->NextConsecutiveRegister();
2998   Register closure = register_allocator()->NextConsecutiveRegister();
2999 
3000   builder()
3001       ->LoadLiteral(scope->GetScopeInfo(isolate()))
3002       .StoreAccumulatorInRegister(scope_info);
3003   VisitFunctionClosureForContext();
3004   builder()
3005       ->StoreAccumulatorInRegister(closure)
3006       .CallRuntime(Runtime::kPushBlockContext, scope_info, 2);
3007   execution_result()->SetResultInAccumulator();
3008 }
3009 
VisitNewLocalWithContext()3010 void BytecodeGenerator::VisitNewLocalWithContext() {
3011   AccumulatorResultScope accumulator_execution_result(this);
3012 
3013   register_allocator()->PrepareForConsecutiveAllocations(2);
3014   Register extension_object = register_allocator()->NextConsecutiveRegister();
3015   Register closure = register_allocator()->NextConsecutiveRegister();
3016 
3017   builder()->StoreAccumulatorInRegister(extension_object);
3018   VisitFunctionClosureForContext();
3019   builder()->StoreAccumulatorInRegister(closure).CallRuntime(
3020       Runtime::kPushWithContext, extension_object, 2);
3021   execution_result()->SetResultInAccumulator();
3022 }
3023 
VisitNewLocalCatchContext(Variable * variable)3024 void BytecodeGenerator::VisitNewLocalCatchContext(Variable* variable) {
3025   AccumulatorResultScope accumulator_execution_result(this);
3026   DCHECK(variable->IsContextSlot());
3027 
3028   // Allocate a new local block context.
3029   register_allocator()->PrepareForConsecutiveAllocations(3);
3030   Register name = register_allocator()->NextConsecutiveRegister();
3031   Register exception = register_allocator()->NextConsecutiveRegister();
3032   Register closure = register_allocator()->NextConsecutiveRegister();
3033 
3034   builder()
3035       ->StoreAccumulatorInRegister(exception)
3036       .LoadLiteral(variable->name())
3037       .StoreAccumulatorInRegister(name);
3038   VisitFunctionClosureForContext();
3039   builder()->StoreAccumulatorInRegister(closure).CallRuntime(
3040       Runtime::kPushCatchContext, name, 3);
3041   execution_result()->SetResultInAccumulator();
3042 }
3043 
VisitObjectLiteralAccessor(Register home_object,ObjectLiteralProperty * property,Register value_out)3044 void BytecodeGenerator::VisitObjectLiteralAccessor(
3045     Register home_object, ObjectLiteralProperty* property, Register value_out) {
3046   // TODO(rmcilroy): Replace value_out with VisitForRegister();
3047   if (property == nullptr) {
3048     builder()->LoadNull().StoreAccumulatorInRegister(value_out);
3049   } else {
3050     VisitForAccumulatorValue(property->value());
3051     builder()->StoreAccumulatorInRegister(value_out);
3052     VisitSetHomeObject(value_out, home_object, property);
3053   }
3054 }
3055 
VisitSetHomeObject(Register value,Register home_object,ObjectLiteralProperty * property,int slot_number)3056 void BytecodeGenerator::VisitSetHomeObject(Register value, Register home_object,
3057                                            ObjectLiteralProperty* property,
3058                                            int slot_number) {
3059   Expression* expr = property->value();
3060   if (FunctionLiteral::NeedsHomeObject(expr)) {
3061     Handle<Name> name = isolate()->factory()->home_object_symbol();
3062     FeedbackVectorSlot slot = property->GetSlot(slot_number);
3063     builder()
3064         ->LoadAccumulatorWithRegister(home_object)
3065         .StoreNamedProperty(value, name, feedback_index(slot), language_mode());
3066   }
3067 }
3068 
VisitArgumentsObject(Variable * variable)3069 void BytecodeGenerator::VisitArgumentsObject(Variable* variable) {
3070   if (variable == nullptr) return;
3071 
3072   DCHECK(variable->IsContextSlot() || variable->IsStackAllocated());
3073 
3074   // Allocate and initialize a new arguments object and assign to the
3075   // {arguments} variable.
3076   CreateArgumentsType type =
3077       is_strict(language_mode()) || !info()->has_simple_parameters()
3078           ? CreateArgumentsType::kUnmappedArguments
3079           : CreateArgumentsType::kMappedArguments;
3080   builder()->CreateArguments(type);
3081   VisitVariableAssignment(variable, Token::ASSIGN,
3082                           FeedbackVectorSlot::Invalid());
3083 }
3084 
VisitRestArgumentsArray(Variable * rest)3085 void BytecodeGenerator::VisitRestArgumentsArray(Variable* rest) {
3086   if (rest == nullptr) return;
3087 
3088   // Allocate and initialize a new rest parameter and assign to the {rest}
3089   // variable.
3090   builder()->CreateArguments(CreateArgumentsType::kRestParameter);
3091   DCHECK(rest->IsContextSlot() || rest->IsStackAllocated());
3092   VisitVariableAssignment(rest, Token::ASSIGN, FeedbackVectorSlot::Invalid());
3093 }
3094 
VisitThisFunctionVariable(Variable * variable)3095 void BytecodeGenerator::VisitThisFunctionVariable(Variable* variable) {
3096   if (variable == nullptr) return;
3097 
3098   // Store the closure we were called with in the given variable.
3099   builder()->LoadAccumulatorWithRegister(Register::function_closure());
3100   VisitVariableAssignment(variable, Token::INIT, FeedbackVectorSlot::Invalid());
3101 }
3102 
VisitNewTargetVariable(Variable * variable)3103 void BytecodeGenerator::VisitNewTargetVariable(Variable* variable) {
3104   if (variable == nullptr) return;
3105 
3106   // Store the new target we were called with in the given variable.
3107   builder()->LoadAccumulatorWithRegister(Register::new_target());
3108   VisitVariableAssignment(variable, Token::INIT, FeedbackVectorSlot::Invalid());
3109 }
3110 
VisitFunctionClosureForContext()3111 void BytecodeGenerator::VisitFunctionClosureForContext() {
3112   AccumulatorResultScope accumulator_execution_result(this);
3113   Scope* closure_scope = execution_context()->scope()->ClosureScope();
3114   if (closure_scope->is_script_scope() ||
3115       closure_scope->is_module_scope()) {
3116     // Contexts nested in the native context have a canonical empty function as
3117     // their closure, not the anonymous closure containing the global code.
3118     Register native_context = register_allocator()->NewRegister();
3119     builder()
3120         ->LoadContextSlot(execution_context()->reg(),
3121                           Context::NATIVE_CONTEXT_INDEX)
3122         .StoreAccumulatorInRegister(native_context)
3123         .LoadContextSlot(native_context, Context::CLOSURE_INDEX);
3124   } else if (closure_scope->is_eval_scope()) {
3125     // Contexts created by a call to eval have the same closure as the
3126     // context calling eval, not the anonymous closure containing the eval
3127     // code. Fetch it from the context.
3128     builder()->LoadContextSlot(execution_context()->reg(),
3129                                Context::CLOSURE_INDEX);
3130   } else {
3131     DCHECK(closure_scope->is_function_scope());
3132     builder()->LoadAccumulatorWithRegister(Register::function_closure());
3133   }
3134   execution_result()->SetResultInAccumulator();
3135 }
3136 
3137 // Visits the expression |expr| and places the result in the accumulator.
VisitForAccumulatorValue(Expression * expr)3138 void BytecodeGenerator::VisitForAccumulatorValue(Expression* expr) {
3139   AccumulatorResultScope accumulator_scope(this);
3140   Visit(expr);
3141 }
3142 
VisitForAccumulatorValueOrTheHole(Expression * expr)3143 void BytecodeGenerator::VisitForAccumulatorValueOrTheHole(Expression* expr) {
3144   if (expr == nullptr) {
3145     builder()->LoadTheHole();
3146   } else {
3147     VisitForAccumulatorValue(expr);
3148   }
3149 }
3150 
3151 // Visits the expression |expr| and discards the result.
VisitForEffect(Expression * expr)3152 void BytecodeGenerator::VisitForEffect(Expression* expr) {
3153   EffectResultScope effect_scope(this);
3154   Visit(expr);
3155 }
3156 
3157 // Visits the expression |expr| and returns the register containing
3158 // the expression result.
VisitForRegisterValue(Expression * expr)3159 Register BytecodeGenerator::VisitForRegisterValue(Expression* expr) {
3160   RegisterResultScope register_scope(this);
3161   Visit(expr);
3162   return register_scope.ResultRegister();
3163 }
3164 
3165 // Visits the expression |expr| and stores the expression result in
3166 // |destination|.
VisitForRegisterValue(Expression * expr,Register destination)3167 void BytecodeGenerator::VisitForRegisterValue(Expression* expr,
3168                                               Register destination) {
3169   AccumulatorResultScope register_scope(this);
3170   Visit(expr);
3171   builder()->StoreAccumulatorInRegister(destination);
3172 }
3173 
VisitInScope(Statement * stmt,Scope * scope)3174 void BytecodeGenerator::VisitInScope(Statement* stmt, Scope* scope) {
3175   ContextScope context_scope(this, scope);
3176   DCHECK(scope->declarations()->is_empty());
3177   Visit(stmt);
3178 }
3179 
language_mode() const3180 LanguageMode BytecodeGenerator::language_mode() const {
3181   return execution_context()->scope()->language_mode();
3182 }
3183 
feedback_index(FeedbackVectorSlot slot) const3184 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const {
3185   return TypeFeedbackVector::GetIndex(slot);
3186 }
3187 
3188 }  // namespace interpreter
3189 }  // namespace internal
3190 }  // namespace v8
3191