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