blob: b0fa245e18d74f41c3e41d945d26a6aa1677a41b [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// Copyright 2015 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "src/interpreter/bytecode-generator.h"
6
7#include "src/ast/scopes.h"
8#include "src/compiler.h"
9#include "src/interpreter/bytecode-register-allocator.h"
10#include "src/interpreter/control-flow-builders.h"
11#include "src/objects.h"
12#include "src/parsing/parser.h"
13#include "src/parsing/token.h"
14
15namespace v8 {
16namespace internal {
17namespace interpreter {
18
19
20// Scoped class tracking context objects created by the visitor. Represents
21// mutations of the context chain within the function body, allowing pushing and
22// popping of the current {context_register} during visitation.
23class BytecodeGenerator::ContextScope BASE_EMBEDDED {
24 public:
25 ContextScope(BytecodeGenerator* generator, Scope* scope,
26 bool should_pop_context = true)
27 : generator_(generator),
28 scope_(scope),
29 outer_(generator_->execution_context()),
Ben Murdoch097c5b22016-05-18 11:27:45 +010030 register_(Register::current_context()),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000031 depth_(0),
32 should_pop_context_(should_pop_context) {
33 if (outer_) {
34 depth_ = outer_->depth_ + 1;
Ben Murdoch097c5b22016-05-18 11:27:45 +010035
36 // Push the outer context into a new context register.
37 Register outer_context_reg(builder()->first_context_register().index() +
38 outer_->depth_);
39 outer_->set_register(outer_context_reg);
40 generator_->builder()->PushContext(outer_context_reg);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000041 }
42 generator_->set_execution_context(this);
43 }
44
45 ~ContextScope() {
46 if (outer_ && should_pop_context_) {
Ben Murdoch097c5b22016-05-18 11:27:45 +010047 DCHECK_EQ(register_.index(), Register::current_context().index());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000048 generator_->builder()->PopContext(outer_->reg());
Ben Murdoch097c5b22016-05-18 11:27:45 +010049 outer_->set_register(register_);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000050 }
51 generator_->set_execution_context(outer_);
52 }
53
54 // Returns the depth of the given |scope| for the current execution context.
55 int ContextChainDepth(Scope* scope) {
56 return scope_->ContextChainLength(scope);
57 }
58
59 // Returns the execution context at |depth| in the current context chain if it
60 // is a function local execution context, otherwise returns nullptr.
61 ContextScope* Previous(int depth) {
62 if (depth > depth_) {
63 return nullptr;
64 }
65
66 ContextScope* previous = this;
67 for (int i = depth; i > 0; --i) {
68 previous = previous->outer_;
69 }
70 return previous;
71 }
72
73 Scope* scope() const { return scope_; }
74 Register reg() const { return register_; }
Ben Murdochda12d292016-06-02 14:46:10 +010075 bool ShouldPopContext() { return should_pop_context_; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000076
77 private:
Ben Murdoch097c5b22016-05-18 11:27:45 +010078 const BytecodeArrayBuilder* builder() const { return generator_->builder(); }
79
80 void set_register(Register reg) { register_ = reg; }
81
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000082 BytecodeGenerator* generator_;
83 Scope* scope_;
84 ContextScope* outer_;
85 Register register_;
86 int depth_;
87 bool should_pop_context_;
88};
89
90
91// Scoped class for tracking control statements entered by the
92// visitor. The pattern derives AstGraphBuilder::ControlScope.
93class BytecodeGenerator::ControlScope BASE_EMBEDDED {
94 public:
95 explicit ControlScope(BytecodeGenerator* generator)
Ben Murdoch097c5b22016-05-18 11:27:45 +010096 : generator_(generator), outer_(generator->execution_control()),
97 context_(generator->execution_context()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000098 generator_->set_execution_control(this);
99 }
100 virtual ~ControlScope() { generator_->set_execution_control(outer()); }
101
102 void Break(Statement* stmt) { PerformCommand(CMD_BREAK, stmt); }
103 void Continue(Statement* stmt) { PerformCommand(CMD_CONTINUE, stmt); }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100104 void ReturnAccumulator() { PerformCommand(CMD_RETURN, nullptr); }
105 void ReThrowAccumulator() { PerformCommand(CMD_RETHROW, nullptr); }
106
107 class DeferredCommands;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000108
109 protected:
Ben Murdoch097c5b22016-05-18 11:27:45 +0100110 enum Command { CMD_BREAK, CMD_CONTINUE, CMD_RETURN, CMD_RETHROW };
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000111 void PerformCommand(Command command, Statement* statement);
112 virtual bool Execute(Command command, Statement* statement) = 0;
113
114 BytecodeGenerator* generator() const { return generator_; }
115 ControlScope* outer() const { return outer_; }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100116 ContextScope* context() const { return context_; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000117
118 private:
119 BytecodeGenerator* generator_;
120 ControlScope* outer_;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100121 ContextScope* context_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000122
123 DISALLOW_COPY_AND_ASSIGN(ControlScope);
124};
125
126
Ben Murdoch097c5b22016-05-18 11:27:45 +0100127// Helper class for a try-finally control scope. It can record intercepted
128// control-flow commands that cause entry into a finally-block, and re-apply
129// them after again leaving that block. Special tokens are used to identify
130// paths going through the finally-block to dispatch after leaving the block.
131class BytecodeGenerator::ControlScope::DeferredCommands final {
132 public:
133 DeferredCommands(BytecodeGenerator* generator, Register token_register,
134 Register result_register)
135 : generator_(generator),
136 deferred_(generator->zone()),
137 token_register_(token_register),
138 result_register_(result_register) {}
139
140 // One recorded control-flow command.
141 struct Entry {
142 Command command; // The command type being applied on this path.
143 Statement* statement; // The target statement for the command or {nullptr}.
144 int token; // A token identifying this particular path.
145 };
146
147 // Records a control-flow command while entering the finally-block. This also
148 // generates a new dispatch token that identifies one particular path. This
149 // expects the result to be in the accumulator.
150 void RecordCommand(Command command, Statement* statement) {
151 int token = static_cast<int>(deferred_.size());
152 deferred_.push_back({command, statement, token});
153
154 builder()->StoreAccumulatorInRegister(result_register_);
155 builder()->LoadLiteral(Smi::FromInt(token));
156 builder()->StoreAccumulatorInRegister(token_register_);
157 }
158
159 // Records the dispatch token to be used to identify the re-throw path when
160 // the finally-block has been entered through the exception handler. This
161 // expects the exception to be in the accumulator.
162 void RecordHandlerReThrowPath() {
163 // The accumulator contains the exception object.
164 RecordCommand(CMD_RETHROW, nullptr);
165 }
166
167 // Records the dispatch token to be used to identify the implicit fall-through
168 // path at the end of a try-block into the corresponding finally-block.
169 void RecordFallThroughPath() {
170 builder()->LoadLiteral(Smi::FromInt(-1));
171 builder()->StoreAccumulatorInRegister(token_register_);
172 }
173
174 // Applies all recorded control-flow commands after the finally-block again.
175 // This generates a dynamic dispatch on the token from the entry point.
176 void ApplyDeferredCommands() {
177 // The fall-through path is covered by the default case, hence +1 here.
178 SwitchBuilder dispatch(builder(), static_cast<int>(deferred_.size() + 1));
179 for (size_t i = 0; i < deferred_.size(); ++i) {
180 Entry& entry = deferred_[i];
181 builder()->LoadLiteral(Smi::FromInt(entry.token));
182 builder()->CompareOperation(Token::EQ_STRICT, token_register_);
183 dispatch.Case(static_cast<int>(i));
184 }
185 dispatch.DefaultAt(static_cast<int>(deferred_.size()));
186 for (size_t i = 0; i < deferred_.size(); ++i) {
187 Entry& entry = deferred_[i];
188 dispatch.SetCaseTarget(static_cast<int>(i));
189 builder()->LoadAccumulatorWithRegister(result_register_);
190 execution_control()->PerformCommand(entry.command, entry.statement);
191 }
192 dispatch.SetCaseTarget(static_cast<int>(deferred_.size()));
193 }
194
195 BytecodeArrayBuilder* builder() { return generator_->builder(); }
196 ControlScope* execution_control() { return generator_->execution_control(); }
197
198 private:
199 BytecodeGenerator* generator_;
200 ZoneVector<Entry> deferred_;
201 Register token_register_;
202 Register result_register_;
203};
204
205
206// Scoped class for dealing with control flow reaching the function level.
207class BytecodeGenerator::ControlScopeForTopLevel final
208 : public BytecodeGenerator::ControlScope {
209 public:
210 explicit ControlScopeForTopLevel(BytecodeGenerator* generator)
211 : ControlScope(generator) {}
212
213 protected:
214 bool Execute(Command command, Statement* statement) override {
215 switch (command) {
Ben Murdochda12d292016-06-02 14:46:10 +0100216 case CMD_BREAK: // We should never see break/continue in top-level.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100217 case CMD_CONTINUE:
Ben Murdochda12d292016-06-02 14:46:10 +0100218 UNREACHABLE();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100219 case CMD_RETURN:
220 generator()->builder()->Return();
221 return true;
222 case CMD_RETHROW:
223 generator()->builder()->ReThrow();
224 return true;
225 }
226 return false;
227 }
228};
229
230
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000231// Scoped class for enabling break inside blocks and switch blocks.
232class BytecodeGenerator::ControlScopeForBreakable final
233 : public BytecodeGenerator::ControlScope {
234 public:
235 ControlScopeForBreakable(BytecodeGenerator* generator,
236 BreakableStatement* statement,
237 BreakableControlFlowBuilder* control_builder)
238 : ControlScope(generator),
239 statement_(statement),
240 control_builder_(control_builder) {}
241
242 protected:
Ben Murdoch097c5b22016-05-18 11:27:45 +0100243 bool Execute(Command command, Statement* statement) override {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000244 if (statement != statement_) return false;
245 switch (command) {
246 case CMD_BREAK:
247 control_builder_->Break();
248 return true;
249 case CMD_CONTINUE:
Ben Murdoch097c5b22016-05-18 11:27:45 +0100250 case CMD_RETURN:
251 case CMD_RETHROW:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000252 break;
253 }
254 return false;
255 }
256
257 private:
258 Statement* statement_;
259 BreakableControlFlowBuilder* control_builder_;
260};
261
262
263// Scoped class for enabling 'break' and 'continue' in iteration
264// constructs, e.g. do...while, while..., for...
265class BytecodeGenerator::ControlScopeForIteration final
266 : public BytecodeGenerator::ControlScope {
267 public:
268 ControlScopeForIteration(BytecodeGenerator* generator,
269 IterationStatement* statement,
270 LoopBuilder* loop_builder)
271 : ControlScope(generator),
272 statement_(statement),
273 loop_builder_(loop_builder) {}
274
275 protected:
Ben Murdoch097c5b22016-05-18 11:27:45 +0100276 bool Execute(Command command, Statement* statement) override {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000277 if (statement != statement_) return false;
278 switch (command) {
279 case CMD_BREAK:
280 loop_builder_->Break();
281 return true;
282 case CMD_CONTINUE:
283 loop_builder_->Continue();
284 return true;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100285 case CMD_RETURN:
286 case CMD_RETHROW:
287 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000288 }
289 return false;
290 }
291
292 private:
293 Statement* statement_;
294 LoopBuilder* loop_builder_;
295};
296
297
Ben Murdoch097c5b22016-05-18 11:27:45 +0100298// Scoped class for enabling 'throw' in try-catch constructs.
299class BytecodeGenerator::ControlScopeForTryCatch final
300 : public BytecodeGenerator::ControlScope {
301 public:
302 ControlScopeForTryCatch(BytecodeGenerator* generator,
303 TryCatchBuilder* try_catch_builder)
304 : ControlScope(generator) {
305 generator->try_catch_nesting_level_++;
306 }
307 virtual ~ControlScopeForTryCatch() {
308 generator()->try_catch_nesting_level_--;
309 }
310
311 protected:
312 bool Execute(Command command, Statement* statement) override {
313 switch (command) {
314 case CMD_BREAK:
315 case CMD_CONTINUE:
316 case CMD_RETURN:
317 break;
318 case CMD_RETHROW:
319 generator()->builder()->ReThrow();
320 return true;
321 }
322 return false;
323 }
324};
325
326
327// Scoped class for enabling control flow through try-finally constructs.
328class BytecodeGenerator::ControlScopeForTryFinally final
329 : public BytecodeGenerator::ControlScope {
330 public:
331 ControlScopeForTryFinally(BytecodeGenerator* generator,
332 TryFinallyBuilder* try_finally_builder,
333 DeferredCommands* commands)
334 : ControlScope(generator),
335 try_finally_builder_(try_finally_builder),
336 commands_(commands) {
337 generator->try_finally_nesting_level_++;
338 }
339 virtual ~ControlScopeForTryFinally() {
340 generator()->try_finally_nesting_level_--;
341 }
342
343 protected:
344 bool Execute(Command command, Statement* statement) override {
345 switch (command) {
346 case CMD_BREAK:
347 case CMD_CONTINUE:
348 case CMD_RETURN:
349 case CMD_RETHROW:
350 commands_->RecordCommand(command, statement);
351 try_finally_builder_->LeaveTry();
352 return true;
353 }
354 return false;
355 }
356
357 private:
358 TryFinallyBuilder* try_finally_builder_;
359 DeferredCommands* commands_;
360};
361
362
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000363void BytecodeGenerator::ControlScope::PerformCommand(Command command,
364 Statement* statement) {
365 ControlScope* current = this;
Ben Murdochda12d292016-06-02 14:46:10 +0100366 ContextScope* context = generator()->execution_context();
367 // Pop context to the expected depth but do not pop the outermost context.
368 if (context != current->context() && context->ShouldPopContext()) {
369 generator()->builder()->PopContext(current->context()->reg());
370 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000371 do {
Ben Murdochda12d292016-06-02 14:46:10 +0100372 if (current->Execute(command, statement)) {
373 return;
374 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000375 current = current->outer();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100376 if (current->context() != context) {
377 // Pop context to the expected depth.
378 // TODO(rmcilroy): Only emit a single context pop.
379 generator()->builder()->PopContext(current->context()->reg());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100380 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000381 } while (current != nullptr);
382 UNREACHABLE();
383}
384
385
386class BytecodeGenerator::RegisterAllocationScope {
387 public:
388 explicit RegisterAllocationScope(BytecodeGenerator* generator)
389 : generator_(generator),
390 outer_(generator->register_allocator()),
Ben Murdoch097c5b22016-05-18 11:27:45 +0100391 allocator_(builder()->zone(),
392 builder()->temporary_register_allocator()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000393 generator_->set_register_allocator(this);
394 }
395
396 virtual ~RegisterAllocationScope() {
397 generator_->set_register_allocator(outer_);
398 }
399
400 Register NewRegister() {
401 RegisterAllocationScope* current_scope = generator()->register_allocator();
402 if ((current_scope == this) ||
403 (current_scope->outer() == this &&
404 !current_scope->allocator_.HasConsecutiveAllocations())) {
405 // Regular case - Allocating registers in current or outer context.
406 // VisitForRegisterValue allocates register in outer context.
407 return allocator_.NewRegister();
408 } else {
409 // If it is required to allocate a register other than current or outer
410 // scopes, allocate a new temporary register. It might be expensive to
411 // walk the full context chain and compute the list of consecutive
412 // reservations in the innerscopes.
413 UNIMPLEMENTED();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100414 return Register::invalid_value();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000415 }
416 }
417
Ben Murdoch097c5b22016-05-18 11:27:45 +0100418 void PrepareForConsecutiveAllocations(int count) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000419 allocator_.PrepareForConsecutiveAllocations(count);
420 }
421
422 Register NextConsecutiveRegister() {
423 return allocator_.NextConsecutiveRegister();
424 }
425
426 bool RegisterIsAllocatedInThisScope(Register reg) const {
427 return allocator_.RegisterIsAllocatedInThisScope(reg);
428 }
429
430 RegisterAllocationScope* outer() const { return outer_; }
431
432 private:
433 BytecodeGenerator* generator() const { return generator_; }
434 BytecodeArrayBuilder* builder() const { return generator_->builder(); }
435
436 BytecodeGenerator* generator_;
437 RegisterAllocationScope* outer_;
438 BytecodeRegisterAllocator allocator_;
439
440 DISALLOW_COPY_AND_ASSIGN(RegisterAllocationScope);
441};
442
443
444// Scoped base class for determining where the result of an expression
445// is stored.
446class BytecodeGenerator::ExpressionResultScope {
447 public:
448 ExpressionResultScope(BytecodeGenerator* generator, Expression::Context kind)
449 : generator_(generator),
450 kind_(kind),
451 outer_(generator->execution_result()),
452 allocator_(generator),
453 result_identified_(false) {
454 generator_->set_execution_result(this);
455 }
456
457 virtual ~ExpressionResultScope() {
458 generator_->set_execution_result(outer_);
Ben Murdochda12d292016-06-02 14:46:10 +0100459 DCHECK(result_identified() || generator_->HasStackOverflow());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000460 }
461
462 bool IsEffect() const { return kind_ == Expression::kEffect; }
463 bool IsValue() const { return kind_ == Expression::kValue; }
464
465 virtual void SetResultInAccumulator() = 0;
466 virtual void SetResultInRegister(Register reg) = 0;
467
468 protected:
469 ExpressionResultScope* outer() const { return outer_; }
470 BytecodeArrayBuilder* builder() const { return generator_->builder(); }
Ben Murdochda12d292016-06-02 14:46:10 +0100471 BytecodeGenerator* generator() const { return generator_; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000472 const RegisterAllocationScope* allocator() const { return &allocator_; }
473
474 void set_result_identified() {
475 DCHECK(!result_identified());
476 result_identified_ = true;
477 }
478
479 bool result_identified() const { return result_identified_; }
480
481 private:
482 BytecodeGenerator* generator_;
483 Expression::Context kind_;
484 ExpressionResultScope* outer_;
485 RegisterAllocationScope allocator_;
486 bool result_identified_;
487
488 DISALLOW_COPY_AND_ASSIGN(ExpressionResultScope);
489};
490
491
492// Scoped class used when the result of the current expression is not
493// expected to produce a result.
494class BytecodeGenerator::EffectResultScope final
495 : public ExpressionResultScope {
496 public:
497 explicit EffectResultScope(BytecodeGenerator* generator)
498 : ExpressionResultScope(generator, Expression::kEffect) {
499 set_result_identified();
500 }
501
502 virtual void SetResultInAccumulator() {}
503 virtual void SetResultInRegister(Register reg) {}
504};
505
506
507// Scoped class used when the result of the current expression to be
508// evaluated should go into the interpreter's accumulator register.
509class BytecodeGenerator::AccumulatorResultScope final
510 : public ExpressionResultScope {
511 public:
512 explicit AccumulatorResultScope(BytecodeGenerator* generator)
513 : ExpressionResultScope(generator, Expression::kValue) {}
514
515 virtual void SetResultInAccumulator() { set_result_identified(); }
516
517 virtual void SetResultInRegister(Register reg) {
518 builder()->LoadAccumulatorWithRegister(reg);
519 set_result_identified();
520 }
521};
522
523
524// Scoped class used when the result of the current expression to be
525// evaluated should go into an interpreter register.
526class BytecodeGenerator::RegisterResultScope final
527 : public ExpressionResultScope {
528 public:
529 explicit RegisterResultScope(BytecodeGenerator* generator)
530 : ExpressionResultScope(generator, Expression::kValue) {}
531
532 virtual void SetResultInAccumulator() {
533 result_register_ = allocator()->outer()->NewRegister();
534 builder()->StoreAccumulatorInRegister(result_register_);
535 set_result_identified();
536 }
537
538 virtual void SetResultInRegister(Register reg) {
539 DCHECK(builder()->RegisterIsParameterOrLocal(reg) ||
Ben Murdoch097c5b22016-05-18 11:27:45 +0100540 (builder()->TemporaryRegisterIsLive(reg) &&
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000541 !allocator()->RegisterIsAllocatedInThisScope(reg)));
542 result_register_ = reg;
543 set_result_identified();
544 }
545
Ben Murdochda12d292016-06-02 14:46:10 +0100546 Register ResultRegister() {
547 if (generator()->HasStackOverflow() && !result_identified()) {
548 SetResultInAccumulator();
549 }
550 return result_register_;
551 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000552
553 private:
554 Register result_register_;
555};
556
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000557BytecodeGenerator::BytecodeGenerator(Isolate* isolate, Zone* zone)
558 : isolate_(isolate),
559 zone_(zone),
Ben Murdoch097c5b22016-05-18 11:27:45 +0100560 builder_(nullptr),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000561 info_(nullptr),
562 scope_(nullptr),
563 globals_(0, zone),
564 execution_control_(nullptr),
565 execution_context_(nullptr),
566 execution_result_(nullptr),
Ben Murdoch097c5b22016-05-18 11:27:45 +0100567 register_allocator_(nullptr),
568 try_catch_nesting_level_(0),
569 try_finally_nesting_level_(0) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000570 InitializeAstVisitor(isolate);
571}
572
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000573Handle<BytecodeArray> BytecodeGenerator::MakeBytecode(CompilationInfo* info) {
574 set_info(info);
575 set_scope(info->scope());
576
Ben Murdoch097c5b22016-05-18 11:27:45 +0100577 // Initialize bytecode array builder.
578 set_builder(new (zone()) BytecodeArrayBuilder(
579 isolate(), zone(), info->num_parameters_including_this(),
Ben Murdochda12d292016-06-02 14:46:10 +0100580 scope()->MaxNestedContextChainLength(), scope()->num_stack_slots(),
581 info->literal()));
Ben Murdoch097c5b22016-05-18 11:27:45 +0100582
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000583 // Initialize the incoming context.
584 ContextScope incoming_context(this, scope(), false);
585
Ben Murdoch097c5b22016-05-18 11:27:45 +0100586 // Initialize control scope.
587 ControlScopeForTopLevel control(this);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000588
589 // Build function context only if there are context allocated variables.
590 if (scope()->NeedsContext()) {
591 // Push a new inner context scope for the function.
592 VisitNewLocalFunctionContext();
593 ContextScope local_function_context(this, scope(), false);
594 VisitBuildLocalActivationContext();
595 MakeBytecodeBody();
596 } else {
597 MakeBytecodeBody();
598 }
599
Ben Murdochda12d292016-06-02 14:46:10 +0100600 builder()->EnsureReturn();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000601 set_scope(nullptr);
602 set_info(nullptr);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100603 return builder()->ToBytecodeArray();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000604}
605
606
607void BytecodeGenerator::MakeBytecodeBody() {
608 // Build the arguments object if it is used.
609 VisitArgumentsObject(scope()->arguments());
610
Ben Murdoch097c5b22016-05-18 11:27:45 +0100611 // Build rest arguments array if it is used.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000612 int rest_index;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100613 Variable* rest_parameter = scope()->rest_parameter(&rest_index);
614 VisitRestArgumentsArray(rest_parameter);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000615
616 // Build assignment to {.this_function} variable if it is used.
617 VisitThisFunctionVariable(scope()->this_function_var());
618
619 // Build assignment to {new.target} variable if it is used.
620 VisitNewTargetVariable(scope()->new_target_var());
621
622 // TODO(rmcilroy): Emit tracing call if requested to do so.
623 if (FLAG_trace) {
624 UNIMPLEMENTED();
625 }
626
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000627 // Visit declarations within the function scope.
628 VisitDeclarations(scope()->declarations());
629
Ben Murdoch097c5b22016-05-18 11:27:45 +0100630 // Perform a stack-check before the body.
631 builder()->StackCheck();
632
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000633 // Visit statements in the function body.
634 VisitStatements(info()->literal()->body());
635}
636
637
638void BytecodeGenerator::VisitBlock(Block* stmt) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100639 // Visit declarations and statements.
640 if (stmt->scope() != nullptr && stmt->scope()->NeedsContext()) {
641 VisitNewLocalBlockContext(stmt->scope());
642 ContextScope scope(this, stmt->scope());
643 VisitBlockDeclarationsAndStatements(stmt);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000644 } else {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100645 VisitBlockDeclarationsAndStatements(stmt);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000646 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100647}
648
649
650void BytecodeGenerator::VisitBlockDeclarationsAndStatements(Block* stmt) {
651 BlockBuilder block_builder(builder());
652 ControlScopeForBreakable execution_control(this, stmt, &block_builder);
653 if (stmt->scope() != nullptr) {
654 VisitDeclarations(stmt->scope()->declarations());
655 }
656 VisitStatements(stmt->statements());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000657 if (stmt->labels() != nullptr) block_builder.EndBlock();
658}
659
660
661void BytecodeGenerator::VisitVariableDeclaration(VariableDeclaration* decl) {
662 Variable* variable = decl->proxy()->var();
663 VariableMode mode = decl->mode();
664 // Const and let variables are initialized with the hole so that we can
665 // check that they are only assigned once.
666 bool hole_init = mode == CONST || mode == CONST_LEGACY || mode == LET;
667 switch (variable->location()) {
668 case VariableLocation::GLOBAL:
669 case VariableLocation::UNALLOCATED: {
670 Handle<Oddball> value = variable->binding_needs_init()
671 ? isolate()->factory()->the_hole_value()
672 : isolate()->factory()->undefined_value();
673 globals()->push_back(variable->name());
674 globals()->push_back(value);
675 break;
676 }
677 case VariableLocation::LOCAL:
678 if (hole_init) {
679 Register destination(variable->index());
680 builder()->LoadTheHole().StoreAccumulatorInRegister(destination);
681 }
682 break;
683 case VariableLocation::PARAMETER:
684 if (hole_init) {
685 // The parameter indices are shifted by 1 (receiver is variable
686 // index -1 but is parameter index 0 in BytecodeArrayBuilder).
687 Register destination(builder()->Parameter(variable->index() + 1));
688 builder()->LoadTheHole().StoreAccumulatorInRegister(destination);
689 }
690 break;
691 case VariableLocation::CONTEXT:
692 if (hole_init) {
693 builder()->LoadTheHole().StoreContextSlot(execution_context()->reg(),
694 variable->index());
695 }
696 break;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100697 case VariableLocation::LOOKUP: {
698 DCHECK(IsDeclaredVariableMode(mode));
699
700 register_allocator()->PrepareForConsecutiveAllocations(3);
701 Register name = register_allocator()->NextConsecutiveRegister();
702 Register init_value = register_allocator()->NextConsecutiveRegister();
703 Register attributes = register_allocator()->NextConsecutiveRegister();
704
705 builder()->LoadLiteral(variable->name()).StoreAccumulatorInRegister(name);
706 if (hole_init) {
707 builder()->LoadTheHole().StoreAccumulatorInRegister(init_value);
708 } else {
709 // For variables, we must not use an initial value (such as 'undefined')
710 // because we may have a (legal) redeclaration and we must not destroy
711 // the current value.
712 builder()
713 ->LoadLiteral(Smi::FromInt(0))
714 .StoreAccumulatorInRegister(init_value);
715 }
716 builder()
717 ->LoadLiteral(Smi::FromInt(variable->DeclarationPropertyAttributes()))
718 .StoreAccumulatorInRegister(attributes)
719 .CallRuntime(Runtime::kDeclareLookupSlot, name, 3);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000720 break;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100721 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000722 }
723}
724
725
726void BytecodeGenerator::VisitFunctionDeclaration(FunctionDeclaration* decl) {
727 Variable* variable = decl->proxy()->var();
728 switch (variable->location()) {
729 case VariableLocation::GLOBAL:
730 case VariableLocation::UNALLOCATED: {
731 Handle<SharedFunctionInfo> function = Compiler::GetSharedFunctionInfo(
732 decl->fun(), info()->script(), info());
733 // Check for stack-overflow exception.
734 if (function.is_null()) return SetStackOverflow();
735 globals()->push_back(variable->name());
736 globals()->push_back(function);
737 break;
738 }
739 case VariableLocation::PARAMETER:
740 case VariableLocation::LOCAL: {
741 VisitForAccumulatorValue(decl->fun());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100742 DCHECK(variable->mode() == LET || variable->mode() == VAR ||
743 variable->mode() == CONST);
744 VisitVariableAssignment(variable, Token::INIT,
745 FeedbackVectorSlot::Invalid());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000746 break;
747 }
748 case VariableLocation::CONTEXT: {
749 DCHECK_EQ(0, execution_context()->ContextChainDepth(variable->scope()));
750 VisitForAccumulatorValue(decl->fun());
751 builder()->StoreContextSlot(execution_context()->reg(),
752 variable->index());
753 break;
754 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100755 case VariableLocation::LOOKUP: {
756 register_allocator()->PrepareForConsecutiveAllocations(3);
757 Register name = register_allocator()->NextConsecutiveRegister();
758 Register literal = register_allocator()->NextConsecutiveRegister();
759 Register attributes = register_allocator()->NextConsecutiveRegister();
760 builder()->LoadLiteral(variable->name()).StoreAccumulatorInRegister(name);
761
762 VisitForAccumulatorValue(decl->fun());
763 builder()
764 ->StoreAccumulatorInRegister(literal)
765 .LoadLiteral(Smi::FromInt(variable->DeclarationPropertyAttributes()))
766 .StoreAccumulatorInRegister(attributes)
767 .CallRuntime(Runtime::kDeclareLookupSlot, name, 3);
768 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000769 }
770}
771
772
773void BytecodeGenerator::VisitImportDeclaration(ImportDeclaration* decl) {
774 UNIMPLEMENTED();
775}
776
777
778void BytecodeGenerator::VisitExportDeclaration(ExportDeclaration* decl) {
779 UNIMPLEMENTED();
780}
781
782
783void BytecodeGenerator::VisitDeclarations(
784 ZoneList<Declaration*>* declarations) {
785 RegisterAllocationScope register_scope(this);
786 DCHECK(globals()->empty());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100787 for (int i = 0; i < declarations->length(); i++) {
788 RegisterAllocationScope register_scope(this);
789 Visit(declarations->at(i));
790 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000791 if (globals()->empty()) return;
792 int array_index = 0;
793 Handle<FixedArray> data = isolate()->factory()->NewFixedArray(
794 static_cast<int>(globals()->size()), TENURED);
795 for (Handle<Object> obj : *globals()) data->set(array_index++, *obj);
796 int encoded_flags = DeclareGlobalsEvalFlag::encode(info()->is_eval()) |
797 DeclareGlobalsNativeFlag::encode(info()->is_native()) |
798 DeclareGlobalsLanguageMode::encode(language_mode());
799
800 Register pairs = register_allocator()->NewRegister();
801 builder()->LoadLiteral(data);
802 builder()->StoreAccumulatorInRegister(pairs);
803
804 Register flags = register_allocator()->NewRegister();
805 builder()->LoadLiteral(Smi::FromInt(encoded_flags));
806 builder()->StoreAccumulatorInRegister(flags);
807 DCHECK(flags.index() == pairs.index() + 1);
808
809 builder()->CallRuntime(Runtime::kDeclareGlobals, pairs, 2);
810 globals()->clear();
811}
812
813
814void BytecodeGenerator::VisitStatements(ZoneList<Statement*>* statements) {
815 for (int i = 0; i < statements->length(); i++) {
816 // Allocate an outer register allocations scope for the statement.
817 RegisterAllocationScope allocation_scope(this);
818 Statement* stmt = statements->at(i);
819 Visit(stmt);
820 if (stmt->IsJump()) break;
821 }
822}
823
824
825void BytecodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100826 builder()->SetStatementPosition(stmt);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000827 VisitForEffect(stmt->expression());
828}
829
830
831void BytecodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) {
832}
833
834
835void BytecodeGenerator::VisitIfStatement(IfStatement* stmt) {
Ben Murdochda12d292016-06-02 14:46:10 +0100836 builder()->SetStatementPosition(stmt);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000837 BytecodeLabel else_label, end_label;
838 if (stmt->condition()->ToBooleanIsTrue()) {
839 // Generate then block unconditionally as always true.
840 Visit(stmt->then_statement());
841 } else if (stmt->condition()->ToBooleanIsFalse()) {
842 // Generate else block unconditionally if it exists.
843 if (stmt->HasElseStatement()) {
844 Visit(stmt->else_statement());
845 }
846 } else {
847 // TODO(oth): If then statement is BreakStatement or
848 // ContinueStatement we can reduce number of generated
849 // jump/jump_ifs here. See BasicLoops test.
850 VisitForAccumulatorValue(stmt->condition());
851 builder()->JumpIfFalse(&else_label);
852 Visit(stmt->then_statement());
853 if (stmt->HasElseStatement()) {
854 builder()->Jump(&end_label);
855 builder()->Bind(&else_label);
856 Visit(stmt->else_statement());
857 } else {
858 builder()->Bind(&else_label);
859 }
860 builder()->Bind(&end_label);
861 }
862}
863
864
865void BytecodeGenerator::VisitSloppyBlockFunctionStatement(
866 SloppyBlockFunctionStatement* stmt) {
867 Visit(stmt->statement());
868}
869
870
871void BytecodeGenerator::VisitContinueStatement(ContinueStatement* stmt) {
Ben Murdochda12d292016-06-02 14:46:10 +0100872 builder()->SetStatementPosition(stmt);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000873 execution_control()->Continue(stmt->target());
874}
875
876
877void BytecodeGenerator::VisitBreakStatement(BreakStatement* stmt) {
Ben Murdochda12d292016-06-02 14:46:10 +0100878 builder()->SetStatementPosition(stmt);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000879 execution_control()->Break(stmt->target());
880}
881
882
883void BytecodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100884 builder()->SetStatementPosition(stmt);
Ben Murdochda12d292016-06-02 14:46:10 +0100885 VisitForAccumulatorValue(stmt->expression());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100886 execution_control()->ReturnAccumulator();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000887}
888
889
890void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) {
Ben Murdochda12d292016-06-02 14:46:10 +0100891 builder()->SetStatementPosition(stmt);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100892 VisitForAccumulatorValue(stmt->expression());
893 builder()->CastAccumulatorToJSObject();
894 VisitNewLocalWithContext();
895 VisitInScope(stmt->statement(), stmt->scope());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000896}
897
898
899void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
900 // We need this scope because we visit for register values. We have to
901 // maintain a execution result scope where registers can be allocated.
902 ZoneList<CaseClause*>* clauses = stmt->cases();
903 SwitchBuilder switch_builder(builder(), clauses->length());
904 ControlScopeForBreakable scope(this, stmt, &switch_builder);
905 int default_index = -1;
906
Ben Murdochda12d292016-06-02 14:46:10 +0100907 builder()->SetStatementPosition(stmt);
908
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000909 // Keep the switch value in a register until a case matches.
910 Register tag = VisitForRegisterValue(stmt->tag());
911
912 // Iterate over all cases and create nodes for label comparison.
913 BytecodeLabel done_label;
914 for (int i = 0; i < clauses->length(); i++) {
915 CaseClause* clause = clauses->at(i);
916
917 // The default is not a test, remember index.
918 if (clause->is_default()) {
919 default_index = i;
920 continue;
921 }
922
923 // Perform label comparison as if via '===' with tag.
924 VisitForAccumulatorValue(clause->label());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100925 builder()->CompareOperation(Token::Value::EQ_STRICT, tag);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000926 switch_builder.Case(i);
927 }
928
929 if (default_index >= 0) {
930 // Emit default jump if there is a default case.
931 switch_builder.DefaultAt(default_index);
932 } else {
933 // Otherwise if we have reached here none of the cases matched, so jump to
934 // done.
935 builder()->Jump(&done_label);
936 }
937
938 // Iterate over all cases and create the case bodies.
939 for (int i = 0; i < clauses->length(); i++) {
940 CaseClause* clause = clauses->at(i);
941 switch_builder.SetCaseTarget(i);
942 VisitStatements(clause->statements());
943 }
944 builder()->Bind(&done_label);
945
946 switch_builder.SetBreakTarget(done_label);
947}
948
949
950void BytecodeGenerator::VisitCaseClause(CaseClause* clause) {
951 // Handled entirely in VisitSwitchStatement.
952 UNREACHABLE();
953}
954
Ben Murdoch097c5b22016-05-18 11:27:45 +0100955void BytecodeGenerator::VisitIterationBody(IterationStatement* stmt,
956 LoopBuilder* loop_builder) {
957 ControlScopeForIteration execution_control(this, stmt, loop_builder);
958 builder()->StackCheck();
959 Visit(stmt->body());
960}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000961
962void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
963 LoopBuilder loop_builder(builder());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000964 loop_builder.LoopHeader();
965 if (stmt->cond()->ToBooleanIsFalse()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100966 VisitIterationBody(stmt, &loop_builder);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000967 loop_builder.Condition();
968 } else if (stmt->cond()->ToBooleanIsTrue()) {
969 loop_builder.Condition();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100970 VisitIterationBody(stmt, &loop_builder);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000971 loop_builder.JumpToHeader();
972 } else {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100973 VisitIterationBody(stmt, &loop_builder);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000974 loop_builder.Condition();
Ben Murdochda12d292016-06-02 14:46:10 +0100975 builder()->SetExpressionAsStatementPosition(stmt->cond());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000976 VisitForAccumulatorValue(stmt->cond());
977 loop_builder.JumpToHeaderIfTrue();
978 }
979 loop_builder.EndLoop();
980}
981
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000982void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
983 if (stmt->cond()->ToBooleanIsFalse()) {
984 // If the condition is false there is no need to generate the loop.
985 return;
986 }
987
988 LoopBuilder loop_builder(builder());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000989 loop_builder.LoopHeader();
990 loop_builder.Condition();
991 if (!stmt->cond()->ToBooleanIsTrue()) {
Ben Murdochda12d292016-06-02 14:46:10 +0100992 builder()->SetExpressionAsStatementPosition(stmt->cond());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000993 VisitForAccumulatorValue(stmt->cond());
994 loop_builder.BreakIfFalse();
995 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100996 VisitIterationBody(stmt, &loop_builder);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000997 loop_builder.JumpToHeader();
998 loop_builder.EndLoop();
999}
1000
1001
1002void BytecodeGenerator::VisitForStatement(ForStatement* stmt) {
1003 if (stmt->init() != nullptr) {
1004 Visit(stmt->init());
1005 }
1006 if (stmt->cond() && stmt->cond()->ToBooleanIsFalse()) {
1007 // If the condition is known to be false there is no need to generate
1008 // body, next or condition blocks. Init block should be generated.
1009 return;
1010 }
1011
1012 LoopBuilder loop_builder(builder());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001013 loop_builder.LoopHeader();
1014 loop_builder.Condition();
1015 if (stmt->cond() && !stmt->cond()->ToBooleanIsTrue()) {
Ben Murdochda12d292016-06-02 14:46:10 +01001016 builder()->SetExpressionAsStatementPosition(stmt->cond());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001017 VisitForAccumulatorValue(stmt->cond());
1018 loop_builder.BreakIfFalse();
1019 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001020 VisitIterationBody(stmt, &loop_builder);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001021 if (stmt->next() != nullptr) {
1022 loop_builder.Next();
Ben Murdochda12d292016-06-02 14:46:10 +01001023 builder()->SetStatementPosition(stmt->next());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001024 Visit(stmt->next());
1025 }
1026 loop_builder.JumpToHeader();
1027 loop_builder.EndLoop();
1028}
1029
1030
1031void BytecodeGenerator::VisitForInAssignment(Expression* expr,
1032 FeedbackVectorSlot slot) {
1033 DCHECK(expr->IsValidReferenceExpression());
1034
1035 // Evaluate assignment starting with the value to be stored in the
1036 // accumulator.
1037 Property* property = expr->AsProperty();
1038 LhsKind assign_type = Property::GetAssignType(property);
1039 switch (assign_type) {
1040 case VARIABLE: {
1041 Variable* variable = expr->AsVariableProxy()->var();
Ben Murdoch097c5b22016-05-18 11:27:45 +01001042 VisitVariableAssignment(variable, Token::ASSIGN, slot);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001043 break;
1044 }
1045 case NAMED_PROPERTY: {
1046 RegisterAllocationScope register_scope(this);
1047 Register value = register_allocator()->NewRegister();
1048 builder()->StoreAccumulatorInRegister(value);
1049 Register object = VisitForRegisterValue(property->obj());
1050 Handle<String> name = property->key()->AsLiteral()->AsPropertyName();
1051 builder()->LoadAccumulatorWithRegister(value);
1052 builder()->StoreNamedProperty(object, name, feedback_index(slot),
1053 language_mode());
1054 break;
1055 }
1056 case KEYED_PROPERTY: {
1057 RegisterAllocationScope register_scope(this);
1058 Register value = register_allocator()->NewRegister();
1059 builder()->StoreAccumulatorInRegister(value);
1060 Register object = VisitForRegisterValue(property->obj());
1061 Register key = VisitForRegisterValue(property->key());
1062 builder()->LoadAccumulatorWithRegister(value);
1063 builder()->StoreKeyedProperty(object, key, feedback_index(slot),
1064 language_mode());
1065 break;
1066 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001067 case NAMED_SUPER_PROPERTY: {
1068 RegisterAllocationScope register_scope(this);
1069 register_allocator()->PrepareForConsecutiveAllocations(4);
1070 Register receiver = register_allocator()->NextConsecutiveRegister();
1071 Register home_object = register_allocator()->NextConsecutiveRegister();
1072 Register name = register_allocator()->NextConsecutiveRegister();
1073 Register value = register_allocator()->NextConsecutiveRegister();
1074 builder()->StoreAccumulatorInRegister(value);
1075 SuperPropertyReference* super_property =
1076 property->obj()->AsSuperPropertyReference();
1077 VisitForRegisterValue(super_property->this_var(), receiver);
1078 VisitForRegisterValue(super_property->home_object(), home_object);
1079 builder()
1080 ->LoadLiteral(property->key()->AsLiteral()->AsPropertyName())
1081 .StoreAccumulatorInRegister(name);
1082 BuildNamedSuperPropertyStore(receiver, home_object, name, value);
1083 break;
1084 }
1085 case KEYED_SUPER_PROPERTY: {
1086 RegisterAllocationScope register_scope(this);
1087 register_allocator()->PrepareForConsecutiveAllocations(4);
1088 Register receiver = register_allocator()->NextConsecutiveRegister();
1089 Register home_object = register_allocator()->NextConsecutiveRegister();
1090 Register key = register_allocator()->NextConsecutiveRegister();
1091 Register value = register_allocator()->NextConsecutiveRegister();
1092 builder()->StoreAccumulatorInRegister(value);
1093 SuperPropertyReference* super_property =
1094 property->obj()->AsSuperPropertyReference();
1095 VisitForRegisterValue(super_property->this_var(), receiver);
1096 VisitForRegisterValue(super_property->home_object(), home_object);
1097 VisitForRegisterValue(property->key(), key);
1098 BuildKeyedSuperPropertyStore(receiver, home_object, key, value);
1099 break;
1100 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001101 }
1102}
1103
1104
1105void BytecodeGenerator::VisitForInStatement(ForInStatement* stmt) {
1106 if (stmt->subject()->IsNullLiteral() ||
Ben Murdochda12d292016-06-02 14:46:10 +01001107 stmt->subject()->IsUndefinedLiteral()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001108 // ForIn generates lots of code, skip if it wouldn't produce any effects.
1109 return;
1110 }
1111
1112 LoopBuilder loop_builder(builder());
Ben Murdochda12d292016-06-02 14:46:10 +01001113 BytecodeLabel subject_null_label, subject_undefined_label;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001114
1115 // Prepare the state for executing ForIn.
Ben Murdochda12d292016-06-02 14:46:10 +01001116 builder()->SetExpressionAsStatementPosition(stmt->subject());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001117 VisitForAccumulatorValue(stmt->subject());
1118 builder()->JumpIfUndefined(&subject_undefined_label);
1119 builder()->JumpIfNull(&subject_null_label);
1120 Register receiver = register_allocator()->NewRegister();
1121 builder()->CastAccumulatorToJSObject();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001122 builder()->StoreAccumulatorInRegister(receiver);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001123
1124 register_allocator()->PrepareForConsecutiveAllocations(3);
1125 Register cache_type = register_allocator()->NextConsecutiveRegister();
1126 Register cache_array = register_allocator()->NextConsecutiveRegister();
1127 Register cache_length = register_allocator()->NextConsecutiveRegister();
Ben Murdochda12d292016-06-02 14:46:10 +01001128 // Used as kRegTriple and kRegPair in ForInPrepare and ForInNext.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001129 USE(cache_array);
1130 builder()->ForInPrepare(cache_type);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001131
1132 // Set up loop counter
1133 Register index = register_allocator()->NewRegister();
1134 builder()->LoadLiteral(Smi::FromInt(0));
1135 builder()->StoreAccumulatorInRegister(index);
1136
1137 // The loop
1138 loop_builder.LoopHeader();
Ben Murdochda12d292016-06-02 14:46:10 +01001139 builder()->SetExpressionAsStatementPosition(stmt->each());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001140 loop_builder.Condition();
1141 builder()->ForInDone(index, cache_length);
1142 loop_builder.BreakIfTrue();
Ben Murdoch097c5b22016-05-18 11:27:45 +01001143 DCHECK(Register::AreContiguous(cache_type, cache_array));
Ben Murdochda12d292016-06-02 14:46:10 +01001144 FeedbackVectorSlot slot = stmt->ForInFeedbackSlot();
1145 builder()->ForInNext(receiver, index, cache_type, feedback_index(slot));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001146 loop_builder.ContinueIfUndefined();
1147 VisitForInAssignment(stmt->each(), stmt->EachFeedbackSlot());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001148 VisitIterationBody(stmt, &loop_builder);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001149 loop_builder.Next();
1150 builder()->ForInStep(index);
1151 builder()->StoreAccumulatorInRegister(index);
1152 loop_builder.JumpToHeader();
1153 loop_builder.EndLoop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001154 builder()->Bind(&subject_null_label);
1155 builder()->Bind(&subject_undefined_label);
1156}
1157
1158
1159void BytecodeGenerator::VisitForOfStatement(ForOfStatement* stmt) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001160 LoopBuilder loop_builder(builder());
1161 ControlScopeForIteration control_scope(this, stmt, &loop_builder);
1162
1163 VisitForEffect(stmt->assign_iterator());
1164
1165 loop_builder.LoopHeader();
1166 loop_builder.Next();
Ben Murdochda12d292016-06-02 14:46:10 +01001167 builder()->SetExpressionAsStatementPosition(stmt->next_result());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001168 VisitForEffect(stmt->next_result());
1169 VisitForAccumulatorValue(stmt->result_done());
1170 loop_builder.BreakIfTrue();
1171
1172 VisitForEffect(stmt->assign_each());
1173 VisitIterationBody(stmt, &loop_builder);
1174 loop_builder.JumpToHeader();
1175 loop_builder.EndLoop();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001176}
1177
1178
1179void BytecodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001180 TryCatchBuilder try_control_builder(builder());
1181 Register no_reg;
1182
1183 // Preserve the context in a dedicated register, so that it can be restored
1184 // when the handler is entered by the stack-unwinding machinery.
1185 // TODO(mstarzinger): Be smarter about register allocation.
1186 Register context = register_allocator()->NewRegister();
1187 builder()->MoveRegister(Register::current_context(), context);
1188
1189 // Evaluate the try-block inside a control scope. This simulates a handler
1190 // that is intercepting 'throw' control commands.
1191 try_control_builder.BeginTry(context);
1192 {
1193 ControlScopeForTryCatch scope(this, &try_control_builder);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001194 Visit(stmt->try_block());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001195 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001196 try_control_builder.EndTry();
1197
1198 // Create a catch scope that binds the exception.
1199 VisitNewLocalCatchContext(stmt->variable());
1200 builder()->StoreAccumulatorInRegister(context);
1201
Ben Murdochda12d292016-06-02 14:46:10 +01001202 // If requested, clear message object as we enter the catch block.
1203 if (stmt->clear_pending_message()) {
1204 builder()->CallRuntime(Runtime::kInterpreterClearPendingMessage, no_reg, 0);
1205 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001206
1207 // Load the catch context into the accumulator.
1208 builder()->LoadAccumulatorWithRegister(context);
1209
1210 // Evaluate the catch-block.
1211 VisitInScope(stmt->catch_block(), stmt->scope());
1212 try_control_builder.EndCatch();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001213}
1214
1215
1216void BytecodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001217 TryFinallyBuilder try_control_builder(builder(), IsInsideTryCatch());
1218 Register no_reg;
1219
1220 // We keep a record of all paths that enter the finally-block to be able to
1221 // dispatch to the correct continuation point after the statements in the
1222 // finally-block have been evaluated.
1223 //
1224 // The try-finally construct can enter the finally-block in three ways:
1225 // 1. By exiting the try-block normally, falling through at the end.
1226 // 2. By exiting the try-block with a function-local control flow transfer
1227 // (i.e. through break/continue/return statements).
1228 // 3. By exiting the try-block with a thrown exception.
1229 //
1230 // The result register semantics depend on how the block was entered:
1231 // - ReturnStatement: It represents the return value being returned.
1232 // - ThrowStatement: It represents the exception being thrown.
1233 // - BreakStatement/ContinueStatement: Undefined and not used.
1234 // - Falling through into finally-block: Undefined and not used.
1235 Register token = register_allocator()->NewRegister();
1236 Register result = register_allocator()->NewRegister();
1237 ControlScope::DeferredCommands commands(this, token, result);
1238
1239 // Preserve the context in a dedicated register, so that it can be restored
1240 // when the handler is entered by the stack-unwinding machinery.
1241 // TODO(mstarzinger): Be smarter about register allocation.
1242 Register context = register_allocator()->NewRegister();
1243 builder()->MoveRegister(Register::current_context(), context);
1244
1245 // Evaluate the try-block inside a control scope. This simulates a handler
1246 // that is intercepting all control commands.
1247 try_control_builder.BeginTry(context);
1248 {
1249 ControlScopeForTryFinally scope(this, &try_control_builder, &commands);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001250 Visit(stmt->try_block());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001251 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001252 try_control_builder.EndTry();
1253
1254 // Record fall-through and exception cases.
1255 commands.RecordFallThroughPath();
1256 try_control_builder.LeaveTry();
1257 try_control_builder.BeginHandler();
1258 commands.RecordHandlerReThrowPath();
1259
1260 // Pending message object is saved on entry.
1261 try_control_builder.BeginFinally();
1262 Register message = context; // Reuse register.
1263
1264 // Clear message object as we enter the finally block.
1265 builder()
1266 ->CallRuntime(Runtime::kInterpreterClearPendingMessage, no_reg, 0)
1267 .StoreAccumulatorInRegister(message);
1268
1269 // Evaluate the finally-block.
1270 Visit(stmt->finally_block());
1271 try_control_builder.EndFinally();
1272
1273 // Pending message object is restored on exit.
1274 builder()->CallRuntime(Runtime::kInterpreterSetPendingMessage, message, 1);
1275
1276 // Dynamic dispatch after the finally-block.
1277 commands.ApplyDeferredCommands();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001278}
1279
1280
1281void BytecodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001282 builder()->SetStatementPosition(stmt);
1283 builder()->Debugger();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001284}
1285
1286
1287void BytecodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
1288 // Find or build a shared function info.
1289 Handle<SharedFunctionInfo> shared_info =
1290 Compiler::GetSharedFunctionInfo(expr, info()->script(), info());
Ben Murdochda12d292016-06-02 14:46:10 +01001291 if (shared_info.is_null()) {
1292 return SetStackOverflow();
1293 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001294 builder()->CreateClosure(shared_info,
1295 expr->pretenure() ? TENURED : NOT_TENURED);
1296 execution_result()->SetResultInAccumulator();
1297}
1298
1299
1300void BytecodeGenerator::VisitClassLiteral(ClassLiteral* expr) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001301 if (expr->scope()->ContextLocalCount() > 0) {
1302 VisitNewLocalBlockContext(expr->scope());
1303 ContextScope scope(this, expr->scope());
1304 VisitDeclarations(expr->scope()->declarations());
1305 VisitClassLiteralContents(expr);
1306 } else {
1307 VisitDeclarations(expr->scope()->declarations());
1308 VisitClassLiteralContents(expr);
1309 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001310}
1311
Ben Murdoch097c5b22016-05-18 11:27:45 +01001312void BytecodeGenerator::VisitClassLiteralContents(ClassLiteral* expr) {
1313 VisitClassLiteralForRuntimeDefinition(expr);
1314
1315 // Load the "prototype" from the constructor.
1316 register_allocator()->PrepareForConsecutiveAllocations(2);
1317 Register literal = register_allocator()->NextConsecutiveRegister();
1318 Register prototype = register_allocator()->NextConsecutiveRegister();
1319 Handle<String> name = isolate()->factory()->prototype_string();
1320 FeedbackVectorSlot slot = expr->PrototypeSlot();
1321 builder()
1322 ->StoreAccumulatorInRegister(literal)
1323 .LoadNamedProperty(literal, name, feedback_index(slot))
1324 .StoreAccumulatorInRegister(prototype);
1325
1326 VisitClassLiteralProperties(expr, literal, prototype);
1327 builder()->CallRuntime(Runtime::kFinalizeClassDefinition, literal, 2);
1328 // Assign to class variable.
1329 if (expr->class_variable_proxy() != nullptr) {
1330 Variable* var = expr->class_variable_proxy()->var();
1331 FeedbackVectorSlot slot = expr->NeedsProxySlot()
1332 ? expr->ProxySlot()
1333 : FeedbackVectorSlot::Invalid();
1334 VisitVariableAssignment(var, Token::INIT, slot);
1335 }
1336 execution_result()->SetResultInAccumulator();
1337}
1338
1339void BytecodeGenerator::VisitClassLiteralForRuntimeDefinition(
1340 ClassLiteral* expr) {
1341 AccumulatorResultScope result_scope(this);
1342 register_allocator()->PrepareForConsecutiveAllocations(4);
1343 Register extends = register_allocator()->NextConsecutiveRegister();
1344 Register constructor = register_allocator()->NextConsecutiveRegister();
1345 Register start_position = register_allocator()->NextConsecutiveRegister();
1346 Register end_position = register_allocator()->NextConsecutiveRegister();
1347
1348 VisitForAccumulatorValueOrTheHole(expr->extends());
1349 builder()->StoreAccumulatorInRegister(extends);
1350
1351 VisitForAccumulatorValue(expr->constructor());
1352 builder()
1353 ->StoreAccumulatorInRegister(constructor)
1354 .LoadLiteral(Smi::FromInt(expr->start_position()))
1355 .StoreAccumulatorInRegister(start_position)
1356 .LoadLiteral(Smi::FromInt(expr->end_position()))
1357 .StoreAccumulatorInRegister(end_position)
1358 .CallRuntime(Runtime::kDefineClass, extends, 4);
1359 result_scope.SetResultInAccumulator();
1360}
1361
1362void BytecodeGenerator::VisitClassLiteralProperties(ClassLiteral* expr,
1363 Register literal,
1364 Register prototype) {
1365 RegisterAllocationScope register_scope(this);
1366 register_allocator()->PrepareForConsecutiveAllocations(5);
1367 Register receiver = register_allocator()->NextConsecutiveRegister();
1368 Register key = register_allocator()->NextConsecutiveRegister();
1369 Register value = register_allocator()->NextConsecutiveRegister();
1370 Register attr = register_allocator()->NextConsecutiveRegister();
1371 Register set_function_name = register_allocator()->NextConsecutiveRegister();
1372
1373 bool attr_assigned = false;
1374 Register old_receiver = Register::invalid_value();
1375
1376 // Create nodes to store method values into the literal.
1377 for (int i = 0; i < expr->properties()->length(); i++) {
1378 ObjectLiteral::Property* property = expr->properties()->at(i);
1379
1380 // Set-up receiver.
1381 Register new_receiver = property->is_static() ? literal : prototype;
1382 if (new_receiver != old_receiver) {
1383 builder()->MoveRegister(new_receiver, receiver);
1384 old_receiver = new_receiver;
1385 }
1386
1387 VisitForAccumulatorValue(property->key());
1388 builder()->CastAccumulatorToName().StoreAccumulatorInRegister(key);
1389 // The static prototype property is read only. We handle the non computed
1390 // property name case in the parser. Since this is the only case where we
1391 // need to check for an own read only property we special case this so we do
1392 // not need to do this for every property.
1393 if (property->is_static() && property->is_computed_name()) {
1394 VisitClassLiteralStaticPrototypeWithComputedName(key);
1395 }
1396 VisitForAccumulatorValue(property->value());
1397 builder()->StoreAccumulatorInRegister(value);
1398
1399 VisitSetHomeObject(value, receiver, property);
1400
1401 if (!attr_assigned) {
1402 builder()
1403 ->LoadLiteral(Smi::FromInt(DONT_ENUM))
1404 .StoreAccumulatorInRegister(attr);
1405 attr_assigned = true;
1406 }
1407
1408 switch (property->kind()) {
1409 case ObjectLiteral::Property::CONSTANT:
1410 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1411 case ObjectLiteral::Property::PROTOTYPE:
1412 // Invalid properties for ES6 classes.
1413 UNREACHABLE();
1414 break;
1415 case ObjectLiteral::Property::COMPUTED: {
1416 builder()
1417 ->LoadLiteral(Smi::FromInt(property->NeedsSetFunctionName()))
1418 .StoreAccumulatorInRegister(set_function_name);
1419 builder()->CallRuntime(Runtime::kDefineDataPropertyInLiteral, receiver,
1420 5);
1421 break;
1422 }
1423 case ObjectLiteral::Property::GETTER: {
1424 builder()->CallRuntime(Runtime::kDefineGetterPropertyUnchecked,
1425 receiver, 4);
1426 break;
1427 }
1428 case ObjectLiteral::Property::SETTER: {
1429 builder()->CallRuntime(Runtime::kDefineSetterPropertyUnchecked,
1430 receiver, 4);
1431 break;
1432 }
1433 }
1434 }
1435}
1436
1437void BytecodeGenerator::VisitClassLiteralStaticPrototypeWithComputedName(
1438 Register key) {
1439 BytecodeLabel done;
1440 builder()
1441 ->LoadLiteral(isolate()->factory()->prototype_string())
1442 .CompareOperation(Token::Value::EQ_STRICT, key)
1443 .JumpIfFalse(&done)
1444 .CallRuntime(Runtime::kThrowStaticPrototypeError, Register(0), 0)
1445 .Bind(&done);
1446}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001447
1448void BytecodeGenerator::VisitNativeFunctionLiteral(
1449 NativeFunctionLiteral* expr) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001450 // Find or build a shared function info for the native function template.
1451 Handle<SharedFunctionInfo> shared_info =
1452 Compiler::GetSharedFunctionInfoForNative(expr->extension(), expr->name());
1453 builder()->CreateClosure(shared_info, NOT_TENURED);
1454 execution_result()->SetResultInAccumulator();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001455}
1456
1457
1458void BytecodeGenerator::VisitDoExpression(DoExpression* expr) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001459 VisitBlock(expr->block());
1460 VisitVariableProxy(expr->result());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001461}
1462
1463
1464void BytecodeGenerator::VisitConditional(Conditional* expr) {
1465 // TODO(rmcilroy): Spot easy cases where there code would not need to
1466 // emit the then block or the else block, e.g. condition is
1467 // obviously true/1/false/0.
1468
1469 BytecodeLabel else_label, end_label;
1470
1471 VisitForAccumulatorValue(expr->condition());
1472 builder()->JumpIfFalse(&else_label);
1473
1474 VisitForAccumulatorValue(expr->then_expression());
1475 builder()->Jump(&end_label);
1476
1477 builder()->Bind(&else_label);
1478 VisitForAccumulatorValue(expr->else_expression());
1479 builder()->Bind(&end_label);
1480
1481 execution_result()->SetResultInAccumulator();
1482}
1483
1484
1485void BytecodeGenerator::VisitLiteral(Literal* expr) {
1486 if (!execution_result()->IsEffect()) {
1487 Handle<Object> value = expr->value();
1488 if (value->IsSmi()) {
1489 builder()->LoadLiteral(Smi::cast(*value));
1490 } else if (value->IsUndefined()) {
1491 builder()->LoadUndefined();
1492 } else if (value->IsTrue()) {
1493 builder()->LoadTrue();
1494 } else if (value->IsFalse()) {
1495 builder()->LoadFalse();
1496 } else if (value->IsNull()) {
1497 builder()->LoadNull();
1498 } else if (value->IsTheHole()) {
1499 builder()->LoadTheHole();
1500 } else {
1501 builder()->LoadLiteral(value);
1502 }
1503 execution_result()->SetResultInAccumulator();
1504 }
1505}
1506
1507
1508void BytecodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
1509 // Materialize a regular expression literal.
1510 builder()->CreateRegExpLiteral(expr->pattern(), expr->literal_index(),
1511 expr->flags());
1512 execution_result()->SetResultInAccumulator();
1513}
1514
1515
1516void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
1517 // Deep-copy the literal boilerplate.
1518 builder()->CreateObjectLiteral(expr->constant_properties(),
1519 expr->literal_index(),
1520 expr->ComputeFlags(true));
Ben Murdoch097c5b22016-05-18 11:27:45 +01001521
1522 // Allocate in the outer scope since this register is used to return the
1523 // expression's results to the caller.
1524 Register literal = register_allocator()->outer()->NewRegister();
1525 builder()->StoreAccumulatorInRegister(literal);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001526
1527 // Store computed values into the literal.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001528 int property_index = 0;
1529 AccessorTable accessor_table(zone());
1530 for (; property_index < expr->properties()->length(); property_index++) {
1531 ObjectLiteral::Property* property = expr->properties()->at(property_index);
1532 if (property->is_computed_name()) break;
1533 if (property->IsCompileTimeValue()) continue;
1534
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001535 RegisterAllocationScope inner_register_scope(this);
1536 Literal* literal_key = property->key()->AsLiteral();
1537 switch (property->kind()) {
1538 case ObjectLiteral::Property::CONSTANT:
1539 UNREACHABLE();
1540 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1541 DCHECK(!CompileTimeValue::IsCompileTimeValue(property->value()));
1542 // Fall through.
1543 case ObjectLiteral::Property::COMPUTED: {
1544 // It is safe to use [[Put]] here because the boilerplate already
1545 // contains computed properties with an uninitialized value.
1546 if (literal_key->value()->IsInternalizedString()) {
1547 if (property->emit_store()) {
1548 VisitForAccumulatorValue(property->value());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001549 if (FunctionLiteral::NeedsHomeObject(property->value())) {
1550 RegisterAllocationScope register_scope(this);
1551 Register value = register_allocator()->NewRegister();
1552 builder()->StoreAccumulatorInRegister(value);
1553 builder()->StoreNamedProperty(
1554 literal, literal_key->AsPropertyName(),
1555 feedback_index(property->GetSlot(0)), language_mode());
1556 VisitSetHomeObject(value, literal, property, 1);
1557 } else {
1558 builder()->StoreNamedProperty(
1559 literal, literal_key->AsPropertyName(),
1560 feedback_index(property->GetSlot(0)), language_mode());
1561 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001562 } else {
1563 VisitForEffect(property->value());
1564 }
1565 } else {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001566 register_allocator()->PrepareForConsecutiveAllocations(4);
1567 Register literal_argument =
1568 register_allocator()->NextConsecutiveRegister();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001569 Register key = register_allocator()->NextConsecutiveRegister();
1570 Register value = register_allocator()->NextConsecutiveRegister();
1571 Register language = register_allocator()->NextConsecutiveRegister();
Ben Murdoch097c5b22016-05-18 11:27:45 +01001572
1573 builder()->MoveRegister(literal, literal_argument);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001574 VisitForAccumulatorValue(property->key());
1575 builder()->StoreAccumulatorInRegister(key);
1576 VisitForAccumulatorValue(property->value());
1577 builder()->StoreAccumulatorInRegister(value);
1578 if (property->emit_store()) {
1579 builder()
1580 ->LoadLiteral(Smi::FromInt(SLOPPY))
1581 .StoreAccumulatorInRegister(language)
Ben Murdoch097c5b22016-05-18 11:27:45 +01001582 .CallRuntime(Runtime::kSetProperty, literal_argument, 4);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001583 VisitSetHomeObject(value, literal, property);
1584 }
1585 }
1586 break;
1587 }
1588 case ObjectLiteral::Property::PROTOTYPE: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001589 DCHECK(property->emit_store());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001590 register_allocator()->PrepareForConsecutiveAllocations(2);
1591 Register literal_argument =
1592 register_allocator()->NextConsecutiveRegister();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001593 Register value = register_allocator()->NextConsecutiveRegister();
Ben Murdoch097c5b22016-05-18 11:27:45 +01001594
1595 builder()->MoveRegister(literal, literal_argument);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001596 VisitForAccumulatorValue(property->value());
1597 builder()->StoreAccumulatorInRegister(value).CallRuntime(
Ben Murdoch097c5b22016-05-18 11:27:45 +01001598 Runtime::kInternalSetPrototype, literal_argument, 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001599 break;
1600 }
1601 case ObjectLiteral::Property::GETTER:
1602 if (property->emit_store()) {
1603 accessor_table.lookup(literal_key)->second->getter = property;
1604 }
1605 break;
1606 case ObjectLiteral::Property::SETTER:
1607 if (property->emit_store()) {
1608 accessor_table.lookup(literal_key)->second->setter = property;
1609 }
1610 break;
1611 }
1612 }
1613
1614 // Define accessors, using only a single call to the runtime for each pair of
1615 // corresponding getters and setters.
1616 for (AccessorTable::Iterator it = accessor_table.begin();
1617 it != accessor_table.end(); ++it) {
1618 RegisterAllocationScope inner_register_scope(this);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001619 register_allocator()->PrepareForConsecutiveAllocations(5);
1620 Register literal_argument = register_allocator()->NextConsecutiveRegister();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001621 Register name = register_allocator()->NextConsecutiveRegister();
1622 Register getter = register_allocator()->NextConsecutiveRegister();
1623 Register setter = register_allocator()->NextConsecutiveRegister();
1624 Register attr = register_allocator()->NextConsecutiveRegister();
Ben Murdoch097c5b22016-05-18 11:27:45 +01001625
1626 builder()->MoveRegister(literal, literal_argument);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001627 VisitForAccumulatorValue(it->first);
1628 builder()->StoreAccumulatorInRegister(name);
1629 VisitObjectLiteralAccessor(literal, it->second->getter, getter);
1630 VisitObjectLiteralAccessor(literal, it->second->setter, setter);
1631 builder()
1632 ->LoadLiteral(Smi::FromInt(NONE))
1633 .StoreAccumulatorInRegister(attr)
Ben Murdoch097c5b22016-05-18 11:27:45 +01001634 .CallRuntime(Runtime::kDefineAccessorPropertyUnchecked,
1635 literal_argument, 5);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001636 }
1637
1638 // Object literals have two parts. The "static" part on the left contains no
1639 // computed property names, and so we can compute its map ahead of time; see
1640 // Runtime_CreateObjectLiteralBoilerplate. The second "dynamic" part starts
1641 // with the first computed property name and continues with all properties to
1642 // its right. All the code from above initializes the static component of the
1643 // object literal, and arranges for the map of the result to reflect the
1644 // static order in which the keys appear. For the dynamic properties, we
1645 // compile them into a series of "SetOwnProperty" runtime calls. This will
1646 // preserve insertion order.
1647 for (; property_index < expr->properties()->length(); property_index++) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001648 ObjectLiteral::Property* property = expr->properties()->at(property_index);
1649 RegisterAllocationScope inner_register_scope(this);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001650
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001651 if (property->kind() == ObjectLiteral::Property::PROTOTYPE) {
1652 DCHECK(property->emit_store());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001653 register_allocator()->PrepareForConsecutiveAllocations(2);
1654 Register literal_argument =
1655 register_allocator()->NextConsecutiveRegister();
1656 Register value = register_allocator()->NextConsecutiveRegister();
1657
1658 builder()->MoveRegister(literal, literal_argument);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001659 VisitForAccumulatorValue(property->value());
1660 builder()->StoreAccumulatorInRegister(value).CallRuntime(
Ben Murdoch097c5b22016-05-18 11:27:45 +01001661 Runtime::kInternalSetPrototype, literal_argument, 2);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001662 continue;
1663 }
1664
Ben Murdoch097c5b22016-05-18 11:27:45 +01001665 register_allocator()->PrepareForConsecutiveAllocations(5);
1666 Register literal_argument = register_allocator()->NextConsecutiveRegister();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001667 Register key = register_allocator()->NextConsecutiveRegister();
1668 Register value = register_allocator()->NextConsecutiveRegister();
1669 Register attr = register_allocator()->NextConsecutiveRegister();
Ben Murdoch097c5b22016-05-18 11:27:45 +01001670 DCHECK(Register::AreContiguous(literal_argument, key, value, attr));
1671 Register set_function_name =
1672 register_allocator()->NextConsecutiveRegister();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001673
Ben Murdoch097c5b22016-05-18 11:27:45 +01001674 builder()->MoveRegister(literal, literal_argument);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001675 VisitForAccumulatorValue(property->key());
1676 builder()->CastAccumulatorToName().StoreAccumulatorInRegister(key);
1677 VisitForAccumulatorValue(property->value());
1678 builder()->StoreAccumulatorInRegister(value);
1679 VisitSetHomeObject(value, literal, property);
1680 builder()->LoadLiteral(Smi::FromInt(NONE)).StoreAccumulatorInRegister(attr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001681 switch (property->kind()) {
1682 case ObjectLiteral::Property::CONSTANT:
1683 case ObjectLiteral::Property::COMPUTED:
1684 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
Ben Murdoch097c5b22016-05-18 11:27:45 +01001685 builder()
1686 ->LoadLiteral(Smi::FromInt(property->NeedsSetFunctionName()))
1687 .StoreAccumulatorInRegister(set_function_name);
1688 builder()->CallRuntime(Runtime::kDefineDataPropertyInLiteral,
1689 literal_argument, 5);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001690 break;
1691 case ObjectLiteral::Property::PROTOTYPE:
1692 UNREACHABLE(); // Handled specially above.
1693 break;
1694 case ObjectLiteral::Property::GETTER:
Ben Murdoch097c5b22016-05-18 11:27:45 +01001695 builder()->CallRuntime(Runtime::kDefineGetterPropertyUnchecked,
1696 literal_argument, 4);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001697 break;
1698 case ObjectLiteral::Property::SETTER:
Ben Murdoch097c5b22016-05-18 11:27:45 +01001699 builder()->CallRuntime(Runtime::kDefineSetterPropertyUnchecked,
1700 literal_argument, 4);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001701 break;
1702 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001703 }
1704
Ben Murdoch097c5b22016-05-18 11:27:45 +01001705 execution_result()->SetResultInRegister(literal);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001706}
1707
1708
1709void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
1710 // Deep-copy the literal boilerplate.
1711 builder()->CreateArrayLiteral(expr->constant_elements(),
1712 expr->literal_index(),
1713 expr->ComputeFlags(true));
1714 Register index, literal;
1715
1716 // Evaluate all the non-constant subexpressions and store them into the
1717 // newly cloned array.
1718 bool literal_in_accumulator = true;
1719 for (int array_index = 0; array_index < expr->values()->length();
1720 array_index++) {
1721 Expression* subexpr = expr->values()->at(array_index);
1722 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
Ben Murdoch097c5b22016-05-18 11:27:45 +01001723 DCHECK(!subexpr->IsSpread());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001724
1725 if (literal_in_accumulator) {
1726 index = register_allocator()->NewRegister();
1727 literal = register_allocator()->NewRegister();
1728 builder()->StoreAccumulatorInRegister(literal);
1729 literal_in_accumulator = false;
1730 }
1731
1732 FeedbackVectorSlot slot = expr->LiteralFeedbackSlot();
1733 builder()
1734 ->LoadLiteral(Smi::FromInt(array_index))
1735 .StoreAccumulatorInRegister(index);
1736 VisitForAccumulatorValue(subexpr);
1737 builder()->StoreKeyedProperty(literal, index, feedback_index(slot),
1738 language_mode());
1739 }
1740
1741 if (!literal_in_accumulator) {
1742 // Restore literal array into accumulator.
1743 builder()->LoadAccumulatorWithRegister(literal);
1744 }
1745 execution_result()->SetResultInAccumulator();
1746}
1747
1748
1749void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) {
Ben Murdochda12d292016-06-02 14:46:10 +01001750 builder()->SetExpressionPosition(proxy);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001751 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot());
1752}
1753
Ben Murdoch097c5b22016-05-18 11:27:45 +01001754void BytecodeGenerator::BuildHoleCheckForVariableLoad(VariableMode mode,
1755 Handle<String> name) {
1756 if (mode == CONST_LEGACY) {
1757 BytecodeLabel end_label;
1758 builder()->JumpIfNotHole(&end_label).LoadUndefined().Bind(&end_label);
1759 } else if (mode == LET || mode == CONST) {
1760 BuildThrowIfHole(name);
1761 }
1762}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001763
1764void BytecodeGenerator::VisitVariableLoad(Variable* variable,
1765 FeedbackVectorSlot slot,
1766 TypeofMode typeof_mode) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001767 VariableMode mode = variable->mode();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001768 switch (variable->location()) {
1769 case VariableLocation::LOCAL: {
1770 Register source(Register(variable->index()));
1771 builder()->LoadAccumulatorWithRegister(source);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001772 BuildHoleCheckForVariableLoad(mode, variable->name());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001773 execution_result()->SetResultInAccumulator();
1774 break;
1775 }
1776 case VariableLocation::PARAMETER: {
1777 // The parameter indices are shifted by 1 (receiver is variable
1778 // index -1 but is parameter index 0 in BytecodeArrayBuilder).
1779 Register source = builder()->Parameter(variable->index() + 1);
1780 builder()->LoadAccumulatorWithRegister(source);
Ben Murdoch097c5b22016-05-18 11:27:45 +01001781 BuildHoleCheckForVariableLoad(mode, variable->name());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001782 execution_result()->SetResultInAccumulator();
1783 break;
1784 }
1785 case VariableLocation::GLOBAL:
1786 case VariableLocation::UNALLOCATED: {
1787 builder()->LoadGlobal(variable->name(), feedback_index(slot),
Ben Murdoch097c5b22016-05-18 11:27:45 +01001788 typeof_mode);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001789 execution_result()->SetResultInAccumulator();
1790 break;
1791 }
1792 case VariableLocation::CONTEXT: {
1793 int depth = execution_context()->ContextChainDepth(variable->scope());
1794 ContextScope* context = execution_context()->Previous(depth);
1795 Register context_reg;
1796 if (context) {
1797 context_reg = context->reg();
1798 } else {
1799 context_reg = register_allocator()->NewRegister();
1800 // Walk the context chain to find the context at the given depth.
1801 // TODO(rmcilroy): Perform this work in a bytecode handler once we have
1802 // a generic mechanism for performing jumps in interpreter.cc.
1803 // TODO(mythria): Also update bytecode graph builder with correct depth
1804 // when this changes.
1805 builder()
1806 ->LoadAccumulatorWithRegister(execution_context()->reg())
1807 .StoreAccumulatorInRegister(context_reg);
1808 for (int i = 0; i < depth; ++i) {
1809 builder()
1810 ->LoadContextSlot(context_reg, Context::PREVIOUS_INDEX)
1811 .StoreAccumulatorInRegister(context_reg);
1812 }
1813 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001814
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001815 builder()->LoadContextSlot(context_reg, variable->index());
Ben Murdoch097c5b22016-05-18 11:27:45 +01001816 BuildHoleCheckForVariableLoad(mode, variable->name());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001817 execution_result()->SetResultInAccumulator();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001818 break;
1819 }
1820 case VariableLocation::LOOKUP: {
1821 builder()->LoadLookupSlot(variable->name(), typeof_mode);
1822 execution_result()->SetResultInAccumulator();
1823 break;
1824 }
1825 }
1826}
1827
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001828void BytecodeGenerator::VisitVariableLoadForAccumulatorValue(
1829 Variable* variable, FeedbackVectorSlot slot, TypeofMode typeof_mode) {
1830 AccumulatorResultScope accumulator_result(this);
1831 VisitVariableLoad(variable, slot, typeof_mode);
1832}
1833
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001834Register BytecodeGenerator::VisitVariableLoadForRegisterValue(
1835 Variable* variable, FeedbackVectorSlot slot, TypeofMode typeof_mode) {
1836 RegisterResultScope register_scope(this);
1837 VisitVariableLoad(variable, slot, typeof_mode);
1838 return register_scope.ResultRegister();
1839}
1840
Ben Murdoch097c5b22016-05-18 11:27:45 +01001841void BytecodeGenerator::BuildNamedSuperPropertyLoad(Register receiver,
1842 Register home_object,
1843 Register name) {
1844 DCHECK(Register::AreContiguous(receiver, home_object, name));
1845 builder()->CallRuntime(Runtime::kLoadFromSuper, receiver, 3);
1846}
1847
1848void BytecodeGenerator::BuildKeyedSuperPropertyLoad(Register receiver,
1849 Register home_object,
1850 Register key) {
1851 DCHECK(Register::AreContiguous(receiver, home_object, key));
1852 builder()->CallRuntime(Runtime::kLoadKeyedFromSuper, receiver, 3);
1853}
1854
1855void BytecodeGenerator::BuildNamedSuperPropertyStore(Register receiver,
1856 Register home_object,
1857 Register name,
1858 Register value) {
1859 DCHECK(Register::AreContiguous(receiver, home_object, name, value));
1860 Runtime::FunctionId function_id = is_strict(language_mode())
1861 ? Runtime::kStoreToSuper_Strict
1862 : Runtime::kStoreToSuper_Sloppy;
1863 builder()->CallRuntime(function_id, receiver, 4);
1864}
1865
1866void BytecodeGenerator::BuildKeyedSuperPropertyStore(Register receiver,
1867 Register home_object,
1868 Register key,
1869 Register value) {
1870 DCHECK(Register::AreContiguous(receiver, home_object, key, value));
1871 Runtime::FunctionId function_id = is_strict(language_mode())
1872 ? Runtime::kStoreKeyedToSuper_Strict
1873 : Runtime::kStoreKeyedToSuper_Sloppy;
1874 builder()->CallRuntime(function_id, receiver, 4);
1875}
1876
1877void BytecodeGenerator::BuildThrowReferenceError(Handle<String> name) {
1878 RegisterAllocationScope register_scope(this);
1879 Register name_reg = register_allocator()->NewRegister();
1880 builder()->LoadLiteral(name).StoreAccumulatorInRegister(name_reg).CallRuntime(
1881 Runtime::kThrowReferenceError, name_reg, 1);
1882}
1883
1884void BytecodeGenerator::BuildThrowIfHole(Handle<String> name) {
1885 // TODO(interpreter): Can the parser reduce the number of checks
1886 // performed? Or should there be a ThrowIfHole bytecode.
1887 BytecodeLabel no_reference_error;
1888 builder()->JumpIfNotHole(&no_reference_error);
1889 BuildThrowReferenceError(name);
1890 builder()->Bind(&no_reference_error);
1891}
1892
1893void BytecodeGenerator::BuildThrowIfNotHole(Handle<String> name) {
1894 // TODO(interpreter): Can the parser reduce the number of checks
1895 // performed? Or should there be a ThrowIfNotHole bytecode.
1896 BytecodeLabel no_reference_error, reference_error;
1897 builder()
1898 ->JumpIfNotHole(&reference_error)
1899 .Jump(&no_reference_error)
1900 .Bind(&reference_error);
1901 BuildThrowReferenceError(name);
1902 builder()->Bind(&no_reference_error);
1903}
1904
1905void BytecodeGenerator::BuildThrowReassignConstant(Handle<String> name) {
1906 // TODO(mythria): This will be replaced by a new bytecode that throws an
1907 // appropriate error depending on the whether the value is a hole or not.
1908 BytecodeLabel const_assign_error;
1909 builder()->JumpIfNotHole(&const_assign_error);
1910 BuildThrowReferenceError(name);
1911 builder()
1912 ->Bind(&const_assign_error)
1913 .CallRuntime(Runtime::kThrowConstAssignError, Register(), 0);
1914}
1915
1916void BytecodeGenerator::BuildHoleCheckForVariableAssignment(Variable* variable,
1917 Token::Value op) {
1918 VariableMode mode = variable->mode();
1919 DCHECK(mode != CONST_LEGACY);
1920 if (mode == CONST && op != Token::INIT) {
1921 // Non-intializing assignments to constant is not allowed.
1922 BuildThrowReassignConstant(variable->name());
1923 } else if (mode == LET && op != Token::INIT) {
1924 // Perform an initialization check for let declared variables.
1925 // E.g. let x = (x = 20); is not allowed.
1926 BuildThrowIfHole(variable->name());
1927 } else {
1928 DCHECK(variable->is_this() && mode == CONST && op == Token::INIT);
1929 // Perform an initialization check for 'this'. 'this' variable is the
1930 // only variable able to trigger bind operations outside the TDZ
1931 // via 'super' calls.
1932 BuildThrowIfNotHole(variable->name());
1933 }
1934}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001935
1936void BytecodeGenerator::VisitVariableAssignment(Variable* variable,
Ben Murdoch097c5b22016-05-18 11:27:45 +01001937 Token::Value op,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001938 FeedbackVectorSlot slot) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001939 VariableMode mode = variable->mode();
1940 RegisterAllocationScope assignment_register_scope(this);
1941 BytecodeLabel end_label;
1942 bool hole_check_required =
1943 (mode == CONST_LEGACY) || (mode == LET && op != Token::INIT) ||
1944 (mode == CONST && op != Token::INIT) ||
1945 (mode == CONST && op == Token::INIT && variable->is_this());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001946 switch (variable->location()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001947 case VariableLocation::PARAMETER:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001948 case VariableLocation::LOCAL: {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001949 Register destination;
1950 if (VariableLocation::PARAMETER == variable->location()) {
1951 destination = Register(builder()->Parameter(variable->index() + 1));
1952 } else {
1953 destination = Register(variable->index());
1954 }
1955
1956 if (hole_check_required) {
1957 // Load destination to check for hole.
1958 Register value_temp = register_allocator()->NewRegister();
1959 builder()
1960 ->StoreAccumulatorInRegister(value_temp)
1961 .LoadAccumulatorWithRegister(destination);
1962
1963 if (mode == CONST_LEGACY && op == Token::INIT) {
1964 // Perform an intialization check for legacy constants.
1965 builder()
1966 ->JumpIfNotHole(&end_label)
1967 .MoveRegister(value_temp, destination)
1968 .Bind(&end_label)
1969 .LoadAccumulatorWithRegister(value_temp);
1970 // Break here because the value should not be stored unconditionally.
1971 break;
1972 } else if (mode == CONST_LEGACY && op != Token::INIT) {
1973 DCHECK(!is_strict(language_mode()));
1974 // Ensure accumulator is in the correct state.
1975 builder()->LoadAccumulatorWithRegister(value_temp);
1976 // Break here, non-initializing assignments to legacy constants are
1977 // ignored.
1978 break;
1979 } else {
1980 BuildHoleCheckForVariableAssignment(variable, op);
1981 builder()->LoadAccumulatorWithRegister(value_temp);
1982 }
1983 }
1984
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001985 builder()->StoreAccumulatorInRegister(destination);
1986 break;
1987 }
1988 case VariableLocation::GLOBAL:
1989 case VariableLocation::UNALLOCATED: {
1990 builder()->StoreGlobal(variable->name(), feedback_index(slot),
1991 language_mode());
1992 break;
1993 }
1994 case VariableLocation::CONTEXT: {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001995 int depth = execution_context()->ContextChainDepth(variable->scope());
1996 ContextScope* context = execution_context()->Previous(depth);
1997 Register context_reg;
Ben Murdoch097c5b22016-05-18 11:27:45 +01001998
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001999 if (context) {
2000 context_reg = context->reg();
2001 } else {
2002 Register value_temp = register_allocator()->NewRegister();
2003 context_reg = register_allocator()->NewRegister();
2004 // Walk the context chain to find the context at the given depth.
2005 // TODO(rmcilroy): Perform this work in a bytecode handler once we have
2006 // a generic mechanism for performing jumps in interpreter.cc.
2007 // TODO(mythria): Also update bytecode graph builder with correct depth
2008 // when this changes.
2009 builder()
2010 ->StoreAccumulatorInRegister(value_temp)
2011 .LoadAccumulatorWithRegister(execution_context()->reg())
2012 .StoreAccumulatorInRegister(context_reg);
2013 for (int i = 0; i < depth; ++i) {
2014 builder()
2015 ->LoadContextSlot(context_reg, Context::PREVIOUS_INDEX)
2016 .StoreAccumulatorInRegister(context_reg);
2017 }
2018 builder()->LoadAccumulatorWithRegister(value_temp);
2019 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01002020
2021 if (hole_check_required) {
2022 // Load destination to check for hole.
2023 Register value_temp = register_allocator()->NewRegister();
2024 builder()
2025 ->StoreAccumulatorInRegister(value_temp)
2026 .LoadContextSlot(context_reg, variable->index());
2027
2028 if (mode == CONST_LEGACY && op == Token::INIT) {
2029 // Perform an intialization check for legacy constants.
2030 builder()
2031 ->JumpIfNotHole(&end_label)
2032 .LoadAccumulatorWithRegister(value_temp)
2033 .StoreContextSlot(context_reg, variable->index())
2034 .Bind(&end_label);
2035 builder()->LoadAccumulatorWithRegister(value_temp);
2036 // Break here because the value should not be stored unconditionally.
2037 // The above code performs the store conditionally.
2038 break;
2039 } else if (mode == CONST_LEGACY && op != Token::INIT) {
2040 DCHECK(!is_strict(language_mode()));
2041 // Ensure accumulator is in the correct state.
2042 builder()->LoadAccumulatorWithRegister(value_temp);
2043 // Break here, non-initializing assignments to legacy constants are
2044 // ignored.
2045 break;
2046 } else {
2047 BuildHoleCheckForVariableAssignment(variable, op);
2048 builder()->LoadAccumulatorWithRegister(value_temp);
2049 }
2050 }
2051
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002052 builder()->StoreContextSlot(context_reg, variable->index());
2053 break;
2054 }
2055 case VariableLocation::LOOKUP: {
Ben Murdoch097c5b22016-05-18 11:27:45 +01002056 if (mode == CONST_LEGACY && op == Token::INIT) {
2057 register_allocator()->PrepareForConsecutiveAllocations(3);
2058 Register value = register_allocator()->NextConsecutiveRegister();
2059 Register context = register_allocator()->NextConsecutiveRegister();
2060 Register name = register_allocator()->NextConsecutiveRegister();
2061
2062 // InitializeLegacyConstLookupSlot runtime call returns the 'value'
2063 // passed to it. So, accumulator will have its original contents when
2064 // runtime call returns.
2065 builder()
2066 ->StoreAccumulatorInRegister(value)
2067 .MoveRegister(execution_context()->reg(), context)
2068 .LoadLiteral(variable->name())
2069 .StoreAccumulatorInRegister(name)
2070 .CallRuntime(Runtime::kInitializeLegacyConstLookupSlot, value, 3);
2071 } else if (mode == CONST_LEGACY && op != Token::INIT) {
2072 // Non-intializing assignments to legacy constants are ignored.
2073 DCHECK(!is_strict(language_mode()));
2074 } else {
2075 builder()->StoreLookupSlot(variable->name(), language_mode());
2076 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002077 break;
2078 }
2079 }
2080}
2081
2082
2083void BytecodeGenerator::VisitAssignment(Assignment* expr) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01002084 DCHECK(expr->target()->IsValidReferenceExpressionOrThis());
2085 Register object, key, home_object, value;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002086 Handle<String> name;
2087
2088 // Left-hand side can only be a property, a global or a variable slot.
2089 Property* property = expr->target()->AsProperty();
2090 LhsKind assign_type = Property::GetAssignType(property);
2091
2092 // Evaluate LHS expression.
2093 switch (assign_type) {
2094 case VARIABLE:
2095 // Nothing to do to evaluate variable assignment LHS.
2096 break;
2097 case NAMED_PROPERTY: {
2098 object = VisitForRegisterValue(property->obj());
2099 name = property->key()->AsLiteral()->AsPropertyName();
2100 break;
2101 }
2102 case KEYED_PROPERTY: {
2103 object = VisitForRegisterValue(property->obj());
2104 if (expr->is_compound()) {
2105 // Use VisitForAccumulator and store to register so that the key is
2106 // still in the accumulator for loading the old value below.
2107 key = register_allocator()->NewRegister();
2108 VisitForAccumulatorValue(property->key());
2109 builder()->StoreAccumulatorInRegister(key);
2110 } else {
2111 key = VisitForRegisterValue(property->key());
2112 }
2113 break;
2114 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01002115 case NAMED_SUPER_PROPERTY: {
2116 register_allocator()->PrepareForConsecutiveAllocations(4);
2117 object = register_allocator()->NextConsecutiveRegister();
2118 home_object = register_allocator()->NextConsecutiveRegister();
2119 key = register_allocator()->NextConsecutiveRegister();
2120 value = register_allocator()->NextConsecutiveRegister();
2121 SuperPropertyReference* super_property =
2122 property->obj()->AsSuperPropertyReference();
2123 VisitForRegisterValue(super_property->this_var(), object);
2124 VisitForRegisterValue(super_property->home_object(), home_object);
2125 builder()
2126 ->LoadLiteral(property->key()->AsLiteral()->AsPropertyName())
2127 .StoreAccumulatorInRegister(key);
2128 break;
2129 }
2130 case KEYED_SUPER_PROPERTY: {
2131 register_allocator()->PrepareForConsecutiveAllocations(4);
2132 object = register_allocator()->NextConsecutiveRegister();
2133 home_object = register_allocator()->NextConsecutiveRegister();
2134 key = register_allocator()->NextConsecutiveRegister();
2135 value = register_allocator()->NextConsecutiveRegister();
2136 builder()->StoreAccumulatorInRegister(value);
2137 SuperPropertyReference* super_property =
2138 property->obj()->AsSuperPropertyReference();
2139 VisitForRegisterValue(super_property->this_var(), object);
2140 VisitForRegisterValue(super_property->home_object(), home_object);
2141 VisitForRegisterValue(property->key(), key);
2142 break;
2143 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002144 }
2145
2146 // Evaluate the value and potentially handle compound assignments by loading
2147 // the left-hand side value and performing a binary operation.
2148 if (expr->is_compound()) {
2149 Register old_value;
2150 switch (assign_type) {
2151 case VARIABLE: {
2152 VariableProxy* proxy = expr->target()->AsVariableProxy();
2153 old_value = VisitVariableLoadForRegisterValue(
2154 proxy->var(), proxy->VariableFeedbackSlot());
2155 break;
2156 }
2157 case NAMED_PROPERTY: {
2158 FeedbackVectorSlot slot = property->PropertyFeedbackSlot();
2159 old_value = register_allocator()->NewRegister();
2160 builder()
Ben Murdoch097c5b22016-05-18 11:27:45 +01002161 ->LoadNamedProperty(object, name, feedback_index(slot))
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002162 .StoreAccumulatorInRegister(old_value);
2163 break;
2164 }
2165 case KEYED_PROPERTY: {
2166 // Key is already in accumulator at this point due to evaluating the
2167 // LHS above.
2168 FeedbackVectorSlot slot = property->PropertyFeedbackSlot();
2169 old_value = register_allocator()->NewRegister();
2170 builder()
Ben Murdoch097c5b22016-05-18 11:27:45 +01002171 ->LoadKeyedProperty(object, feedback_index(slot))
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002172 .StoreAccumulatorInRegister(old_value);
2173 break;
2174 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01002175 case NAMED_SUPER_PROPERTY: {
2176 old_value = register_allocator()->NewRegister();
2177 BuildNamedSuperPropertyLoad(object, home_object, key);
2178 builder()->StoreAccumulatorInRegister(old_value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002179 break;
Ben Murdoch097c5b22016-05-18 11:27:45 +01002180 }
2181 case KEYED_SUPER_PROPERTY: {
2182 old_value = register_allocator()->NewRegister();
2183 BuildKeyedSuperPropertyLoad(object, home_object, key);
2184 builder()->StoreAccumulatorInRegister(old_value);
2185 break;
2186 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002187 }
2188 VisitForAccumulatorValue(expr->value());
Ben Murdoch097c5b22016-05-18 11:27:45 +01002189 builder()->BinaryOperation(expr->binary_op(), old_value);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002190 } else {
2191 VisitForAccumulatorValue(expr->value());
2192 }
2193
2194 // Store the value.
Ben Murdochda12d292016-06-02 14:46:10 +01002195 builder()->SetExpressionPosition(expr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002196 FeedbackVectorSlot slot = expr->AssignmentSlot();
2197 switch (assign_type) {
2198 case VARIABLE: {
2199 // TODO(oth): The VisitVariableAssignment() call is hard to reason about.
2200 // Is the value in the accumulator safe? Yes, but scary.
2201 Variable* variable = expr->target()->AsVariableProxy()->var();
Ben Murdoch097c5b22016-05-18 11:27:45 +01002202 VisitVariableAssignment(variable, expr->op(), slot);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002203 break;
2204 }
2205 case NAMED_PROPERTY:
2206 builder()->StoreNamedProperty(object, name, feedback_index(slot),
2207 language_mode());
2208 break;
2209 case KEYED_PROPERTY:
2210 builder()->StoreKeyedProperty(object, key, feedback_index(slot),
2211 language_mode());
2212 break;
Ben Murdoch097c5b22016-05-18 11:27:45 +01002213 case NAMED_SUPER_PROPERTY: {
2214 builder()->StoreAccumulatorInRegister(value);
2215 BuildNamedSuperPropertyStore(object, home_object, key, value);
2216 break;
2217 }
2218 case KEYED_SUPER_PROPERTY: {
2219 builder()->StoreAccumulatorInRegister(value);
2220 BuildKeyedSuperPropertyStore(object, home_object, key, value);
2221 break;
2222 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002223 }
2224 execution_result()->SetResultInAccumulator();
2225}
2226
2227
2228void BytecodeGenerator::VisitYield(Yield* expr) { UNIMPLEMENTED(); }
2229
2230
2231void BytecodeGenerator::VisitThrow(Throw* expr) {
2232 VisitForAccumulatorValue(expr->exception());
Ben Murdochda12d292016-06-02 14:46:10 +01002233 builder()->SetExpressionPosition(expr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002234 builder()->Throw();
Ben Murdoch097c5b22016-05-18 11:27:45 +01002235 // Throw statments are modeled as expression instead of statments. These are
2236 // converted from assignment statements in Rewriter::ReWrite pass. An
2237 // assignment statement expects a value in the accumulator. This is a hack to
2238 // avoid DCHECK fails assert accumulator has been set.
2239 execution_result()->SetResultInAccumulator();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002240}
2241
2242
2243void BytecodeGenerator::VisitPropertyLoad(Register obj, Property* expr) {
2244 LhsKind property_kind = Property::GetAssignType(expr);
2245 FeedbackVectorSlot slot = expr->PropertyFeedbackSlot();
Ben Murdochda12d292016-06-02 14:46:10 +01002246 builder()->SetExpressionPosition(expr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002247 switch (property_kind) {
2248 case VARIABLE:
2249 UNREACHABLE();
2250 case NAMED_PROPERTY: {
2251 builder()->LoadNamedProperty(obj,
2252 expr->key()->AsLiteral()->AsPropertyName(),
Ben Murdoch097c5b22016-05-18 11:27:45 +01002253 feedback_index(slot));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002254 break;
2255 }
2256 case KEYED_PROPERTY: {
2257 VisitForAccumulatorValue(expr->key());
Ben Murdoch097c5b22016-05-18 11:27:45 +01002258 builder()->LoadKeyedProperty(obj, feedback_index(slot));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002259 break;
2260 }
2261 case NAMED_SUPER_PROPERTY:
Ben Murdoch097c5b22016-05-18 11:27:45 +01002262 VisitNamedSuperPropertyLoad(expr, Register::invalid_value());
2263 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002264 case KEYED_SUPER_PROPERTY:
Ben Murdoch097c5b22016-05-18 11:27:45 +01002265 VisitKeyedSuperPropertyLoad(expr, Register::invalid_value());
2266 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002267 }
2268 execution_result()->SetResultInAccumulator();
2269}
2270
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002271void BytecodeGenerator::VisitPropertyLoadForAccumulator(Register obj,
2272 Property* expr) {
2273 AccumulatorResultScope result_scope(this);
2274 VisitPropertyLoad(obj, expr);
2275}
2276
Ben Murdoch097c5b22016-05-18 11:27:45 +01002277void BytecodeGenerator::VisitNamedSuperPropertyLoad(Property* property,
2278 Register opt_receiver_out) {
2279 RegisterAllocationScope register_scope(this);
2280 register_allocator()->PrepareForConsecutiveAllocations(3);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002281
Ben Murdoch097c5b22016-05-18 11:27:45 +01002282 Register receiver, home_object, name;
2283 receiver = register_allocator()->NextConsecutiveRegister();
2284 home_object = register_allocator()->NextConsecutiveRegister();
2285 name = register_allocator()->NextConsecutiveRegister();
2286 SuperPropertyReference* super_property =
2287 property->obj()->AsSuperPropertyReference();
2288 VisitForRegisterValue(super_property->this_var(), receiver);
2289 VisitForRegisterValue(super_property->home_object(), home_object);
2290 builder()
2291 ->LoadLiteral(property->key()->AsLiteral()->AsPropertyName())
2292 .StoreAccumulatorInRegister(name);
2293 BuildNamedSuperPropertyLoad(receiver, home_object, name);
2294
2295 if (opt_receiver_out.is_valid()) {
2296 builder()->MoveRegister(receiver, opt_receiver_out);
2297 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002298}
2299
Ben Murdoch097c5b22016-05-18 11:27:45 +01002300void BytecodeGenerator::VisitKeyedSuperPropertyLoad(Property* property,
2301 Register opt_receiver_out) {
2302 RegisterAllocationScope register_scope(this);
2303 register_allocator()->PrepareForConsecutiveAllocations(3);
2304
2305 Register receiver, home_object, key;
2306 receiver = register_allocator()->NextConsecutiveRegister();
2307 home_object = register_allocator()->NextConsecutiveRegister();
2308 key = register_allocator()->NextConsecutiveRegister();
2309 SuperPropertyReference* super_property =
2310 property->obj()->AsSuperPropertyReference();
2311 VisitForRegisterValue(super_property->this_var(), receiver);
2312 VisitForRegisterValue(super_property->home_object(), home_object);
2313 VisitForRegisterValue(property->key(), key);
2314 BuildKeyedSuperPropertyLoad(receiver, home_object, key);
2315
2316 if (opt_receiver_out.is_valid()) {
2317 builder()->MoveRegister(receiver, opt_receiver_out);
2318 }
2319}
2320
2321void BytecodeGenerator::VisitProperty(Property* expr) {
2322 LhsKind property_kind = Property::GetAssignType(expr);
2323 if (property_kind != NAMED_SUPER_PROPERTY &&
2324 property_kind != KEYED_SUPER_PROPERTY) {
2325 Register obj = VisitForRegisterValue(expr->obj());
2326 VisitPropertyLoad(obj, expr);
2327 } else {
2328 VisitPropertyLoad(Register::invalid_value(), expr);
2329 }
2330}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002331
2332Register BytecodeGenerator::VisitArguments(ZoneList<Expression*>* args) {
2333 if (args->length() == 0) {
2334 return Register();
2335 }
2336
2337 // Visit arguments and place in a contiguous block of temporary
2338 // registers. Return the first temporary register corresponding to
2339 // the first argument.
2340 //
2341 // NB the caller may have already called
2342 // PrepareForConsecutiveAllocations() with args->length() + N. The
2343 // second call here will be a no-op provided there have been N or
2344 // less calls to NextConsecutiveRegister(). Otherwise, the arguments
2345 // here will be consecutive, but they will not be consecutive with
2346 // earlier consecutive allocations made by the caller.
2347 register_allocator()->PrepareForConsecutiveAllocations(args->length());
2348
2349 // Visit for first argument that goes into returned register
2350 Register first_arg = register_allocator()->NextConsecutiveRegister();
2351 VisitForAccumulatorValue(args->at(0));
2352 builder()->StoreAccumulatorInRegister(first_arg);
2353
2354 // Visit remaining arguments
2355 for (int i = 1; i < static_cast<int>(args->length()); i++) {
2356 Register ith_arg = register_allocator()->NextConsecutiveRegister();
2357 VisitForAccumulatorValue(args->at(i));
2358 builder()->StoreAccumulatorInRegister(ith_arg);
2359 DCHECK(ith_arg.index() - i == first_arg.index());
2360 }
2361 return first_arg;
2362}
2363
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002364void BytecodeGenerator::VisitCall(Call* expr) {
2365 Expression* callee_expr = expr->expression();
2366 Call::CallType call_type = expr->GetCallType(isolate());
2367
Ben Murdoch097c5b22016-05-18 11:27:45 +01002368 if (call_type == Call::SUPER_CALL) {
2369 return VisitCallSuper(expr);
2370 }
2371
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002372 // Prepare the callee and the receiver to the function call. This depends on
2373 // the semantics of the underlying call type.
2374
2375 // The receiver and arguments need to be allocated consecutively for
2376 // Call(). We allocate the callee and receiver consecutively for calls to
Ben Murdoch097c5b22016-05-18 11:27:45 +01002377 // %LoadLookupSlotForCall. Future optimizations could avoid this there are
2378 // no arguments or the receiver and arguments are already consecutive.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002379 ZoneList<Expression*>* args = expr->arguments();
2380 register_allocator()->PrepareForConsecutiveAllocations(args->length() + 2);
2381 Register callee = register_allocator()->NextConsecutiveRegister();
2382 Register receiver = register_allocator()->NextConsecutiveRegister();
2383
2384 switch (call_type) {
2385 case Call::NAMED_PROPERTY_CALL:
2386 case Call::KEYED_PROPERTY_CALL: {
2387 Property* property = callee_expr->AsProperty();
2388 VisitForAccumulatorValue(property->obj());
2389 builder()->StoreAccumulatorInRegister(receiver);
2390 VisitPropertyLoadForAccumulator(receiver, property);
2391 builder()->StoreAccumulatorInRegister(callee);
2392 break;
2393 }
2394 case Call::GLOBAL_CALL: {
2395 // Receiver is undefined for global calls.
2396 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver);
2397 // Load callee as a global variable.
2398 VariableProxy* proxy = callee_expr->AsVariableProxy();
2399 VisitVariableLoadForAccumulatorValue(proxy->var(),
2400 proxy->VariableFeedbackSlot());
2401 builder()->StoreAccumulatorInRegister(callee);
2402 break;
2403 }
2404 case Call::LOOKUP_SLOT_CALL:
2405 case Call::POSSIBLY_EVAL_CALL: {
2406 if (callee_expr->AsVariableProxy()->var()->IsLookupSlot()) {
2407 RegisterAllocationScope inner_register_scope(this);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002408 Register name = register_allocator()->NewRegister();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002409
Ben Murdoch097c5b22016-05-18 11:27:45 +01002410 // Call %LoadLookupSlotForCall to get the callee and receiver.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002411 DCHECK(Register::AreContiguous(callee, receiver));
2412 Variable* variable = callee_expr->AsVariableProxy()->var();
2413 builder()
Ben Murdoch097c5b22016-05-18 11:27:45 +01002414 ->LoadLiteral(variable->name())
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002415 .StoreAccumulatorInRegister(name)
Ben Murdoch097c5b22016-05-18 11:27:45 +01002416 .CallRuntimeForPair(Runtime::kLoadLookupSlotForCall, name, 1,
2417 callee);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002418 break;
2419 }
2420 // Fall through.
2421 DCHECK_EQ(call_type, Call::POSSIBLY_EVAL_CALL);
2422 }
2423 case Call::OTHER_CALL: {
2424 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver);
2425 VisitForAccumulatorValue(callee_expr);
2426 builder()->StoreAccumulatorInRegister(callee);
2427 break;
2428 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01002429 case Call::NAMED_SUPER_PROPERTY_CALL: {
2430 Property* property = callee_expr->AsProperty();
2431 VisitNamedSuperPropertyLoad(property, receiver);
2432 builder()->StoreAccumulatorInRegister(callee);
2433 break;
2434 }
2435 case Call::KEYED_SUPER_PROPERTY_CALL: {
2436 Property* property = callee_expr->AsProperty();
2437 VisitKeyedSuperPropertyLoad(property, receiver);
2438 builder()->StoreAccumulatorInRegister(callee);
2439 break;
2440 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002441 case Call::SUPER_CALL:
Ben Murdoch097c5b22016-05-18 11:27:45 +01002442 UNREACHABLE();
2443 break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002444 }
2445
2446 // Evaluate all arguments to the function call and store in sequential
2447 // registers.
2448 Register arg = VisitArguments(args);
2449 CHECK(args->length() == 0 || arg.index() == receiver.index() + 1);
2450
2451 // Resolve callee for a potential direct eval call. This block will mutate the
2452 // callee value.
2453 if (call_type == Call::POSSIBLY_EVAL_CALL && args->length() > 0) {
2454 RegisterAllocationScope inner_register_scope(this);
2455 register_allocator()->PrepareForConsecutiveAllocations(5);
2456 Register callee_for_eval = register_allocator()->NextConsecutiveRegister();
2457 Register source = register_allocator()->NextConsecutiveRegister();
2458 Register function = register_allocator()->NextConsecutiveRegister();
2459 Register language = register_allocator()->NextConsecutiveRegister();
2460 Register position = register_allocator()->NextConsecutiveRegister();
2461
2462 // Set up arguments for ResolvePossiblyDirectEval by copying callee, source
2463 // strings and function closure, and loading language and
2464 // position.
2465 builder()
2466 ->MoveRegister(callee, callee_for_eval)
2467 .MoveRegister(arg, source)
2468 .MoveRegister(Register::function_closure(), function)
2469 .LoadLiteral(Smi::FromInt(language_mode()))
2470 .StoreAccumulatorInRegister(language)
2471 .LoadLiteral(
2472 Smi::FromInt(execution_context()->scope()->start_position()))
2473 .StoreAccumulatorInRegister(position);
2474
2475 // Call ResolvePossiblyDirectEval and modify the callee.
2476 builder()
2477 ->CallRuntime(Runtime::kResolvePossiblyDirectEval, callee_for_eval, 5)
2478 .StoreAccumulatorInRegister(callee);
2479 }
2480
Ben Murdoch097c5b22016-05-18 11:27:45 +01002481 builder()->SetExpressionPosition(expr);
2482 builder()->Call(callee, receiver, 1 + args->length(),
2483 feedback_index(expr->CallFeedbackICSlot()),
2484 expr->tail_call_mode());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002485 execution_result()->SetResultInAccumulator();
2486}
2487
Ben Murdoch097c5b22016-05-18 11:27:45 +01002488void BytecodeGenerator::VisitCallSuper(Call* expr) {
2489 RegisterAllocationScope register_scope(this);
2490 SuperCallReference* super = expr->expression()->AsSuperCallReference();
2491
2492 // Prepare the constructor to the super call.
2493 Register this_function = register_allocator()->NewRegister();
2494 VisitForAccumulatorValue(super->this_function_var());
2495 builder()
2496 ->StoreAccumulatorInRegister(this_function)
2497 .CallRuntime(Runtime::kInlineGetSuperConstructor, this_function, 1);
2498
2499 Register constructor = this_function; // Re-use dead this_function register.
2500 builder()->StoreAccumulatorInRegister(constructor);
2501
2502 ZoneList<Expression*>* args = expr->arguments();
2503 Register first_arg = VisitArguments(args);
2504
2505 // The new target is loaded into the accumulator from the
2506 // {new.target} variable.
2507 VisitForAccumulatorValue(super->new_target_var());
2508
2509 // Call construct.
2510 builder()->SetExpressionPosition(expr);
2511 builder()->New(constructor, first_arg, args->length());
2512 execution_result()->SetResultInAccumulator();
2513}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002514
2515void BytecodeGenerator::VisitCallNew(CallNew* expr) {
2516 Register constructor = register_allocator()->NewRegister();
2517 VisitForAccumulatorValue(expr->expression());
2518 builder()->StoreAccumulatorInRegister(constructor);
2519
2520 ZoneList<Expression*>* args = expr->arguments();
2521 Register first_arg = VisitArguments(args);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002522
2523 builder()->SetExpressionPosition(expr);
2524 // The accumulator holds new target which is the same as the
2525 // constructor for CallNew.
2526 builder()
2527 ->LoadAccumulatorWithRegister(constructor)
2528 .New(constructor, first_arg, args->length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002529 execution_result()->SetResultInAccumulator();
2530}
2531
2532
2533void BytecodeGenerator::VisitCallRuntime(CallRuntime* expr) {
2534 ZoneList<Expression*>* args = expr->arguments();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002535 if (expr->is_jsruntime()) {
2536 // Allocate a register for the receiver and load it with undefined.
Ben Murdoch097c5b22016-05-18 11:27:45 +01002537 register_allocator()->PrepareForConsecutiveAllocations(1 + args->length());
2538 Register receiver = register_allocator()->NextConsecutiveRegister();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002539 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002540 Register first_arg = VisitArguments(args);
2541 CHECK(args->length() == 0 || first_arg.index() == receiver.index() + 1);
2542 builder()->CallJSRuntime(expr->context_index(), receiver,
2543 1 + args->length());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002544 } else {
Ben Murdoch097c5b22016-05-18 11:27:45 +01002545 // Evaluate all arguments to the runtime call.
2546 Register first_arg = VisitArguments(args);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002547 Runtime::FunctionId function_id = expr->function()->function_id;
2548 builder()->CallRuntime(function_id, first_arg, args->length());
2549 }
2550 execution_result()->SetResultInAccumulator();
2551}
2552
2553
2554void BytecodeGenerator::VisitVoid(UnaryOperation* expr) {
2555 VisitForEffect(expr->expression());
2556 builder()->LoadUndefined();
2557 execution_result()->SetResultInAccumulator();
2558}
2559
2560
2561void BytecodeGenerator::VisitTypeOf(UnaryOperation* expr) {
2562 if (expr->expression()->IsVariableProxy()) {
2563 // Typeof does not throw a reference error on global variables, hence we
2564 // perform a non-contextual load in case the operand is a variable proxy.
2565 VariableProxy* proxy = expr->expression()->AsVariableProxy();
2566 VisitVariableLoadForAccumulatorValue(
2567 proxy->var(), proxy->VariableFeedbackSlot(), INSIDE_TYPEOF);
2568 } else {
2569 VisitForAccumulatorValue(expr->expression());
2570 }
2571 builder()->TypeOf();
2572 execution_result()->SetResultInAccumulator();
2573}
2574
2575
2576void BytecodeGenerator::VisitNot(UnaryOperation* expr) {
2577 VisitForAccumulatorValue(expr->expression());
2578 builder()->LogicalNot();
2579 execution_result()->SetResultInAccumulator();
2580}
2581
2582
2583void BytecodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
2584 switch (expr->op()) {
2585 case Token::Value::NOT:
2586 VisitNot(expr);
2587 break;
2588 case Token::Value::TYPEOF:
2589 VisitTypeOf(expr);
2590 break;
2591 case Token::Value::VOID:
2592 VisitVoid(expr);
2593 break;
2594 case Token::Value::DELETE:
2595 VisitDelete(expr);
2596 break;
2597 case Token::Value::BIT_NOT:
2598 case Token::Value::ADD:
2599 case Token::Value::SUB:
2600 // These operators are converted to an equivalent binary operators in
2601 // the parser. These operators are not expected to be visited here.
2602 UNREACHABLE();
2603 default:
2604 UNREACHABLE();
2605 }
2606}
2607
2608
2609void BytecodeGenerator::VisitDelete(UnaryOperation* expr) {
2610 if (expr->expression()->IsProperty()) {
2611 // Delete of an object property is allowed both in sloppy
2612 // and strict modes.
2613 Property* property = expr->expression()->AsProperty();
2614 Register object = VisitForRegisterValue(property->obj());
2615 VisitForAccumulatorValue(property->key());
2616 builder()->Delete(object, language_mode());
2617 } else if (expr->expression()->IsVariableProxy()) {
2618 // Delete of an unqualified identifier is allowed in sloppy mode but is
2619 // not allowed in strict mode. Deleting 'this' is allowed in both modes.
2620 VariableProxy* proxy = expr->expression()->AsVariableProxy();
2621 Variable* variable = proxy->var();
2622 DCHECK(is_sloppy(language_mode()) || variable->HasThisName(isolate()));
2623 switch (variable->location()) {
2624 case VariableLocation::GLOBAL:
2625 case VariableLocation::UNALLOCATED: {
2626 // Global var, let, const or variables not explicitly declared.
2627 Register native_context = register_allocator()->NewRegister();
2628 Register global_object = register_allocator()->NewRegister();
2629 builder()
2630 ->LoadContextSlot(execution_context()->reg(),
2631 Context::NATIVE_CONTEXT_INDEX)
2632 .StoreAccumulatorInRegister(native_context)
2633 .LoadContextSlot(native_context, Context::EXTENSION_INDEX)
2634 .StoreAccumulatorInRegister(global_object)
2635 .LoadLiteral(variable->name())
2636 .Delete(global_object, language_mode());
2637 break;
2638 }
2639 case VariableLocation::PARAMETER:
2640 case VariableLocation::LOCAL:
2641 case VariableLocation::CONTEXT: {
2642 // Deleting local var/let/const, context variables, and arguments
2643 // does not have any effect.
2644 if (variable->HasThisName(isolate())) {
2645 builder()->LoadTrue();
2646 } else {
2647 builder()->LoadFalse();
2648 }
2649 break;
2650 }
2651 case VariableLocation::LOOKUP: {
Ben Murdoch097c5b22016-05-18 11:27:45 +01002652 Register name_reg = register_allocator()->NewRegister();
2653 builder()
2654 ->LoadLiteral(variable->name())
2655 .StoreAccumulatorInRegister(name_reg)
2656 .CallRuntime(Runtime::kDeleteLookupSlot, name_reg, 1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002657 break;
2658 }
2659 default:
2660 UNREACHABLE();
2661 }
2662 } else {
2663 // Delete of an unresolvable reference returns true.
2664 VisitForEffect(expr->expression());
2665 builder()->LoadTrue();
2666 }
2667 execution_result()->SetResultInAccumulator();
2668}
2669
2670
2671void BytecodeGenerator::VisitCountOperation(CountOperation* expr) {
2672 DCHECK(expr->expression()->IsValidReferenceExpressionOrThis());
2673
2674 // Left-hand side can only be a property, a global or a variable slot.
2675 Property* property = expr->expression()->AsProperty();
2676 LhsKind assign_type = Property::GetAssignType(property);
2677
2678 // TODO(rmcilroy): Set is_postfix to false if visiting for effect.
2679 bool is_postfix = expr->is_postfix();
2680
2681 // Evaluate LHS expression and get old value.
Ben Murdoch097c5b22016-05-18 11:27:45 +01002682 Register object, home_object, key, old_value, value;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002683 Handle<String> name;
2684 switch (assign_type) {
2685 case VARIABLE: {
2686 VariableProxy* proxy = expr->expression()->AsVariableProxy();
2687 VisitVariableLoadForAccumulatorValue(proxy->var(),
2688 proxy->VariableFeedbackSlot());
2689 break;
2690 }
2691 case NAMED_PROPERTY: {
2692 FeedbackVectorSlot slot = property->PropertyFeedbackSlot();
Ben Murdoch097c5b22016-05-18 11:27:45 +01002693 object = VisitForRegisterValue(property->obj());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002694 name = property->key()->AsLiteral()->AsPropertyName();
Ben Murdoch097c5b22016-05-18 11:27:45 +01002695 builder()->LoadNamedProperty(object, name, feedback_index(slot));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002696 break;
2697 }
2698 case KEYED_PROPERTY: {
2699 FeedbackVectorSlot slot = property->PropertyFeedbackSlot();
Ben Murdoch097c5b22016-05-18 11:27:45 +01002700 object = VisitForRegisterValue(property->obj());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002701 // Use visit for accumulator here since we need the key in the accumulator
2702 // for the LoadKeyedProperty.
2703 key = register_allocator()->NewRegister();
2704 VisitForAccumulatorValue(property->key());
2705 builder()->StoreAccumulatorInRegister(key).LoadKeyedProperty(
Ben Murdoch097c5b22016-05-18 11:27:45 +01002706 object, feedback_index(slot));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002707 break;
2708 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01002709 case NAMED_SUPER_PROPERTY: {
2710 register_allocator()->PrepareForConsecutiveAllocations(4);
2711 object = register_allocator()->NextConsecutiveRegister();
2712 home_object = register_allocator()->NextConsecutiveRegister();
2713 key = register_allocator()->NextConsecutiveRegister();
2714 value = register_allocator()->NextConsecutiveRegister();
2715 SuperPropertyReference* super_property =
2716 property->obj()->AsSuperPropertyReference();
2717 VisitForRegisterValue(super_property->this_var(), object);
2718 VisitForRegisterValue(super_property->home_object(), home_object);
2719 builder()
2720 ->LoadLiteral(property->key()->AsLiteral()->AsPropertyName())
2721 .StoreAccumulatorInRegister(key);
2722 BuildNamedSuperPropertyLoad(object, home_object, key);
2723 break;
2724 }
2725 case KEYED_SUPER_PROPERTY: {
2726 register_allocator()->PrepareForConsecutiveAllocations(4);
2727 object = register_allocator()->NextConsecutiveRegister();
2728 home_object = register_allocator()->NextConsecutiveRegister();
2729 key = register_allocator()->NextConsecutiveRegister();
2730 value = register_allocator()->NextConsecutiveRegister();
2731 builder()->StoreAccumulatorInRegister(value);
2732 SuperPropertyReference* super_property =
2733 property->obj()->AsSuperPropertyReference();
2734 VisitForRegisterValue(super_property->this_var(), object);
2735 VisitForRegisterValue(super_property->home_object(), home_object);
2736 VisitForRegisterValue(property->key(), key);
2737 BuildKeyedSuperPropertyLoad(object, home_object, key);
2738 break;
2739 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002740 }
2741
2742 // Convert old value into a number.
Ben Murdochda12d292016-06-02 14:46:10 +01002743 builder()->CastAccumulatorToNumber();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002744
2745 // Save result for postfix expressions.
2746 if (is_postfix) {
2747 old_value = register_allocator()->outer()->NewRegister();
2748 builder()->StoreAccumulatorInRegister(old_value);
2749 }
2750
2751 // Perform +1/-1 operation.
Ben Murdoch097c5b22016-05-18 11:27:45 +01002752 builder()->CountOperation(expr->binary_op());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002753
2754 // Store the value.
Ben Murdochda12d292016-06-02 14:46:10 +01002755 builder()->SetExpressionPosition(expr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002756 FeedbackVectorSlot feedback_slot = expr->CountSlot();
2757 switch (assign_type) {
2758 case VARIABLE: {
2759 Variable* variable = expr->expression()->AsVariableProxy()->var();
Ben Murdoch097c5b22016-05-18 11:27:45 +01002760 VisitVariableAssignment(variable, expr->op(), feedback_slot);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002761 break;
2762 }
2763 case NAMED_PROPERTY: {
Ben Murdoch097c5b22016-05-18 11:27:45 +01002764 builder()->StoreNamedProperty(object, name, feedback_index(feedback_slot),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002765 language_mode());
2766 break;
2767 }
2768 case KEYED_PROPERTY: {
Ben Murdoch097c5b22016-05-18 11:27:45 +01002769 builder()->StoreKeyedProperty(object, key, feedback_index(feedback_slot),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002770 language_mode());
2771 break;
2772 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01002773 case NAMED_SUPER_PROPERTY: {
2774 builder()->StoreAccumulatorInRegister(value);
2775 BuildNamedSuperPropertyStore(object, home_object, key, value);
2776 break;
2777 }
2778 case KEYED_SUPER_PROPERTY: {
2779 builder()->StoreAccumulatorInRegister(value);
2780 BuildKeyedSuperPropertyStore(object, home_object, key, value);
2781 break;
2782 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002783 }
2784
2785 // Restore old value for postfix expressions.
2786 if (is_postfix) {
2787 execution_result()->SetResultInRegister(old_value);
2788 } else {
2789 execution_result()->SetResultInAccumulator();
2790 }
2791}
2792
2793
2794void BytecodeGenerator::VisitBinaryOperation(BinaryOperation* binop) {
2795 switch (binop->op()) {
2796 case Token::COMMA:
2797 VisitCommaExpression(binop);
2798 break;
2799 case Token::OR:
2800 VisitLogicalOrExpression(binop);
2801 break;
2802 case Token::AND:
2803 VisitLogicalAndExpression(binop);
2804 break;
2805 default:
2806 VisitArithmeticExpression(binop);
2807 break;
2808 }
2809}
2810
2811
2812void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) {
2813 Register lhs = VisitForRegisterValue(expr->left());
2814 VisitForAccumulatorValue(expr->right());
Ben Murdochda12d292016-06-02 14:46:10 +01002815 builder()->SetExpressionPosition(expr);
Ben Murdoch097c5b22016-05-18 11:27:45 +01002816 builder()->CompareOperation(expr->op(), lhs);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002817 execution_result()->SetResultInAccumulator();
2818}
2819
2820
2821void BytecodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) {
2822 Register lhs = VisitForRegisterValue(expr->left());
2823 VisitForAccumulatorValue(expr->right());
Ben Murdoch097c5b22016-05-18 11:27:45 +01002824 builder()->BinaryOperation(expr->op(), lhs);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002825 execution_result()->SetResultInAccumulator();
2826}
2827
2828
2829void BytecodeGenerator::VisitSpread(Spread* expr) { UNREACHABLE(); }
2830
2831
2832void BytecodeGenerator::VisitEmptyParentheses(EmptyParentheses* expr) {
2833 UNREACHABLE();
2834}
2835
2836
2837void BytecodeGenerator::VisitThisFunction(ThisFunction* expr) {
2838 execution_result()->SetResultInRegister(Register::function_closure());
2839}
2840
2841
2842void BytecodeGenerator::VisitSuperCallReference(SuperCallReference* expr) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01002843 // Handled by VisitCall().
2844 UNREACHABLE();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002845}
2846
2847
2848void BytecodeGenerator::VisitSuperPropertyReference(
2849 SuperPropertyReference* expr) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01002850 builder()->CallRuntime(Runtime::kThrowUnsupportedSuperError, Register(0), 0);
2851 execution_result()->SetResultInAccumulator();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002852}
2853
2854
2855void BytecodeGenerator::VisitCommaExpression(BinaryOperation* binop) {
2856 VisitForEffect(binop->left());
2857 Visit(binop->right());
2858}
2859
2860
2861void BytecodeGenerator::VisitLogicalOrExpression(BinaryOperation* binop) {
2862 Expression* left = binop->left();
2863 Expression* right = binop->right();
2864
2865 // Short-circuit evaluation- If it is known that left is always true,
2866 // no need to visit right
2867 if (left->ToBooleanIsTrue()) {
2868 VisitForAccumulatorValue(left);
2869 } else {
2870 BytecodeLabel end_label;
2871 VisitForAccumulatorValue(left);
2872 builder()->JumpIfTrue(&end_label);
2873 VisitForAccumulatorValue(right);
2874 builder()->Bind(&end_label);
2875 }
2876 execution_result()->SetResultInAccumulator();
2877}
2878
2879
2880void BytecodeGenerator::VisitLogicalAndExpression(BinaryOperation* binop) {
2881 Expression* left = binop->left();
2882 Expression* right = binop->right();
2883
2884 // Short-circuit evaluation- If it is known that left is always false,
2885 // no need to visit right
2886 if (left->ToBooleanIsFalse()) {
2887 VisitForAccumulatorValue(left);
2888 } else {
2889 BytecodeLabel end_label;
2890 VisitForAccumulatorValue(left);
2891 builder()->JumpIfFalse(&end_label);
2892 VisitForAccumulatorValue(right);
2893 builder()->Bind(&end_label);
2894 }
2895 execution_result()->SetResultInAccumulator();
2896}
2897
2898
Ben Murdoch097c5b22016-05-18 11:27:45 +01002899void BytecodeGenerator::VisitRewritableExpression(RewritableExpression* expr) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002900 Visit(expr->expression());
2901}
2902
2903
2904void BytecodeGenerator::VisitNewLocalFunctionContext() {
2905 AccumulatorResultScope accumulator_execution_result(this);
2906 Scope* scope = this->scope();
2907
2908 // Allocate a new local context.
2909 if (scope->is_script_scope()) {
2910 RegisterAllocationScope register_scope(this);
2911 Register closure = register_allocator()->NewRegister();
2912 Register scope_info = register_allocator()->NewRegister();
2913 DCHECK(Register::AreContiguous(closure, scope_info));
2914 builder()
2915 ->LoadAccumulatorWithRegister(Register::function_closure())
2916 .StoreAccumulatorInRegister(closure)
2917 .LoadLiteral(scope->GetScopeInfo(isolate()))
2918 .StoreAccumulatorInRegister(scope_info)
2919 .CallRuntime(Runtime::kNewScriptContext, closure, 2);
2920 } else {
2921 builder()->CallRuntime(Runtime::kNewFunctionContext,
2922 Register::function_closure(), 1);
2923 }
2924 execution_result()->SetResultInAccumulator();
2925}
2926
2927
2928void BytecodeGenerator::VisitBuildLocalActivationContext() {
2929 Scope* scope = this->scope();
2930
2931 if (scope->has_this_declaration() && scope->receiver()->IsContextSlot()) {
2932 Variable* variable = scope->receiver();
2933 Register receiver(builder()->Parameter(0));
2934 // Context variable (at bottom of the context chain).
2935 DCHECK_EQ(0, scope->ContextChainLength(variable->scope()));
2936 builder()->LoadAccumulatorWithRegister(receiver).StoreContextSlot(
2937 execution_context()->reg(), variable->index());
2938 }
2939
2940 // Copy parameters into context if necessary.
2941 int num_parameters = scope->num_parameters();
2942 for (int i = 0; i < num_parameters; i++) {
2943 Variable* variable = scope->parameter(i);
2944 if (!variable->IsContextSlot()) continue;
2945
2946 // The parameter indices are shifted by 1 (receiver is variable
2947 // index -1 but is parameter index 0 in BytecodeArrayBuilder).
2948 Register parameter(builder()->Parameter(i + 1));
2949 // Context variable (at bottom of the context chain).
2950 DCHECK_EQ(0, scope->ContextChainLength(variable->scope()));
2951 builder()->LoadAccumulatorWithRegister(parameter)
2952 .StoreContextSlot(execution_context()->reg(), variable->index());
2953 }
2954}
2955
2956
2957void BytecodeGenerator::VisitNewLocalBlockContext(Scope* scope) {
2958 AccumulatorResultScope accumulator_execution_result(this);
2959 DCHECK(scope->is_block_scope());
2960
2961 // Allocate a new local block context.
2962 register_allocator()->PrepareForConsecutiveAllocations(2);
2963 Register scope_info = register_allocator()->NextConsecutiveRegister();
2964 Register closure = register_allocator()->NextConsecutiveRegister();
2965
2966 builder()
2967 ->LoadLiteral(scope->GetScopeInfo(isolate()))
2968 .StoreAccumulatorInRegister(scope_info);
2969 VisitFunctionClosureForContext();
2970 builder()
2971 ->StoreAccumulatorInRegister(closure)
2972 .CallRuntime(Runtime::kPushBlockContext, scope_info, 2);
2973 execution_result()->SetResultInAccumulator();
2974}
2975
Ben Murdoch097c5b22016-05-18 11:27:45 +01002976void BytecodeGenerator::VisitNewLocalWithContext() {
2977 AccumulatorResultScope accumulator_execution_result(this);
2978
2979 register_allocator()->PrepareForConsecutiveAllocations(2);
2980 Register extension_object = register_allocator()->NextConsecutiveRegister();
2981 Register closure = register_allocator()->NextConsecutiveRegister();
2982
2983 builder()->StoreAccumulatorInRegister(extension_object);
2984 VisitFunctionClosureForContext();
2985 builder()->StoreAccumulatorInRegister(closure).CallRuntime(
2986 Runtime::kPushWithContext, extension_object, 2);
2987 execution_result()->SetResultInAccumulator();
2988}
2989
2990void BytecodeGenerator::VisitNewLocalCatchContext(Variable* variable) {
2991 AccumulatorResultScope accumulator_execution_result(this);
2992 DCHECK(variable->IsContextSlot());
2993
2994 // Allocate a new local block context.
2995 register_allocator()->PrepareForConsecutiveAllocations(3);
2996 Register name = register_allocator()->NextConsecutiveRegister();
2997 Register exception = register_allocator()->NextConsecutiveRegister();
2998 Register closure = register_allocator()->NextConsecutiveRegister();
2999
3000 builder()
3001 ->StoreAccumulatorInRegister(exception)
3002 .LoadLiteral(variable->name())
3003 .StoreAccumulatorInRegister(name);
3004 VisitFunctionClosureForContext();
3005 builder()->StoreAccumulatorInRegister(closure).CallRuntime(
3006 Runtime::kPushCatchContext, name, 3);
3007 execution_result()->SetResultInAccumulator();
3008}
3009
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003010
3011void BytecodeGenerator::VisitObjectLiteralAccessor(
3012 Register home_object, ObjectLiteralProperty* property, Register value_out) {
3013 // TODO(rmcilroy): Replace value_out with VisitForRegister();
3014 if (property == nullptr) {
3015 builder()->LoadNull().StoreAccumulatorInRegister(value_out);
3016 } else {
3017 VisitForAccumulatorValue(property->value());
3018 builder()->StoreAccumulatorInRegister(value_out);
3019 VisitSetHomeObject(value_out, home_object, property);
3020 }
3021}
3022
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003023void BytecodeGenerator::VisitSetHomeObject(Register value, Register home_object,
3024 ObjectLiteralProperty* property,
3025 int slot_number) {
3026 Expression* expr = property->value();
Ben Murdoch097c5b22016-05-18 11:27:45 +01003027 if (FunctionLiteral::NeedsHomeObject(expr)) {
3028 Handle<Name> name = isolate()->factory()->home_object_symbol();
3029 FeedbackVectorSlot slot = property->GetSlot(slot_number);
3030 builder()
3031 ->LoadAccumulatorWithRegister(home_object)
3032 .StoreNamedProperty(value, name, feedback_index(slot), language_mode());
3033 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003034}
3035
3036
3037void BytecodeGenerator::VisitArgumentsObject(Variable* variable) {
3038 if (variable == nullptr) return;
3039
3040 DCHECK(variable->IsContextSlot() || variable->IsStackAllocated());
3041
3042 // Allocate and initialize a new arguments object and assign to the
3043 // {arguments} variable.
3044 CreateArgumentsType type =
3045 is_strict(language_mode()) || !info()->has_simple_parameters()
3046 ? CreateArgumentsType::kUnmappedArguments
3047 : CreateArgumentsType::kMappedArguments;
3048 builder()->CreateArguments(type);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003049 VisitVariableAssignment(variable, Token::ASSIGN,
3050 FeedbackVectorSlot::Invalid());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003051}
3052
Ben Murdoch097c5b22016-05-18 11:27:45 +01003053void BytecodeGenerator::VisitRestArgumentsArray(Variable* rest) {
3054 if (rest == nullptr) return;
3055
3056 // Allocate and initialize a new rest parameter and assign to the {rest}
3057 // variable.
3058 builder()->CreateArguments(CreateArgumentsType::kRestParameter);
3059 DCHECK(rest->IsContextSlot() || rest->IsStackAllocated());
3060 VisitVariableAssignment(rest, Token::ASSIGN, FeedbackVectorSlot::Invalid());
3061}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003062
3063void BytecodeGenerator::VisitThisFunctionVariable(Variable* variable) {
3064 if (variable == nullptr) return;
3065
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003066 // Store the closure we were called with in the given variable.
3067 builder()->LoadAccumulatorWithRegister(Register::function_closure());
Ben Murdoch097c5b22016-05-18 11:27:45 +01003068 VisitVariableAssignment(variable, Token::INIT, FeedbackVectorSlot::Invalid());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003069}
3070
3071
3072void BytecodeGenerator::VisitNewTargetVariable(Variable* variable) {
3073 if (variable == nullptr) return;
3074
3075 // Store the new target we were called with in the given variable.
3076 builder()->LoadAccumulatorWithRegister(Register::new_target());
Ben Murdoch097c5b22016-05-18 11:27:45 +01003077 VisitVariableAssignment(variable, Token::INIT, FeedbackVectorSlot::Invalid());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003078}
3079
3080
3081void BytecodeGenerator::VisitFunctionClosureForContext() {
3082 AccumulatorResultScope accumulator_execution_result(this);
3083 Scope* closure_scope = execution_context()->scope()->ClosureScope();
3084 if (closure_scope->is_script_scope() ||
3085 closure_scope->is_module_scope()) {
3086 // Contexts nested in the native context have a canonical empty function as
3087 // their closure, not the anonymous closure containing the global code.
3088 Register native_context = register_allocator()->NewRegister();
3089 builder()
3090 ->LoadContextSlot(execution_context()->reg(),
3091 Context::NATIVE_CONTEXT_INDEX)
3092 .StoreAccumulatorInRegister(native_context)
3093 .LoadContextSlot(native_context, Context::CLOSURE_INDEX);
Ben Murdoch097c5b22016-05-18 11:27:45 +01003094 } else if (closure_scope->is_eval_scope()) {
3095 // Contexts created by a call to eval have the same closure as the
3096 // context calling eval, not the anonymous closure containing the eval
3097 // code. Fetch it from the context.
3098 builder()->LoadContextSlot(execution_context()->reg(),
3099 Context::CLOSURE_INDEX);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003100 } else {
3101 DCHECK(closure_scope->is_function_scope());
3102 builder()->LoadAccumulatorWithRegister(Register::function_closure());
3103 }
3104 execution_result()->SetResultInAccumulator();
3105}
3106
3107
3108// Visits the expression |expr| and places the result in the accumulator.
3109void BytecodeGenerator::VisitForAccumulatorValue(Expression* expr) {
3110 AccumulatorResultScope accumulator_scope(this);
3111 Visit(expr);
3112}
3113
Ben Murdoch097c5b22016-05-18 11:27:45 +01003114void BytecodeGenerator::VisitForAccumulatorValueOrTheHole(Expression* expr) {
3115 if (expr == nullptr) {
3116 builder()->LoadTheHole();
3117 } else {
3118 VisitForAccumulatorValue(expr);
3119 }
3120}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003121
3122// Visits the expression |expr| and discards the result.
3123void BytecodeGenerator::VisitForEffect(Expression* expr) {
3124 EffectResultScope effect_scope(this);
3125 Visit(expr);
3126}
3127
3128
3129// Visits the expression |expr| and returns the register containing
3130// the expression result.
3131Register BytecodeGenerator::VisitForRegisterValue(Expression* expr) {
3132 RegisterResultScope register_scope(this);
3133 Visit(expr);
3134 return register_scope.ResultRegister();
3135}
3136
Ben Murdoch097c5b22016-05-18 11:27:45 +01003137// Visits the expression |expr| and stores the expression result in
3138// |destination|.
3139void BytecodeGenerator::VisitForRegisterValue(Expression* expr,
3140 Register destination) {
3141 AccumulatorResultScope register_scope(this);
3142 Visit(expr);
3143 builder()->StoreAccumulatorInRegister(destination);
3144}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003145
Ben Murdoch097c5b22016-05-18 11:27:45 +01003146void BytecodeGenerator::VisitInScope(Statement* stmt, Scope* scope) {
3147 ContextScope context_scope(this, scope);
3148 DCHECK(scope->declarations()->is_empty());
3149 Visit(stmt);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003150}
3151
3152
3153LanguageMode BytecodeGenerator::language_mode() const {
Ben Murdochda12d292016-06-02 14:46:10 +01003154 return execution_context()->scope()->language_mode();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003155}
3156
3157
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003158int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const {
Ben Murdochda12d292016-06-02 14:46:10 +01003159 return info()->shared_info()->feedback_vector()->GetIndex(slot);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00003160}
3161
3162} // namespace interpreter
3163} // namespace internal
3164} // namespace v8