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