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