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