blob: 959e15514976132c32a0292e367ba17ea3b23d5e [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()),
30 register_(generator_->NextContextRegister()),
31 depth_(0),
32 should_pop_context_(should_pop_context) {
33 if (outer_) {
34 depth_ = outer_->depth_ + 1;
35 generator_->builder()->PushContext(register_);
36 }
37 generator_->set_execution_context(this);
38 }
39
40 ~ContextScope() {
41 if (outer_ && should_pop_context_) {
42 generator_->builder()->PopContext(outer_->reg());
43 }
44 generator_->set_execution_context(outer_);
45 }
46
47 // Returns the depth of the given |scope| for the current execution context.
48 int ContextChainDepth(Scope* scope) {
49 return scope_->ContextChainLength(scope);
50 }
51
52 // Returns the execution context at |depth| in the current context chain if it
53 // is a function local execution context, otherwise returns nullptr.
54 ContextScope* Previous(int depth) {
55 if (depth > depth_) {
56 return nullptr;
57 }
58
59 ContextScope* previous = this;
60 for (int i = depth; i > 0; --i) {
61 previous = previous->outer_;
62 }
63 return previous;
64 }
65
66 Scope* scope() const { return scope_; }
67 Register reg() const { return register_; }
68
69 private:
70 BytecodeGenerator* generator_;
71 Scope* scope_;
72 ContextScope* outer_;
73 Register register_;
74 int depth_;
75 bool should_pop_context_;
76};
77
78
79// Scoped class for tracking control statements entered by the
80// visitor. The pattern derives AstGraphBuilder::ControlScope.
81class BytecodeGenerator::ControlScope BASE_EMBEDDED {
82 public:
83 explicit ControlScope(BytecodeGenerator* generator)
84 : generator_(generator), outer_(generator->execution_control()) {
85 generator_->set_execution_control(this);
86 }
87 virtual ~ControlScope() { generator_->set_execution_control(outer()); }
88
89 void Break(Statement* stmt) { PerformCommand(CMD_BREAK, stmt); }
90 void Continue(Statement* stmt) { PerformCommand(CMD_CONTINUE, stmt); }
91
92 protected:
93 enum Command { CMD_BREAK, CMD_CONTINUE };
94 void PerformCommand(Command command, Statement* statement);
95 virtual bool Execute(Command command, Statement* statement) = 0;
96
97 BytecodeGenerator* generator() const { return generator_; }
98 ControlScope* outer() const { return outer_; }
99
100 private:
101 BytecodeGenerator* generator_;
102 ControlScope* outer_;
103
104 DISALLOW_COPY_AND_ASSIGN(ControlScope);
105};
106
107
108// Scoped class for enabling break inside blocks and switch blocks.
109class BytecodeGenerator::ControlScopeForBreakable final
110 : public BytecodeGenerator::ControlScope {
111 public:
112 ControlScopeForBreakable(BytecodeGenerator* generator,
113 BreakableStatement* statement,
114 BreakableControlFlowBuilder* control_builder)
115 : ControlScope(generator),
116 statement_(statement),
117 control_builder_(control_builder) {}
118
119 protected:
120 virtual bool Execute(Command command, Statement* statement) {
121 if (statement != statement_) return false;
122 switch (command) {
123 case CMD_BREAK:
124 control_builder_->Break();
125 return true;
126 case CMD_CONTINUE:
127 break;
128 }
129 return false;
130 }
131
132 private:
133 Statement* statement_;
134 BreakableControlFlowBuilder* control_builder_;
135};
136
137
138// Scoped class for enabling 'break' and 'continue' in iteration
139// constructs, e.g. do...while, while..., for...
140class BytecodeGenerator::ControlScopeForIteration final
141 : public BytecodeGenerator::ControlScope {
142 public:
143 ControlScopeForIteration(BytecodeGenerator* generator,
144 IterationStatement* statement,
145 LoopBuilder* loop_builder)
146 : ControlScope(generator),
147 statement_(statement),
148 loop_builder_(loop_builder) {}
149
150 protected:
151 virtual bool Execute(Command command, Statement* statement) {
152 if (statement != statement_) return false;
153 switch (command) {
154 case CMD_BREAK:
155 loop_builder_->Break();
156 return true;
157 case CMD_CONTINUE:
158 loop_builder_->Continue();
159 return true;
160 }
161 return false;
162 }
163
164 private:
165 Statement* statement_;
166 LoopBuilder* loop_builder_;
167};
168
169
170void BytecodeGenerator::ControlScope::PerformCommand(Command command,
171 Statement* statement) {
172 ControlScope* current = this;
173 do {
174 if (current->Execute(command, statement)) return;
175 current = current->outer();
176 } while (current != nullptr);
177 UNREACHABLE();
178}
179
180
181class BytecodeGenerator::RegisterAllocationScope {
182 public:
183 explicit RegisterAllocationScope(BytecodeGenerator* generator)
184 : generator_(generator),
185 outer_(generator->register_allocator()),
186 allocator_(builder()) {
187 generator_->set_register_allocator(this);
188 }
189
190 virtual ~RegisterAllocationScope() {
191 generator_->set_register_allocator(outer_);
192 }
193
194 Register NewRegister() {
195 RegisterAllocationScope* current_scope = generator()->register_allocator();
196 if ((current_scope == this) ||
197 (current_scope->outer() == this &&
198 !current_scope->allocator_.HasConsecutiveAllocations())) {
199 // Regular case - Allocating registers in current or outer context.
200 // VisitForRegisterValue allocates register in outer context.
201 return allocator_.NewRegister();
202 } else {
203 // If it is required to allocate a register other than current or outer
204 // scopes, allocate a new temporary register. It might be expensive to
205 // walk the full context chain and compute the list of consecutive
206 // reservations in the innerscopes.
207 UNIMPLEMENTED();
208 return Register(-1);
209 }
210 }
211
212 void PrepareForConsecutiveAllocations(size_t count) {
213 allocator_.PrepareForConsecutiveAllocations(count);
214 }
215
216 Register NextConsecutiveRegister() {
217 return allocator_.NextConsecutiveRegister();
218 }
219
220 bool RegisterIsAllocatedInThisScope(Register reg) const {
221 return allocator_.RegisterIsAllocatedInThisScope(reg);
222 }
223
224 RegisterAllocationScope* outer() const { return outer_; }
225
226 private:
227 BytecodeGenerator* generator() const { return generator_; }
228 BytecodeArrayBuilder* builder() const { return generator_->builder(); }
229
230 BytecodeGenerator* generator_;
231 RegisterAllocationScope* outer_;
232 BytecodeRegisterAllocator allocator_;
233
234 DISALLOW_COPY_AND_ASSIGN(RegisterAllocationScope);
235};
236
237
238// Scoped base class for determining where the result of an expression
239// is stored.
240class BytecodeGenerator::ExpressionResultScope {
241 public:
242 ExpressionResultScope(BytecodeGenerator* generator, Expression::Context kind)
243 : generator_(generator),
244 kind_(kind),
245 outer_(generator->execution_result()),
246 allocator_(generator),
247 result_identified_(false) {
248 generator_->set_execution_result(this);
249 }
250
251 virtual ~ExpressionResultScope() {
252 generator_->set_execution_result(outer_);
253 DCHECK(result_identified());
254 }
255
256 bool IsEffect() const { return kind_ == Expression::kEffect; }
257 bool IsValue() const { return kind_ == Expression::kValue; }
258
259 virtual void SetResultInAccumulator() = 0;
260 virtual void SetResultInRegister(Register reg) = 0;
261
262 protected:
263 ExpressionResultScope* outer() const { return outer_; }
264 BytecodeArrayBuilder* builder() const { return generator_->builder(); }
265 const RegisterAllocationScope* allocator() const { return &allocator_; }
266
267 void set_result_identified() {
268 DCHECK(!result_identified());
269 result_identified_ = true;
270 }
271
272 bool result_identified() const { return result_identified_; }
273
274 private:
275 BytecodeGenerator* generator_;
276 Expression::Context kind_;
277 ExpressionResultScope* outer_;
278 RegisterAllocationScope allocator_;
279 bool result_identified_;
280
281 DISALLOW_COPY_AND_ASSIGN(ExpressionResultScope);
282};
283
284
285// Scoped class used when the result of the current expression is not
286// expected to produce a result.
287class BytecodeGenerator::EffectResultScope final
288 : public ExpressionResultScope {
289 public:
290 explicit EffectResultScope(BytecodeGenerator* generator)
291 : ExpressionResultScope(generator, Expression::kEffect) {
292 set_result_identified();
293 }
294
295 virtual void SetResultInAccumulator() {}
296 virtual void SetResultInRegister(Register reg) {}
297};
298
299
300// Scoped class used when the result of the current expression to be
301// evaluated should go into the interpreter's accumulator register.
302class BytecodeGenerator::AccumulatorResultScope final
303 : public ExpressionResultScope {
304 public:
305 explicit AccumulatorResultScope(BytecodeGenerator* generator)
306 : ExpressionResultScope(generator, Expression::kValue) {}
307
308 virtual void SetResultInAccumulator() { set_result_identified(); }
309
310 virtual void SetResultInRegister(Register reg) {
311 builder()->LoadAccumulatorWithRegister(reg);
312 set_result_identified();
313 }
314};
315
316
317// Scoped class used when the result of the current expression to be
318// evaluated should go into an interpreter register.
319class BytecodeGenerator::RegisterResultScope final
320 : public ExpressionResultScope {
321 public:
322 explicit RegisterResultScope(BytecodeGenerator* generator)
323 : ExpressionResultScope(generator, Expression::kValue) {}
324
325 virtual void SetResultInAccumulator() {
326 result_register_ = allocator()->outer()->NewRegister();
327 builder()->StoreAccumulatorInRegister(result_register_);
328 set_result_identified();
329 }
330
331 virtual void SetResultInRegister(Register reg) {
332 DCHECK(builder()->RegisterIsParameterOrLocal(reg) ||
333 (builder()->RegisterIsTemporary(reg) &&
334 !allocator()->RegisterIsAllocatedInThisScope(reg)));
335 result_register_ = reg;
336 set_result_identified();
337 }
338
339 Register ResultRegister() const { return result_register_; }
340
341 private:
342 Register result_register_;
343};
344
345
346BytecodeGenerator::BytecodeGenerator(Isolate* isolate, Zone* zone)
347 : isolate_(isolate),
348 zone_(zone),
349 builder_(isolate, zone),
350 info_(nullptr),
351 scope_(nullptr),
352 globals_(0, zone),
353 execution_control_(nullptr),
354 execution_context_(nullptr),
355 execution_result_(nullptr),
356 register_allocator_(nullptr) {
357 InitializeAstVisitor(isolate);
358}
359
360
361Handle<BytecodeArray> BytecodeGenerator::MakeBytecode(CompilationInfo* info) {
362 set_info(info);
363 set_scope(info->scope());
364
365 // Initialize the incoming context.
366 ContextScope incoming_context(this, scope(), false);
367
368 builder()->set_parameter_count(info->num_parameters_including_this());
369 builder()->set_locals_count(scope()->num_stack_slots());
370 builder()->set_context_count(scope()->MaxNestedContextChainLength());
371
372 // Build function context only if there are context allocated variables.
373 if (scope()->NeedsContext()) {
374 // Push a new inner context scope for the function.
375 VisitNewLocalFunctionContext();
376 ContextScope local_function_context(this, scope(), false);
377 VisitBuildLocalActivationContext();
378 MakeBytecodeBody();
379 } else {
380 MakeBytecodeBody();
381 }
382
383 set_scope(nullptr);
384 set_info(nullptr);
385 return builder_.ToBytecodeArray();
386}
387
388
389void BytecodeGenerator::MakeBytecodeBody() {
390 // Build the arguments object if it is used.
391 VisitArgumentsObject(scope()->arguments());
392
393 // TODO(mythria): Build rest arguments array if it is used.
394 int rest_index;
395 if (scope()->rest_parameter(&rest_index)) {
396 UNIMPLEMENTED();
397 }
398
399 // Build assignment to {.this_function} variable if it is used.
400 VisitThisFunctionVariable(scope()->this_function_var());
401
402 // Build assignment to {new.target} variable if it is used.
403 VisitNewTargetVariable(scope()->new_target_var());
404
405 // TODO(rmcilroy): Emit tracing call if requested to do so.
406 if (FLAG_trace) {
407 UNIMPLEMENTED();
408 }
409
410 // Visit illegal re-declaration and bail out if it exists.
411 if (scope()->HasIllegalRedeclaration()) {
412 Visit(scope()->GetIllegalRedeclaration());
413 return;
414 }
415
416 // Visit declarations within the function scope.
417 VisitDeclarations(scope()->declarations());
418
419 // Visit statements in the function body.
420 VisitStatements(info()->literal()->body());
421}
422
423
424void BytecodeGenerator::VisitBlock(Block* stmt) {
425 BlockBuilder block_builder(this->builder());
426 ControlScopeForBreakable execution_control(this, stmt, &block_builder);
427
428 if (stmt->scope() == NULL) {
429 // Visit statements in the same scope, no declarations.
430 VisitStatements(stmt->statements());
431 } else {
432 // Visit declarations and statements in a block scope.
433 if (stmt->scope()->NeedsContext()) {
434 VisitNewLocalBlockContext(stmt->scope());
435 ContextScope scope(this, stmt->scope());
436 VisitDeclarations(stmt->scope()->declarations());
437 VisitStatements(stmt->statements());
438 } else {
439 VisitDeclarations(stmt->scope()->declarations());
440 VisitStatements(stmt->statements());
441 }
442 }
443 if (stmt->labels() != nullptr) block_builder.EndBlock();
444}
445
446
447void BytecodeGenerator::VisitVariableDeclaration(VariableDeclaration* decl) {
448 Variable* variable = decl->proxy()->var();
449 VariableMode mode = decl->mode();
450 // Const and let variables are initialized with the hole so that we can
451 // check that they are only assigned once.
452 bool hole_init = mode == CONST || mode == CONST_LEGACY || mode == LET;
453 switch (variable->location()) {
454 case VariableLocation::GLOBAL:
455 case VariableLocation::UNALLOCATED: {
456 Handle<Oddball> value = variable->binding_needs_init()
457 ? isolate()->factory()->the_hole_value()
458 : isolate()->factory()->undefined_value();
459 globals()->push_back(variable->name());
460 globals()->push_back(value);
461 break;
462 }
463 case VariableLocation::LOCAL:
464 if (hole_init) {
465 Register destination(variable->index());
466 builder()->LoadTheHole().StoreAccumulatorInRegister(destination);
467 }
468 break;
469 case VariableLocation::PARAMETER:
470 if (hole_init) {
471 // The parameter indices are shifted by 1 (receiver is variable
472 // index -1 but is parameter index 0 in BytecodeArrayBuilder).
473 Register destination(builder()->Parameter(variable->index() + 1));
474 builder()->LoadTheHole().StoreAccumulatorInRegister(destination);
475 }
476 break;
477 case VariableLocation::CONTEXT:
478 if (hole_init) {
479 builder()->LoadTheHole().StoreContextSlot(execution_context()->reg(),
480 variable->index());
481 }
482 break;
483 case VariableLocation::LOOKUP:
484 UNIMPLEMENTED();
485 break;
486 }
487}
488
489
490void BytecodeGenerator::VisitFunctionDeclaration(FunctionDeclaration* decl) {
491 Variable* variable = decl->proxy()->var();
492 switch (variable->location()) {
493 case VariableLocation::GLOBAL:
494 case VariableLocation::UNALLOCATED: {
495 Handle<SharedFunctionInfo> function = Compiler::GetSharedFunctionInfo(
496 decl->fun(), info()->script(), info());
497 // Check for stack-overflow exception.
498 if (function.is_null()) return SetStackOverflow();
499 globals()->push_back(variable->name());
500 globals()->push_back(function);
501 break;
502 }
503 case VariableLocation::PARAMETER:
504 case VariableLocation::LOCAL: {
505 VisitForAccumulatorValue(decl->fun());
506 VisitVariableAssignment(variable, FeedbackVectorSlot::Invalid());
507 break;
508 }
509 case VariableLocation::CONTEXT: {
510 DCHECK_EQ(0, execution_context()->ContextChainDepth(variable->scope()));
511 VisitForAccumulatorValue(decl->fun());
512 builder()->StoreContextSlot(execution_context()->reg(),
513 variable->index());
514 break;
515 }
516 case VariableLocation::LOOKUP:
517 UNIMPLEMENTED();
518 }
519}
520
521
522void BytecodeGenerator::VisitImportDeclaration(ImportDeclaration* decl) {
523 UNIMPLEMENTED();
524}
525
526
527void BytecodeGenerator::VisitExportDeclaration(ExportDeclaration* decl) {
528 UNIMPLEMENTED();
529}
530
531
532void BytecodeGenerator::VisitDeclarations(
533 ZoneList<Declaration*>* declarations) {
534 RegisterAllocationScope register_scope(this);
535 DCHECK(globals()->empty());
536 AstVisitor::VisitDeclarations(declarations);
537 if (globals()->empty()) return;
538 int array_index = 0;
539 Handle<FixedArray> data = isolate()->factory()->NewFixedArray(
540 static_cast<int>(globals()->size()), TENURED);
541 for (Handle<Object> obj : *globals()) data->set(array_index++, *obj);
542 int encoded_flags = DeclareGlobalsEvalFlag::encode(info()->is_eval()) |
543 DeclareGlobalsNativeFlag::encode(info()->is_native()) |
544 DeclareGlobalsLanguageMode::encode(language_mode());
545
546 Register pairs = register_allocator()->NewRegister();
547 builder()->LoadLiteral(data);
548 builder()->StoreAccumulatorInRegister(pairs);
549
550 Register flags = register_allocator()->NewRegister();
551 builder()->LoadLiteral(Smi::FromInt(encoded_flags));
552 builder()->StoreAccumulatorInRegister(flags);
553 DCHECK(flags.index() == pairs.index() + 1);
554
555 builder()->CallRuntime(Runtime::kDeclareGlobals, pairs, 2);
556 globals()->clear();
557}
558
559
560void BytecodeGenerator::VisitStatements(ZoneList<Statement*>* statements) {
561 for (int i = 0; i < statements->length(); i++) {
562 // Allocate an outer register allocations scope for the statement.
563 RegisterAllocationScope allocation_scope(this);
564 Statement* stmt = statements->at(i);
565 Visit(stmt);
566 if (stmt->IsJump()) break;
567 }
568}
569
570
571void BytecodeGenerator::VisitExpressionStatement(ExpressionStatement* stmt) {
572 VisitForEffect(stmt->expression());
573}
574
575
576void BytecodeGenerator::VisitEmptyStatement(EmptyStatement* stmt) {
577}
578
579
580void BytecodeGenerator::VisitIfStatement(IfStatement* stmt) {
581 BytecodeLabel else_label, end_label;
582 if (stmt->condition()->ToBooleanIsTrue()) {
583 // Generate then block unconditionally as always true.
584 Visit(stmt->then_statement());
585 } else if (stmt->condition()->ToBooleanIsFalse()) {
586 // Generate else block unconditionally if it exists.
587 if (stmt->HasElseStatement()) {
588 Visit(stmt->else_statement());
589 }
590 } else {
591 // TODO(oth): If then statement is BreakStatement or
592 // ContinueStatement we can reduce number of generated
593 // jump/jump_ifs here. See BasicLoops test.
594 VisitForAccumulatorValue(stmt->condition());
595 builder()->JumpIfFalse(&else_label);
596 Visit(stmt->then_statement());
597 if (stmt->HasElseStatement()) {
598 builder()->Jump(&end_label);
599 builder()->Bind(&else_label);
600 Visit(stmt->else_statement());
601 } else {
602 builder()->Bind(&else_label);
603 }
604 builder()->Bind(&end_label);
605 }
606}
607
608
609void BytecodeGenerator::VisitSloppyBlockFunctionStatement(
610 SloppyBlockFunctionStatement* stmt) {
611 Visit(stmt->statement());
612}
613
614
615void BytecodeGenerator::VisitContinueStatement(ContinueStatement* stmt) {
616 execution_control()->Continue(stmt->target());
617}
618
619
620void BytecodeGenerator::VisitBreakStatement(BreakStatement* stmt) {
621 execution_control()->Break(stmt->target());
622}
623
624
625void BytecodeGenerator::VisitReturnStatement(ReturnStatement* stmt) {
626 VisitForAccumulatorValue(stmt->expression());
627 builder()->Return();
628}
629
630
631void BytecodeGenerator::VisitWithStatement(WithStatement* stmt) {
632 UNIMPLEMENTED();
633}
634
635
636void BytecodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
637 // We need this scope because we visit for register values. We have to
638 // maintain a execution result scope where registers can be allocated.
639 ZoneList<CaseClause*>* clauses = stmt->cases();
640 SwitchBuilder switch_builder(builder(), clauses->length());
641 ControlScopeForBreakable scope(this, stmt, &switch_builder);
642 int default_index = -1;
643
644 // Keep the switch value in a register until a case matches.
645 Register tag = VisitForRegisterValue(stmt->tag());
646
647 // Iterate over all cases and create nodes for label comparison.
648 BytecodeLabel done_label;
649 for (int i = 0; i < clauses->length(); i++) {
650 CaseClause* clause = clauses->at(i);
651
652 // The default is not a test, remember index.
653 if (clause->is_default()) {
654 default_index = i;
655 continue;
656 }
657
658 // Perform label comparison as if via '===' with tag.
659 VisitForAccumulatorValue(clause->label());
660 builder()->CompareOperation(Token::Value::EQ_STRICT, tag,
661 language_mode_strength());
662 switch_builder.Case(i);
663 }
664
665 if (default_index >= 0) {
666 // Emit default jump if there is a default case.
667 switch_builder.DefaultAt(default_index);
668 } else {
669 // Otherwise if we have reached here none of the cases matched, so jump to
670 // done.
671 builder()->Jump(&done_label);
672 }
673
674 // Iterate over all cases and create the case bodies.
675 for (int i = 0; i < clauses->length(); i++) {
676 CaseClause* clause = clauses->at(i);
677 switch_builder.SetCaseTarget(i);
678 VisitStatements(clause->statements());
679 }
680 builder()->Bind(&done_label);
681
682 switch_builder.SetBreakTarget(done_label);
683}
684
685
686void BytecodeGenerator::VisitCaseClause(CaseClause* clause) {
687 // Handled entirely in VisitSwitchStatement.
688 UNREACHABLE();
689}
690
691
692void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
693 LoopBuilder loop_builder(builder());
694 ControlScopeForIteration execution_control(this, stmt, &loop_builder);
695 loop_builder.LoopHeader();
696 if (stmt->cond()->ToBooleanIsFalse()) {
697 Visit(stmt->body());
698 loop_builder.Condition();
699 } else if (stmt->cond()->ToBooleanIsTrue()) {
700 loop_builder.Condition();
701 Visit(stmt->body());
702 loop_builder.JumpToHeader();
703 } else {
704 Visit(stmt->body());
705 loop_builder.Condition();
706 VisitForAccumulatorValue(stmt->cond());
707 loop_builder.JumpToHeaderIfTrue();
708 }
709 loop_builder.EndLoop();
710}
711
712
713void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
714 if (stmt->cond()->ToBooleanIsFalse()) {
715 // If the condition is false there is no need to generate the loop.
716 return;
717 }
718
719 LoopBuilder loop_builder(builder());
720 ControlScopeForIteration execution_control(this, stmt, &loop_builder);
721 loop_builder.LoopHeader();
722 loop_builder.Condition();
723 if (!stmt->cond()->ToBooleanIsTrue()) {
724 VisitForAccumulatorValue(stmt->cond());
725 loop_builder.BreakIfFalse();
726 }
727 Visit(stmt->body());
728 loop_builder.JumpToHeader();
729 loop_builder.EndLoop();
730}
731
732
733void BytecodeGenerator::VisitForStatement(ForStatement* stmt) {
734 if (stmt->init() != nullptr) {
735 Visit(stmt->init());
736 }
737 if (stmt->cond() && stmt->cond()->ToBooleanIsFalse()) {
738 // If the condition is known to be false there is no need to generate
739 // body, next or condition blocks. Init block should be generated.
740 return;
741 }
742
743 LoopBuilder loop_builder(builder());
744 ControlScopeForIteration execution_control(this, stmt, &loop_builder);
745
746 loop_builder.LoopHeader();
747 loop_builder.Condition();
748 if (stmt->cond() && !stmt->cond()->ToBooleanIsTrue()) {
749 VisitForAccumulatorValue(stmt->cond());
750 loop_builder.BreakIfFalse();
751 }
752 Visit(stmt->body());
753 if (stmt->next() != nullptr) {
754 loop_builder.Next();
755 Visit(stmt->next());
756 }
757 loop_builder.JumpToHeader();
758 loop_builder.EndLoop();
759}
760
761
762void BytecodeGenerator::VisitForInAssignment(Expression* expr,
763 FeedbackVectorSlot slot) {
764 DCHECK(expr->IsValidReferenceExpression());
765
766 // Evaluate assignment starting with the value to be stored in the
767 // accumulator.
768 Property* property = expr->AsProperty();
769 LhsKind assign_type = Property::GetAssignType(property);
770 switch (assign_type) {
771 case VARIABLE: {
772 Variable* variable = expr->AsVariableProxy()->var();
773 VisitVariableAssignment(variable, slot);
774 break;
775 }
776 case NAMED_PROPERTY: {
777 RegisterAllocationScope register_scope(this);
778 Register value = register_allocator()->NewRegister();
779 builder()->StoreAccumulatorInRegister(value);
780 Register object = VisitForRegisterValue(property->obj());
781 Handle<String> name = property->key()->AsLiteral()->AsPropertyName();
782 builder()->LoadAccumulatorWithRegister(value);
783 builder()->StoreNamedProperty(object, name, feedback_index(slot),
784 language_mode());
785 break;
786 }
787 case KEYED_PROPERTY: {
788 RegisterAllocationScope register_scope(this);
789 Register value = register_allocator()->NewRegister();
790 builder()->StoreAccumulatorInRegister(value);
791 Register object = VisitForRegisterValue(property->obj());
792 Register key = VisitForRegisterValue(property->key());
793 builder()->LoadAccumulatorWithRegister(value);
794 builder()->StoreKeyedProperty(object, key, feedback_index(slot),
795 language_mode());
796 break;
797 }
798 case NAMED_SUPER_PROPERTY:
799 case KEYED_SUPER_PROPERTY:
800 UNIMPLEMENTED();
801 }
802}
803
804
805void BytecodeGenerator::VisitForInStatement(ForInStatement* stmt) {
806 if (stmt->subject()->IsNullLiteral() ||
807 stmt->subject()->IsUndefinedLiteral(isolate())) {
808 // ForIn generates lots of code, skip if it wouldn't produce any effects.
809 return;
810 }
811
812 LoopBuilder loop_builder(builder());
813 ControlScopeForIteration control_scope(this, stmt, &loop_builder);
814 BytecodeLabel subject_null_label, subject_undefined_label, not_object_label;
815
816 // Prepare the state for executing ForIn.
817 VisitForAccumulatorValue(stmt->subject());
818 builder()->JumpIfUndefined(&subject_undefined_label);
819 builder()->JumpIfNull(&subject_null_label);
820 Register receiver = register_allocator()->NewRegister();
821 builder()->CastAccumulatorToJSObject();
822 builder()->JumpIfNull(&not_object_label);
823 builder()->StoreAccumulatorInRegister(receiver);
824 Register cache_type = register_allocator()->NewRegister();
825 Register cache_array = register_allocator()->NewRegister();
826 Register cache_length = register_allocator()->NewRegister();
827 builder()->ForInPrepare(cache_type, cache_array, cache_length);
828
829 // Set up loop counter
830 Register index = register_allocator()->NewRegister();
831 builder()->LoadLiteral(Smi::FromInt(0));
832 builder()->StoreAccumulatorInRegister(index);
833
834 // The loop
835 loop_builder.LoopHeader();
836 loop_builder.Condition();
837 builder()->ForInDone(index, cache_length);
838 loop_builder.BreakIfTrue();
839 builder()->ForInNext(receiver, cache_type, cache_array, index);
840 loop_builder.ContinueIfUndefined();
841 VisitForInAssignment(stmt->each(), stmt->EachFeedbackSlot());
842 Visit(stmt->body());
843 loop_builder.Next();
844 builder()->ForInStep(index);
845 builder()->StoreAccumulatorInRegister(index);
846 loop_builder.JumpToHeader();
847 loop_builder.EndLoop();
848 builder()->Bind(&not_object_label);
849 builder()->Bind(&subject_null_label);
850 builder()->Bind(&subject_undefined_label);
851}
852
853
854void BytecodeGenerator::VisitForOfStatement(ForOfStatement* stmt) {
855 UNIMPLEMENTED();
856}
857
858
859void BytecodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) {
860 if (FLAG_ignition_fake_try_catch) {
861 Visit(stmt->try_block());
862 return;
863 }
864 UNIMPLEMENTED();
865}
866
867
868void BytecodeGenerator::VisitTryFinallyStatement(TryFinallyStatement* stmt) {
869 if (FLAG_ignition_fake_try_catch) {
870 Visit(stmt->try_block());
871 Visit(stmt->finally_block());
872 return;
873 }
874 UNIMPLEMENTED();
875}
876
877
878void BytecodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) {
879 UNIMPLEMENTED();
880}
881
882
883void BytecodeGenerator::VisitFunctionLiteral(FunctionLiteral* expr) {
884 // Find or build a shared function info.
885 Handle<SharedFunctionInfo> shared_info =
886 Compiler::GetSharedFunctionInfo(expr, info()->script(), info());
887 CHECK(!shared_info.is_null()); // TODO(rmcilroy): Set stack overflow?
888 builder()->CreateClosure(shared_info,
889 expr->pretenure() ? TENURED : NOT_TENURED);
890 execution_result()->SetResultInAccumulator();
891}
892
893
894void BytecodeGenerator::VisitClassLiteral(ClassLiteral* expr) {
895 UNIMPLEMENTED();
896}
897
898
899void BytecodeGenerator::VisitNativeFunctionLiteral(
900 NativeFunctionLiteral* expr) {
901 UNIMPLEMENTED();
902}
903
904
905void BytecodeGenerator::VisitDoExpression(DoExpression* expr) {
906 UNIMPLEMENTED();
907}
908
909
910void BytecodeGenerator::VisitConditional(Conditional* expr) {
911 // TODO(rmcilroy): Spot easy cases where there code would not need to
912 // emit the then block or the else block, e.g. condition is
913 // obviously true/1/false/0.
914
915 BytecodeLabel else_label, end_label;
916
917 VisitForAccumulatorValue(expr->condition());
918 builder()->JumpIfFalse(&else_label);
919
920 VisitForAccumulatorValue(expr->then_expression());
921 builder()->Jump(&end_label);
922
923 builder()->Bind(&else_label);
924 VisitForAccumulatorValue(expr->else_expression());
925 builder()->Bind(&end_label);
926
927 execution_result()->SetResultInAccumulator();
928}
929
930
931void BytecodeGenerator::VisitLiteral(Literal* expr) {
932 if (!execution_result()->IsEffect()) {
933 Handle<Object> value = expr->value();
934 if (value->IsSmi()) {
935 builder()->LoadLiteral(Smi::cast(*value));
936 } else if (value->IsUndefined()) {
937 builder()->LoadUndefined();
938 } else if (value->IsTrue()) {
939 builder()->LoadTrue();
940 } else if (value->IsFalse()) {
941 builder()->LoadFalse();
942 } else if (value->IsNull()) {
943 builder()->LoadNull();
944 } else if (value->IsTheHole()) {
945 builder()->LoadTheHole();
946 } else {
947 builder()->LoadLiteral(value);
948 }
949 execution_result()->SetResultInAccumulator();
950 }
951}
952
953
954void BytecodeGenerator::VisitRegExpLiteral(RegExpLiteral* expr) {
955 // Materialize a regular expression literal.
956 builder()->CreateRegExpLiteral(expr->pattern(), expr->literal_index(),
957 expr->flags());
958 execution_result()->SetResultInAccumulator();
959}
960
961
962void BytecodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
963 // Deep-copy the literal boilerplate.
964 builder()->CreateObjectLiteral(expr->constant_properties(),
965 expr->literal_index(),
966 expr->ComputeFlags(true));
967 Register literal;
968
969 // Store computed values into the literal.
970 bool literal_in_accumulator = true;
971 int property_index = 0;
972 AccessorTable accessor_table(zone());
973 for (; property_index < expr->properties()->length(); property_index++) {
974 ObjectLiteral::Property* property = expr->properties()->at(property_index);
975 if (property->is_computed_name()) break;
976 if (property->IsCompileTimeValue()) continue;
977
978 if (literal_in_accumulator) {
979 literal = register_allocator()->NewRegister();
980 builder()->StoreAccumulatorInRegister(literal);
981 literal_in_accumulator = false;
982 }
983
984 RegisterAllocationScope inner_register_scope(this);
985 Literal* literal_key = property->key()->AsLiteral();
986 switch (property->kind()) {
987 case ObjectLiteral::Property::CONSTANT:
988 UNREACHABLE();
989 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
990 DCHECK(!CompileTimeValue::IsCompileTimeValue(property->value()));
991 // Fall through.
992 case ObjectLiteral::Property::COMPUTED: {
993 // It is safe to use [[Put]] here because the boilerplate already
994 // contains computed properties with an uninitialized value.
995 if (literal_key->value()->IsInternalizedString()) {
996 if (property->emit_store()) {
997 VisitForAccumulatorValue(property->value());
998 builder()->StoreNamedProperty(
999 literal, literal_key->AsPropertyName(),
1000 feedback_index(property->GetSlot(0)), language_mode());
1001 } else {
1002 VisitForEffect(property->value());
1003 }
1004 } else {
1005 register_allocator()->PrepareForConsecutiveAllocations(3);
1006 Register key = register_allocator()->NextConsecutiveRegister();
1007 Register value = register_allocator()->NextConsecutiveRegister();
1008 Register language = register_allocator()->NextConsecutiveRegister();
1009 // TODO(oth): This is problematic - can't assume contiguous here.
1010 // literal is allocated in outer register scope, whereas key, value,
1011 // language are in another.
1012 DCHECK(Register::AreContiguous(literal, key, value, language));
1013 VisitForAccumulatorValue(property->key());
1014 builder()->StoreAccumulatorInRegister(key);
1015 VisitForAccumulatorValue(property->value());
1016 builder()->StoreAccumulatorInRegister(value);
1017 if (property->emit_store()) {
1018 builder()
1019 ->LoadLiteral(Smi::FromInt(SLOPPY))
1020 .StoreAccumulatorInRegister(language)
1021 .CallRuntime(Runtime::kSetProperty, literal, 4);
1022 VisitSetHomeObject(value, literal, property);
1023 }
1024 }
1025 break;
1026 }
1027 case ObjectLiteral::Property::PROTOTYPE: {
1028 register_allocator()->PrepareForConsecutiveAllocations(1);
1029 DCHECK(property->emit_store());
1030 Register value = register_allocator()->NextConsecutiveRegister();
1031 DCHECK(Register::AreContiguous(literal, value));
1032 VisitForAccumulatorValue(property->value());
1033 builder()->StoreAccumulatorInRegister(value).CallRuntime(
1034 Runtime::kInternalSetPrototype, literal, 2);
1035 break;
1036 }
1037 case ObjectLiteral::Property::GETTER:
1038 if (property->emit_store()) {
1039 accessor_table.lookup(literal_key)->second->getter = property;
1040 }
1041 break;
1042 case ObjectLiteral::Property::SETTER:
1043 if (property->emit_store()) {
1044 accessor_table.lookup(literal_key)->second->setter = property;
1045 }
1046 break;
1047 }
1048 }
1049
1050 // Define accessors, using only a single call to the runtime for each pair of
1051 // corresponding getters and setters.
1052 for (AccessorTable::Iterator it = accessor_table.begin();
1053 it != accessor_table.end(); ++it) {
1054 RegisterAllocationScope inner_register_scope(this);
1055 register_allocator()->PrepareForConsecutiveAllocations(4);
1056 Register name = register_allocator()->NextConsecutiveRegister();
1057 Register getter = register_allocator()->NextConsecutiveRegister();
1058 Register setter = register_allocator()->NextConsecutiveRegister();
1059 Register attr = register_allocator()->NextConsecutiveRegister();
1060 DCHECK(Register::AreContiguous(literal, name, getter, setter, attr));
1061 VisitForAccumulatorValue(it->first);
1062 builder()->StoreAccumulatorInRegister(name);
1063 VisitObjectLiteralAccessor(literal, it->second->getter, getter);
1064 VisitObjectLiteralAccessor(literal, it->second->setter, setter);
1065 builder()
1066 ->LoadLiteral(Smi::FromInt(NONE))
1067 .StoreAccumulatorInRegister(attr)
1068 .CallRuntime(Runtime::kDefineAccessorPropertyUnchecked, literal, 5);
1069 }
1070
1071 // Object literals have two parts. The "static" part on the left contains no
1072 // computed property names, and so we can compute its map ahead of time; see
1073 // Runtime_CreateObjectLiteralBoilerplate. The second "dynamic" part starts
1074 // with the first computed property name and continues with all properties to
1075 // its right. All the code from above initializes the static component of the
1076 // object literal, and arranges for the map of the result to reflect the
1077 // static order in which the keys appear. For the dynamic properties, we
1078 // compile them into a series of "SetOwnProperty" runtime calls. This will
1079 // preserve insertion order.
1080 for (; property_index < expr->properties()->length(); property_index++) {
1081 if (literal_in_accumulator) {
1082 literal = register_allocator()->NewRegister();
1083 builder()->StoreAccumulatorInRegister(literal);
1084 literal_in_accumulator = false;
1085 }
1086
1087 ObjectLiteral::Property* property = expr->properties()->at(property_index);
1088 RegisterAllocationScope inner_register_scope(this);
1089 if (property->kind() == ObjectLiteral::Property::PROTOTYPE) {
1090 DCHECK(property->emit_store());
1091 Register value = register_allocator()->NewRegister();
1092 DCHECK(Register::AreContiguous(literal, value));
1093 VisitForAccumulatorValue(property->value());
1094 builder()->StoreAccumulatorInRegister(value).CallRuntime(
1095 Runtime::kInternalSetPrototype, literal, 2);
1096 continue;
1097 }
1098
1099 register_allocator()->PrepareForConsecutiveAllocations(3);
1100 Register key = register_allocator()->NextConsecutiveRegister();
1101 Register value = register_allocator()->NextConsecutiveRegister();
1102 Register attr = register_allocator()->NextConsecutiveRegister();
1103 DCHECK(Register::AreContiguous(literal, key, value, attr));
1104
1105 VisitForAccumulatorValue(property->key());
1106 builder()->CastAccumulatorToName().StoreAccumulatorInRegister(key);
1107 VisitForAccumulatorValue(property->value());
1108 builder()->StoreAccumulatorInRegister(value);
1109 VisitSetHomeObject(value, literal, property);
1110 builder()->LoadLiteral(Smi::FromInt(NONE)).StoreAccumulatorInRegister(attr);
1111 Runtime::FunctionId function_id = static_cast<Runtime::FunctionId>(-1);
1112 switch (property->kind()) {
1113 case ObjectLiteral::Property::CONSTANT:
1114 case ObjectLiteral::Property::COMPUTED:
1115 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
1116 function_id = Runtime::kDefineDataPropertyUnchecked;
1117 break;
1118 case ObjectLiteral::Property::PROTOTYPE:
1119 UNREACHABLE(); // Handled specially above.
1120 break;
1121 case ObjectLiteral::Property::GETTER:
1122 function_id = Runtime::kDefineGetterPropertyUnchecked;
1123 break;
1124 case ObjectLiteral::Property::SETTER:
1125 function_id = Runtime::kDefineSetterPropertyUnchecked;
1126 break;
1127 }
1128 builder()->CallRuntime(function_id, literal, 4);
1129 }
1130
1131 // Transform literals that contain functions to fast properties.
1132 if (expr->has_function()) {
1133 DCHECK(!literal_in_accumulator);
1134 builder()->CallRuntime(Runtime::kToFastProperties, literal, 1);
1135 }
1136
1137 if (!literal_in_accumulator) {
1138 // Restore literal array into accumulator.
1139 builder()->LoadAccumulatorWithRegister(literal);
1140 }
1141 execution_result()->SetResultInAccumulator();
1142}
1143
1144
1145void BytecodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
1146 // Deep-copy the literal boilerplate.
1147 builder()->CreateArrayLiteral(expr->constant_elements(),
1148 expr->literal_index(),
1149 expr->ComputeFlags(true));
1150 Register index, literal;
1151
1152 // Evaluate all the non-constant subexpressions and store them into the
1153 // newly cloned array.
1154 bool literal_in_accumulator = true;
1155 for (int array_index = 0; array_index < expr->values()->length();
1156 array_index++) {
1157 Expression* subexpr = expr->values()->at(array_index);
1158 if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
1159 if (subexpr->IsSpread()) {
1160 // TODO(rmcilroy): Deal with spread expressions.
1161 UNIMPLEMENTED();
1162 }
1163
1164 if (literal_in_accumulator) {
1165 index = register_allocator()->NewRegister();
1166 literal = register_allocator()->NewRegister();
1167 builder()->StoreAccumulatorInRegister(literal);
1168 literal_in_accumulator = false;
1169 }
1170
1171 FeedbackVectorSlot slot = expr->LiteralFeedbackSlot();
1172 builder()
1173 ->LoadLiteral(Smi::FromInt(array_index))
1174 .StoreAccumulatorInRegister(index);
1175 VisitForAccumulatorValue(subexpr);
1176 builder()->StoreKeyedProperty(literal, index, feedback_index(slot),
1177 language_mode());
1178 }
1179
1180 if (!literal_in_accumulator) {
1181 // Restore literal array into accumulator.
1182 builder()->LoadAccumulatorWithRegister(literal);
1183 }
1184 execution_result()->SetResultInAccumulator();
1185}
1186
1187
1188void BytecodeGenerator::VisitVariableProxy(VariableProxy* proxy) {
1189 VisitVariableLoad(proxy->var(), proxy->VariableFeedbackSlot());
1190}
1191
1192
1193void BytecodeGenerator::VisitVariableLoad(Variable* variable,
1194 FeedbackVectorSlot slot,
1195 TypeofMode typeof_mode) {
1196 switch (variable->location()) {
1197 case VariableLocation::LOCAL: {
1198 Register source(Register(variable->index()));
1199 builder()->LoadAccumulatorWithRegister(source);
1200 execution_result()->SetResultInAccumulator();
1201 break;
1202 }
1203 case VariableLocation::PARAMETER: {
1204 // The parameter indices are shifted by 1 (receiver is variable
1205 // index -1 but is parameter index 0 in BytecodeArrayBuilder).
1206 Register source = builder()->Parameter(variable->index() + 1);
1207 builder()->LoadAccumulatorWithRegister(source);
1208 execution_result()->SetResultInAccumulator();
1209 break;
1210 }
1211 case VariableLocation::GLOBAL:
1212 case VariableLocation::UNALLOCATED: {
1213 builder()->LoadGlobal(variable->name(), feedback_index(slot),
1214 language_mode(), typeof_mode);
1215 execution_result()->SetResultInAccumulator();
1216 break;
1217 }
1218 case VariableLocation::CONTEXT: {
1219 int depth = execution_context()->ContextChainDepth(variable->scope());
1220 ContextScope* context = execution_context()->Previous(depth);
1221 Register context_reg;
1222 if (context) {
1223 context_reg = context->reg();
1224 } else {
1225 context_reg = register_allocator()->NewRegister();
1226 // Walk the context chain to find the context at the given depth.
1227 // TODO(rmcilroy): Perform this work in a bytecode handler once we have
1228 // a generic mechanism for performing jumps in interpreter.cc.
1229 // TODO(mythria): Also update bytecode graph builder with correct depth
1230 // when this changes.
1231 builder()
1232 ->LoadAccumulatorWithRegister(execution_context()->reg())
1233 .StoreAccumulatorInRegister(context_reg);
1234 for (int i = 0; i < depth; ++i) {
1235 builder()
1236 ->LoadContextSlot(context_reg, Context::PREVIOUS_INDEX)
1237 .StoreAccumulatorInRegister(context_reg);
1238 }
1239 }
1240 builder()->LoadContextSlot(context_reg, variable->index());
1241 execution_result()->SetResultInAccumulator();
1242 // TODO(rmcilroy): Perform check for uninitialized legacy const, const and
1243 // let variables.
1244 break;
1245 }
1246 case VariableLocation::LOOKUP: {
1247 builder()->LoadLookupSlot(variable->name(), typeof_mode);
1248 execution_result()->SetResultInAccumulator();
1249 break;
1250 }
1251 }
1252}
1253
1254
1255void BytecodeGenerator::VisitVariableLoadForAccumulatorValue(
1256 Variable* variable, FeedbackVectorSlot slot, TypeofMode typeof_mode) {
1257 AccumulatorResultScope accumulator_result(this);
1258 VisitVariableLoad(variable, slot, typeof_mode);
1259}
1260
1261
1262Register BytecodeGenerator::VisitVariableLoadForRegisterValue(
1263 Variable* variable, FeedbackVectorSlot slot, TypeofMode typeof_mode) {
1264 RegisterResultScope register_scope(this);
1265 VisitVariableLoad(variable, slot, typeof_mode);
1266 return register_scope.ResultRegister();
1267}
1268
1269
1270void BytecodeGenerator::VisitVariableAssignment(Variable* variable,
1271 FeedbackVectorSlot slot) {
1272 switch (variable->location()) {
1273 case VariableLocation::LOCAL: {
1274 // TODO(rmcilroy): support const mode initialization.
1275 Register destination(variable->index());
1276 builder()->StoreAccumulatorInRegister(destination);
1277 break;
1278 }
1279 case VariableLocation::PARAMETER: {
1280 // The parameter indices are shifted by 1 (receiver is variable
1281 // index -1 but is parameter index 0 in BytecodeArrayBuilder).
1282 Register destination(builder()->Parameter(variable->index() + 1));
1283 builder()->StoreAccumulatorInRegister(destination);
1284 break;
1285 }
1286 case VariableLocation::GLOBAL:
1287 case VariableLocation::UNALLOCATED: {
1288 builder()->StoreGlobal(variable->name(), feedback_index(slot),
1289 language_mode());
1290 break;
1291 }
1292 case VariableLocation::CONTEXT: {
1293 // TODO(rmcilroy): support const mode initialization.
1294 int depth = execution_context()->ContextChainDepth(variable->scope());
1295 ContextScope* context = execution_context()->Previous(depth);
1296 Register context_reg;
1297 if (context) {
1298 context_reg = context->reg();
1299 } else {
1300 Register value_temp = register_allocator()->NewRegister();
1301 context_reg = register_allocator()->NewRegister();
1302 // Walk the context chain to find the context at the given depth.
1303 // TODO(rmcilroy): Perform this work in a bytecode handler once we have
1304 // a generic mechanism for performing jumps in interpreter.cc.
1305 // TODO(mythria): Also update bytecode graph builder with correct depth
1306 // when this changes.
1307 builder()
1308 ->StoreAccumulatorInRegister(value_temp)
1309 .LoadAccumulatorWithRegister(execution_context()->reg())
1310 .StoreAccumulatorInRegister(context_reg);
1311 for (int i = 0; i < depth; ++i) {
1312 builder()
1313 ->LoadContextSlot(context_reg, Context::PREVIOUS_INDEX)
1314 .StoreAccumulatorInRegister(context_reg);
1315 }
1316 builder()->LoadAccumulatorWithRegister(value_temp);
1317 }
1318 builder()->StoreContextSlot(context_reg, variable->index());
1319 break;
1320 }
1321 case VariableLocation::LOOKUP: {
1322 builder()->StoreLookupSlot(variable->name(), language_mode());
1323 break;
1324 }
1325 }
1326}
1327
1328
1329void BytecodeGenerator::VisitAssignment(Assignment* expr) {
1330 DCHECK(expr->target()->IsValidReferenceExpression());
1331 Register object, key;
1332 Handle<String> name;
1333
1334 // Left-hand side can only be a property, a global or a variable slot.
1335 Property* property = expr->target()->AsProperty();
1336 LhsKind assign_type = Property::GetAssignType(property);
1337
1338 // Evaluate LHS expression.
1339 switch (assign_type) {
1340 case VARIABLE:
1341 // Nothing to do to evaluate variable assignment LHS.
1342 break;
1343 case NAMED_PROPERTY: {
1344 object = VisitForRegisterValue(property->obj());
1345 name = property->key()->AsLiteral()->AsPropertyName();
1346 break;
1347 }
1348 case KEYED_PROPERTY: {
1349 object = VisitForRegisterValue(property->obj());
1350 if (expr->is_compound()) {
1351 // Use VisitForAccumulator and store to register so that the key is
1352 // still in the accumulator for loading the old value below.
1353 key = register_allocator()->NewRegister();
1354 VisitForAccumulatorValue(property->key());
1355 builder()->StoreAccumulatorInRegister(key);
1356 } else {
1357 key = VisitForRegisterValue(property->key());
1358 }
1359 break;
1360 }
1361 case NAMED_SUPER_PROPERTY:
1362 case KEYED_SUPER_PROPERTY:
1363 UNIMPLEMENTED();
1364 }
1365
1366 // Evaluate the value and potentially handle compound assignments by loading
1367 // the left-hand side value and performing a binary operation.
1368 if (expr->is_compound()) {
1369 Register old_value;
1370 switch (assign_type) {
1371 case VARIABLE: {
1372 VariableProxy* proxy = expr->target()->AsVariableProxy();
1373 old_value = VisitVariableLoadForRegisterValue(
1374 proxy->var(), proxy->VariableFeedbackSlot());
1375 break;
1376 }
1377 case NAMED_PROPERTY: {
1378 FeedbackVectorSlot slot = property->PropertyFeedbackSlot();
1379 old_value = register_allocator()->NewRegister();
1380 builder()
1381 ->LoadNamedProperty(object, name, feedback_index(slot),
1382 language_mode())
1383 .StoreAccumulatorInRegister(old_value);
1384 break;
1385 }
1386 case KEYED_PROPERTY: {
1387 // Key is already in accumulator at this point due to evaluating the
1388 // LHS above.
1389 FeedbackVectorSlot slot = property->PropertyFeedbackSlot();
1390 old_value = register_allocator()->NewRegister();
1391 builder()
1392 ->LoadKeyedProperty(object, feedback_index(slot), language_mode())
1393 .StoreAccumulatorInRegister(old_value);
1394 break;
1395 }
1396 case NAMED_SUPER_PROPERTY:
1397 case KEYED_SUPER_PROPERTY:
1398 UNIMPLEMENTED();
1399 break;
1400 }
1401 VisitForAccumulatorValue(expr->value());
1402 builder()->BinaryOperation(expr->binary_op(), old_value,
1403 language_mode_strength());
1404 } else {
1405 VisitForAccumulatorValue(expr->value());
1406 }
1407
1408 // Store the value.
1409 FeedbackVectorSlot slot = expr->AssignmentSlot();
1410 switch (assign_type) {
1411 case VARIABLE: {
1412 // TODO(oth): The VisitVariableAssignment() call is hard to reason about.
1413 // Is the value in the accumulator safe? Yes, but scary.
1414 Variable* variable = expr->target()->AsVariableProxy()->var();
1415 VisitVariableAssignment(variable, slot);
1416 break;
1417 }
1418 case NAMED_PROPERTY:
1419 builder()->StoreNamedProperty(object, name, feedback_index(slot),
1420 language_mode());
1421 break;
1422 case KEYED_PROPERTY:
1423 builder()->StoreKeyedProperty(object, key, feedback_index(slot),
1424 language_mode());
1425 break;
1426 case NAMED_SUPER_PROPERTY:
1427 case KEYED_SUPER_PROPERTY:
1428 UNIMPLEMENTED();
1429 }
1430 execution_result()->SetResultInAccumulator();
1431}
1432
1433
1434void BytecodeGenerator::VisitYield(Yield* expr) { UNIMPLEMENTED(); }
1435
1436
1437void BytecodeGenerator::VisitThrow(Throw* expr) {
1438 VisitForAccumulatorValue(expr->exception());
1439 builder()->Throw();
1440}
1441
1442
1443void BytecodeGenerator::VisitPropertyLoad(Register obj, Property* expr) {
1444 LhsKind property_kind = Property::GetAssignType(expr);
1445 FeedbackVectorSlot slot = expr->PropertyFeedbackSlot();
1446 switch (property_kind) {
1447 case VARIABLE:
1448 UNREACHABLE();
1449 case NAMED_PROPERTY: {
1450 builder()->LoadNamedProperty(obj,
1451 expr->key()->AsLiteral()->AsPropertyName(),
1452 feedback_index(slot), language_mode());
1453 break;
1454 }
1455 case KEYED_PROPERTY: {
1456 VisitForAccumulatorValue(expr->key());
1457 builder()->LoadKeyedProperty(obj, feedback_index(slot), language_mode());
1458 break;
1459 }
1460 case NAMED_SUPER_PROPERTY:
1461 case KEYED_SUPER_PROPERTY:
1462 UNIMPLEMENTED();
1463 }
1464 execution_result()->SetResultInAccumulator();
1465}
1466
1467
1468void BytecodeGenerator::VisitPropertyLoadForAccumulator(Register obj,
1469 Property* expr) {
1470 AccumulatorResultScope result_scope(this);
1471 VisitPropertyLoad(obj, expr);
1472}
1473
1474
1475void BytecodeGenerator::VisitProperty(Property* expr) {
1476 Register obj = VisitForRegisterValue(expr->obj());
1477 VisitPropertyLoad(obj, expr);
1478}
1479
1480
1481Register BytecodeGenerator::VisitArguments(ZoneList<Expression*>* args) {
1482 if (args->length() == 0) {
1483 return Register();
1484 }
1485
1486 // Visit arguments and place in a contiguous block of temporary
1487 // registers. Return the first temporary register corresponding to
1488 // the first argument.
1489 //
1490 // NB the caller may have already called
1491 // PrepareForConsecutiveAllocations() with args->length() + N. The
1492 // second call here will be a no-op provided there have been N or
1493 // less calls to NextConsecutiveRegister(). Otherwise, the arguments
1494 // here will be consecutive, but they will not be consecutive with
1495 // earlier consecutive allocations made by the caller.
1496 register_allocator()->PrepareForConsecutiveAllocations(args->length());
1497
1498 // Visit for first argument that goes into returned register
1499 Register first_arg = register_allocator()->NextConsecutiveRegister();
1500 VisitForAccumulatorValue(args->at(0));
1501 builder()->StoreAccumulatorInRegister(first_arg);
1502
1503 // Visit remaining arguments
1504 for (int i = 1; i < static_cast<int>(args->length()); i++) {
1505 Register ith_arg = register_allocator()->NextConsecutiveRegister();
1506 VisitForAccumulatorValue(args->at(i));
1507 builder()->StoreAccumulatorInRegister(ith_arg);
1508 DCHECK(ith_arg.index() - i == first_arg.index());
1509 }
1510 return first_arg;
1511}
1512
1513
1514void BytecodeGenerator::VisitCall(Call* expr) {
1515 Expression* callee_expr = expr->expression();
1516 Call::CallType call_type = expr->GetCallType(isolate());
1517
1518 // Prepare the callee and the receiver to the function call. This depends on
1519 // the semantics of the underlying call type.
1520
1521 // The receiver and arguments need to be allocated consecutively for
1522 // Call(). We allocate the callee and receiver consecutively for calls to
1523 // kLoadLookupSlot. Future optimizations could avoid this there are no
1524 // arguments or the receiver and arguments are already consecutive.
1525 ZoneList<Expression*>* args = expr->arguments();
1526 register_allocator()->PrepareForConsecutiveAllocations(args->length() + 2);
1527 Register callee = register_allocator()->NextConsecutiveRegister();
1528 Register receiver = register_allocator()->NextConsecutiveRegister();
1529
1530 switch (call_type) {
1531 case Call::NAMED_PROPERTY_CALL:
1532 case Call::KEYED_PROPERTY_CALL: {
1533 Property* property = callee_expr->AsProperty();
1534 VisitForAccumulatorValue(property->obj());
1535 builder()->StoreAccumulatorInRegister(receiver);
1536 VisitPropertyLoadForAccumulator(receiver, property);
1537 builder()->StoreAccumulatorInRegister(callee);
1538 break;
1539 }
1540 case Call::GLOBAL_CALL: {
1541 // Receiver is undefined for global calls.
1542 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver);
1543 // Load callee as a global variable.
1544 VariableProxy* proxy = callee_expr->AsVariableProxy();
1545 VisitVariableLoadForAccumulatorValue(proxy->var(),
1546 proxy->VariableFeedbackSlot());
1547 builder()->StoreAccumulatorInRegister(callee);
1548 break;
1549 }
1550 case Call::LOOKUP_SLOT_CALL:
1551 case Call::POSSIBLY_EVAL_CALL: {
1552 if (callee_expr->AsVariableProxy()->var()->IsLookupSlot()) {
1553 RegisterAllocationScope inner_register_scope(this);
1554 register_allocator()->PrepareForConsecutiveAllocations(2);
1555 Register context = register_allocator()->NextConsecutiveRegister();
1556 Register name = register_allocator()->NextConsecutiveRegister();
1557
1558 // Call LoadLookupSlot to get the callee and receiver.
1559 DCHECK(Register::AreContiguous(callee, receiver));
1560 Variable* variable = callee_expr->AsVariableProxy()->var();
1561 builder()
1562 ->MoveRegister(Register::function_context(), context)
1563 .LoadLiteral(variable->name())
1564 .StoreAccumulatorInRegister(name)
1565 .CallRuntimeForPair(Runtime::kLoadLookupSlot, context, 2, callee);
1566 break;
1567 }
1568 // Fall through.
1569 DCHECK_EQ(call_type, Call::POSSIBLY_EVAL_CALL);
1570 }
1571 case Call::OTHER_CALL: {
1572 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver);
1573 VisitForAccumulatorValue(callee_expr);
1574 builder()->StoreAccumulatorInRegister(callee);
1575 break;
1576 }
1577 case Call::NAMED_SUPER_PROPERTY_CALL:
1578 case Call::KEYED_SUPER_PROPERTY_CALL:
1579 case Call::SUPER_CALL:
1580 UNIMPLEMENTED();
1581 }
1582
1583 // Evaluate all arguments to the function call and store in sequential
1584 // registers.
1585 Register arg = VisitArguments(args);
1586 CHECK(args->length() == 0 || arg.index() == receiver.index() + 1);
1587
1588 // Resolve callee for a potential direct eval call. This block will mutate the
1589 // callee value.
1590 if (call_type == Call::POSSIBLY_EVAL_CALL && args->length() > 0) {
1591 RegisterAllocationScope inner_register_scope(this);
1592 register_allocator()->PrepareForConsecutiveAllocations(5);
1593 Register callee_for_eval = register_allocator()->NextConsecutiveRegister();
1594 Register source = register_allocator()->NextConsecutiveRegister();
1595 Register function = register_allocator()->NextConsecutiveRegister();
1596 Register language = register_allocator()->NextConsecutiveRegister();
1597 Register position = register_allocator()->NextConsecutiveRegister();
1598
1599 // Set up arguments for ResolvePossiblyDirectEval by copying callee, source
1600 // strings and function closure, and loading language and
1601 // position.
1602 builder()
1603 ->MoveRegister(callee, callee_for_eval)
1604 .MoveRegister(arg, source)
1605 .MoveRegister(Register::function_closure(), function)
1606 .LoadLiteral(Smi::FromInt(language_mode()))
1607 .StoreAccumulatorInRegister(language)
1608 .LoadLiteral(
1609 Smi::FromInt(execution_context()->scope()->start_position()))
1610 .StoreAccumulatorInRegister(position);
1611
1612 // Call ResolvePossiblyDirectEval and modify the callee.
1613 builder()
1614 ->CallRuntime(Runtime::kResolvePossiblyDirectEval, callee_for_eval, 5)
1615 .StoreAccumulatorInRegister(callee);
1616 }
1617
1618 // TODO(rmcilroy): Use CallIC to allow call type feedback.
1619 builder()->Call(callee, receiver, args->length(),
1620 feedback_index(expr->CallFeedbackICSlot()));
1621 execution_result()->SetResultInAccumulator();
1622}
1623
1624
1625void BytecodeGenerator::VisitCallNew(CallNew* expr) {
1626 Register constructor = register_allocator()->NewRegister();
1627 VisitForAccumulatorValue(expr->expression());
1628 builder()->StoreAccumulatorInRegister(constructor);
1629
1630 ZoneList<Expression*>* args = expr->arguments();
1631 Register first_arg = VisitArguments(args);
1632 builder()->New(constructor, first_arg, args->length());
1633 execution_result()->SetResultInAccumulator();
1634}
1635
1636
1637void BytecodeGenerator::VisitCallRuntime(CallRuntime* expr) {
1638 ZoneList<Expression*>* args = expr->arguments();
1639 Register receiver;
1640 if (expr->is_jsruntime()) {
1641 // Allocate a register for the receiver and load it with undefined.
1642 register_allocator()->PrepareForConsecutiveAllocations(args->length() + 1);
1643 receiver = register_allocator()->NextConsecutiveRegister();
1644 builder()->LoadUndefined().StoreAccumulatorInRegister(receiver);
1645 }
1646 // Evaluate all arguments to the runtime call.
1647 Register first_arg = VisitArguments(args);
1648
1649 if (expr->is_jsruntime()) {
1650 DCHECK(args->length() == 0 || first_arg.index() == receiver.index() + 1);
1651 builder()->CallJSRuntime(expr->context_index(), receiver, args->length());
1652 } else {
1653 Runtime::FunctionId function_id = expr->function()->function_id;
1654 builder()->CallRuntime(function_id, first_arg, args->length());
1655 }
1656 execution_result()->SetResultInAccumulator();
1657}
1658
1659
1660void BytecodeGenerator::VisitVoid(UnaryOperation* expr) {
1661 VisitForEffect(expr->expression());
1662 builder()->LoadUndefined();
1663 execution_result()->SetResultInAccumulator();
1664}
1665
1666
1667void BytecodeGenerator::VisitTypeOf(UnaryOperation* expr) {
1668 if (expr->expression()->IsVariableProxy()) {
1669 // Typeof does not throw a reference error on global variables, hence we
1670 // perform a non-contextual load in case the operand is a variable proxy.
1671 VariableProxy* proxy = expr->expression()->AsVariableProxy();
1672 VisitVariableLoadForAccumulatorValue(
1673 proxy->var(), proxy->VariableFeedbackSlot(), INSIDE_TYPEOF);
1674 } else {
1675 VisitForAccumulatorValue(expr->expression());
1676 }
1677 builder()->TypeOf();
1678 execution_result()->SetResultInAccumulator();
1679}
1680
1681
1682void BytecodeGenerator::VisitNot(UnaryOperation* expr) {
1683 VisitForAccumulatorValue(expr->expression());
1684 builder()->LogicalNot();
1685 execution_result()->SetResultInAccumulator();
1686}
1687
1688
1689void BytecodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
1690 switch (expr->op()) {
1691 case Token::Value::NOT:
1692 VisitNot(expr);
1693 break;
1694 case Token::Value::TYPEOF:
1695 VisitTypeOf(expr);
1696 break;
1697 case Token::Value::VOID:
1698 VisitVoid(expr);
1699 break;
1700 case Token::Value::DELETE:
1701 VisitDelete(expr);
1702 break;
1703 case Token::Value::BIT_NOT:
1704 case Token::Value::ADD:
1705 case Token::Value::SUB:
1706 // These operators are converted to an equivalent binary operators in
1707 // the parser. These operators are not expected to be visited here.
1708 UNREACHABLE();
1709 default:
1710 UNREACHABLE();
1711 }
1712}
1713
1714
1715void BytecodeGenerator::VisitDelete(UnaryOperation* expr) {
1716 if (expr->expression()->IsProperty()) {
1717 // Delete of an object property is allowed both in sloppy
1718 // and strict modes.
1719 Property* property = expr->expression()->AsProperty();
1720 Register object = VisitForRegisterValue(property->obj());
1721 VisitForAccumulatorValue(property->key());
1722 builder()->Delete(object, language_mode());
1723 } else if (expr->expression()->IsVariableProxy()) {
1724 // Delete of an unqualified identifier is allowed in sloppy mode but is
1725 // not allowed in strict mode. Deleting 'this' is allowed in both modes.
1726 VariableProxy* proxy = expr->expression()->AsVariableProxy();
1727 Variable* variable = proxy->var();
1728 DCHECK(is_sloppy(language_mode()) || variable->HasThisName(isolate()));
1729 switch (variable->location()) {
1730 case VariableLocation::GLOBAL:
1731 case VariableLocation::UNALLOCATED: {
1732 // Global var, let, const or variables not explicitly declared.
1733 Register native_context = register_allocator()->NewRegister();
1734 Register global_object = register_allocator()->NewRegister();
1735 builder()
1736 ->LoadContextSlot(execution_context()->reg(),
1737 Context::NATIVE_CONTEXT_INDEX)
1738 .StoreAccumulatorInRegister(native_context)
1739 .LoadContextSlot(native_context, Context::EXTENSION_INDEX)
1740 .StoreAccumulatorInRegister(global_object)
1741 .LoadLiteral(variable->name())
1742 .Delete(global_object, language_mode());
1743 break;
1744 }
1745 case VariableLocation::PARAMETER:
1746 case VariableLocation::LOCAL:
1747 case VariableLocation::CONTEXT: {
1748 // Deleting local var/let/const, context variables, and arguments
1749 // does not have any effect.
1750 if (variable->HasThisName(isolate())) {
1751 builder()->LoadTrue();
1752 } else {
1753 builder()->LoadFalse();
1754 }
1755 break;
1756 }
1757 case VariableLocation::LOOKUP: {
1758 builder()->LoadLiteral(variable->name()).DeleteLookupSlot();
1759 break;
1760 }
1761 default:
1762 UNREACHABLE();
1763 }
1764 } else {
1765 // Delete of an unresolvable reference returns true.
1766 VisitForEffect(expr->expression());
1767 builder()->LoadTrue();
1768 }
1769 execution_result()->SetResultInAccumulator();
1770}
1771
1772
1773void BytecodeGenerator::VisitCountOperation(CountOperation* expr) {
1774 DCHECK(expr->expression()->IsValidReferenceExpressionOrThis());
1775
1776 // Left-hand side can only be a property, a global or a variable slot.
1777 Property* property = expr->expression()->AsProperty();
1778 LhsKind assign_type = Property::GetAssignType(property);
1779
1780 // TODO(rmcilroy): Set is_postfix to false if visiting for effect.
1781 bool is_postfix = expr->is_postfix();
1782
1783 // Evaluate LHS expression and get old value.
1784 Register obj, key, old_value;
1785 Handle<String> name;
1786 switch (assign_type) {
1787 case VARIABLE: {
1788 VariableProxy* proxy = expr->expression()->AsVariableProxy();
1789 VisitVariableLoadForAccumulatorValue(proxy->var(),
1790 proxy->VariableFeedbackSlot());
1791 break;
1792 }
1793 case NAMED_PROPERTY: {
1794 FeedbackVectorSlot slot = property->PropertyFeedbackSlot();
1795 obj = VisitForRegisterValue(property->obj());
1796 name = property->key()->AsLiteral()->AsPropertyName();
1797 builder()->LoadNamedProperty(obj, name, feedback_index(slot),
1798 language_mode());
1799 break;
1800 }
1801 case KEYED_PROPERTY: {
1802 FeedbackVectorSlot slot = property->PropertyFeedbackSlot();
1803 obj = VisitForRegisterValue(property->obj());
1804 // Use visit for accumulator here since we need the key in the accumulator
1805 // for the LoadKeyedProperty.
1806 key = register_allocator()->NewRegister();
1807 VisitForAccumulatorValue(property->key());
1808 builder()->StoreAccumulatorInRegister(key).LoadKeyedProperty(
1809 obj, feedback_index(slot), language_mode());
1810 break;
1811 }
1812 case NAMED_SUPER_PROPERTY:
1813 case KEYED_SUPER_PROPERTY:
1814 UNIMPLEMENTED();
1815 }
1816
1817 // Convert old value into a number.
1818 if (!is_strong(language_mode())) {
1819 builder()->CastAccumulatorToNumber();
1820 }
1821
1822 // Save result for postfix expressions.
1823 if (is_postfix) {
1824 old_value = register_allocator()->outer()->NewRegister();
1825 builder()->StoreAccumulatorInRegister(old_value);
1826 }
1827
1828 // Perform +1/-1 operation.
1829 builder()->CountOperation(expr->binary_op(), language_mode_strength());
1830
1831 // Store the value.
1832 FeedbackVectorSlot feedback_slot = expr->CountSlot();
1833 switch (assign_type) {
1834 case VARIABLE: {
1835 Variable* variable = expr->expression()->AsVariableProxy()->var();
1836 VisitVariableAssignment(variable, feedback_slot);
1837 break;
1838 }
1839 case NAMED_PROPERTY: {
1840 builder()->StoreNamedProperty(obj, name, feedback_index(feedback_slot),
1841 language_mode());
1842 break;
1843 }
1844 case KEYED_PROPERTY: {
1845 builder()->StoreKeyedProperty(obj, key, feedback_index(feedback_slot),
1846 language_mode());
1847 break;
1848 }
1849 case NAMED_SUPER_PROPERTY:
1850 case KEYED_SUPER_PROPERTY:
1851 UNIMPLEMENTED();
1852 }
1853
1854 // Restore old value for postfix expressions.
1855 if (is_postfix) {
1856 execution_result()->SetResultInRegister(old_value);
1857 } else {
1858 execution_result()->SetResultInAccumulator();
1859 }
1860}
1861
1862
1863void BytecodeGenerator::VisitBinaryOperation(BinaryOperation* binop) {
1864 switch (binop->op()) {
1865 case Token::COMMA:
1866 VisitCommaExpression(binop);
1867 break;
1868 case Token::OR:
1869 VisitLogicalOrExpression(binop);
1870 break;
1871 case Token::AND:
1872 VisitLogicalAndExpression(binop);
1873 break;
1874 default:
1875 VisitArithmeticExpression(binop);
1876 break;
1877 }
1878}
1879
1880
1881void BytecodeGenerator::VisitCompareOperation(CompareOperation* expr) {
1882 Register lhs = VisitForRegisterValue(expr->left());
1883 VisitForAccumulatorValue(expr->right());
1884 builder()->CompareOperation(expr->op(), lhs, language_mode_strength());
1885 execution_result()->SetResultInAccumulator();
1886}
1887
1888
1889void BytecodeGenerator::VisitArithmeticExpression(BinaryOperation* expr) {
1890 Register lhs = VisitForRegisterValue(expr->left());
1891 VisitForAccumulatorValue(expr->right());
1892 builder()->BinaryOperation(expr->op(), lhs, language_mode_strength());
1893 execution_result()->SetResultInAccumulator();
1894}
1895
1896
1897void BytecodeGenerator::VisitSpread(Spread* expr) { UNREACHABLE(); }
1898
1899
1900void BytecodeGenerator::VisitEmptyParentheses(EmptyParentheses* expr) {
1901 UNREACHABLE();
1902}
1903
1904
1905void BytecodeGenerator::VisitThisFunction(ThisFunction* expr) {
1906 execution_result()->SetResultInRegister(Register::function_closure());
1907}
1908
1909
1910void BytecodeGenerator::VisitSuperCallReference(SuperCallReference* expr) {
1911 UNIMPLEMENTED();
1912}
1913
1914
1915void BytecodeGenerator::VisitSuperPropertyReference(
1916 SuperPropertyReference* expr) {
1917 UNIMPLEMENTED();
1918}
1919
1920
1921void BytecodeGenerator::VisitCommaExpression(BinaryOperation* binop) {
1922 VisitForEffect(binop->left());
1923 Visit(binop->right());
1924}
1925
1926
1927void BytecodeGenerator::VisitLogicalOrExpression(BinaryOperation* binop) {
1928 Expression* left = binop->left();
1929 Expression* right = binop->right();
1930
1931 // Short-circuit evaluation- If it is known that left is always true,
1932 // no need to visit right
1933 if (left->ToBooleanIsTrue()) {
1934 VisitForAccumulatorValue(left);
1935 } else {
1936 BytecodeLabel end_label;
1937 VisitForAccumulatorValue(left);
1938 builder()->JumpIfTrue(&end_label);
1939 VisitForAccumulatorValue(right);
1940 builder()->Bind(&end_label);
1941 }
1942 execution_result()->SetResultInAccumulator();
1943}
1944
1945
1946void BytecodeGenerator::VisitLogicalAndExpression(BinaryOperation* binop) {
1947 Expression* left = binop->left();
1948 Expression* right = binop->right();
1949
1950 // Short-circuit evaluation- If it is known that left is always false,
1951 // no need to visit right
1952 if (left->ToBooleanIsFalse()) {
1953 VisitForAccumulatorValue(left);
1954 } else {
1955 BytecodeLabel end_label;
1956 VisitForAccumulatorValue(left);
1957 builder()->JumpIfFalse(&end_label);
1958 VisitForAccumulatorValue(right);
1959 builder()->Bind(&end_label);
1960 }
1961 execution_result()->SetResultInAccumulator();
1962}
1963
1964
1965void BytecodeGenerator::VisitRewritableAssignmentExpression(
1966 RewritableAssignmentExpression* expr) {
1967 Visit(expr->expression());
1968}
1969
1970
1971void BytecodeGenerator::VisitNewLocalFunctionContext() {
1972 AccumulatorResultScope accumulator_execution_result(this);
1973 Scope* scope = this->scope();
1974
1975 // Allocate a new local context.
1976 if (scope->is_script_scope()) {
1977 RegisterAllocationScope register_scope(this);
1978 Register closure = register_allocator()->NewRegister();
1979 Register scope_info = register_allocator()->NewRegister();
1980 DCHECK(Register::AreContiguous(closure, scope_info));
1981 builder()
1982 ->LoadAccumulatorWithRegister(Register::function_closure())
1983 .StoreAccumulatorInRegister(closure)
1984 .LoadLiteral(scope->GetScopeInfo(isolate()))
1985 .StoreAccumulatorInRegister(scope_info)
1986 .CallRuntime(Runtime::kNewScriptContext, closure, 2);
1987 } else {
1988 builder()->CallRuntime(Runtime::kNewFunctionContext,
1989 Register::function_closure(), 1);
1990 }
1991 execution_result()->SetResultInAccumulator();
1992}
1993
1994
1995void BytecodeGenerator::VisitBuildLocalActivationContext() {
1996 Scope* scope = this->scope();
1997
1998 if (scope->has_this_declaration() && scope->receiver()->IsContextSlot()) {
1999 Variable* variable = scope->receiver();
2000 Register receiver(builder()->Parameter(0));
2001 // Context variable (at bottom of the context chain).
2002 DCHECK_EQ(0, scope->ContextChainLength(variable->scope()));
2003 builder()->LoadAccumulatorWithRegister(receiver).StoreContextSlot(
2004 execution_context()->reg(), variable->index());
2005 }
2006
2007 // Copy parameters into context if necessary.
2008 int num_parameters = scope->num_parameters();
2009 for (int i = 0; i < num_parameters; i++) {
2010 Variable* variable = scope->parameter(i);
2011 if (!variable->IsContextSlot()) continue;
2012
2013 // The parameter indices are shifted by 1 (receiver is variable
2014 // index -1 but is parameter index 0 in BytecodeArrayBuilder).
2015 Register parameter(builder()->Parameter(i + 1));
2016 // Context variable (at bottom of the context chain).
2017 DCHECK_EQ(0, scope->ContextChainLength(variable->scope()));
2018 builder()->LoadAccumulatorWithRegister(parameter)
2019 .StoreContextSlot(execution_context()->reg(), variable->index());
2020 }
2021}
2022
2023
2024void BytecodeGenerator::VisitNewLocalBlockContext(Scope* scope) {
2025 AccumulatorResultScope accumulator_execution_result(this);
2026 DCHECK(scope->is_block_scope());
2027
2028 // Allocate a new local block context.
2029 register_allocator()->PrepareForConsecutiveAllocations(2);
2030 Register scope_info = register_allocator()->NextConsecutiveRegister();
2031 Register closure = register_allocator()->NextConsecutiveRegister();
2032
2033 builder()
2034 ->LoadLiteral(scope->GetScopeInfo(isolate()))
2035 .StoreAccumulatorInRegister(scope_info);
2036 VisitFunctionClosureForContext();
2037 builder()
2038 ->StoreAccumulatorInRegister(closure)
2039 .CallRuntime(Runtime::kPushBlockContext, scope_info, 2);
2040 execution_result()->SetResultInAccumulator();
2041}
2042
2043
2044void BytecodeGenerator::VisitObjectLiteralAccessor(
2045 Register home_object, ObjectLiteralProperty* property, Register value_out) {
2046 // TODO(rmcilroy): Replace value_out with VisitForRegister();
2047 if (property == nullptr) {
2048 builder()->LoadNull().StoreAccumulatorInRegister(value_out);
2049 } else {
2050 VisitForAccumulatorValue(property->value());
2051 builder()->StoreAccumulatorInRegister(value_out);
2052 VisitSetHomeObject(value_out, home_object, property);
2053 }
2054}
2055
2056
2057void BytecodeGenerator::VisitSetHomeObject(Register value, Register home_object,
2058 ObjectLiteralProperty* property,
2059 int slot_number) {
2060 Expression* expr = property->value();
2061 if (!FunctionLiteral::NeedsHomeObject(expr)) return;
2062
2063 UNIMPLEMENTED();
2064}
2065
2066
2067void BytecodeGenerator::VisitArgumentsObject(Variable* variable) {
2068 if (variable == nullptr) return;
2069
2070 DCHECK(variable->IsContextSlot() || variable->IsStackAllocated());
2071
2072 // Allocate and initialize a new arguments object and assign to the
2073 // {arguments} variable.
2074 CreateArgumentsType type =
2075 is_strict(language_mode()) || !info()->has_simple_parameters()
2076 ? CreateArgumentsType::kUnmappedArguments
2077 : CreateArgumentsType::kMappedArguments;
2078 builder()->CreateArguments(type);
2079 VisitVariableAssignment(variable, FeedbackVectorSlot::Invalid());
2080}
2081
2082
2083void BytecodeGenerator::VisitThisFunctionVariable(Variable* variable) {
2084 if (variable == nullptr) return;
2085
2086 // TODO(rmcilroy): Remove once we have tests which exercise this code path.
2087 UNIMPLEMENTED();
2088
2089 // Store the closure we were called with in the given variable.
2090 builder()->LoadAccumulatorWithRegister(Register::function_closure());
2091 VisitVariableAssignment(variable, FeedbackVectorSlot::Invalid());
2092}
2093
2094
2095void BytecodeGenerator::VisitNewTargetVariable(Variable* variable) {
2096 if (variable == nullptr) return;
2097
2098 // Store the new target we were called with in the given variable.
2099 builder()->LoadAccumulatorWithRegister(Register::new_target());
2100 VisitVariableAssignment(variable, FeedbackVectorSlot::Invalid());
2101}
2102
2103
2104void BytecodeGenerator::VisitFunctionClosureForContext() {
2105 AccumulatorResultScope accumulator_execution_result(this);
2106 Scope* closure_scope = execution_context()->scope()->ClosureScope();
2107 if (closure_scope->is_script_scope() ||
2108 closure_scope->is_module_scope()) {
2109 // Contexts nested in the native context have a canonical empty function as
2110 // their closure, not the anonymous closure containing the global code.
2111 Register native_context = register_allocator()->NewRegister();
2112 builder()
2113 ->LoadContextSlot(execution_context()->reg(),
2114 Context::NATIVE_CONTEXT_INDEX)
2115 .StoreAccumulatorInRegister(native_context)
2116 .LoadContextSlot(native_context, Context::CLOSURE_INDEX);
2117 } else {
2118 DCHECK(closure_scope->is_function_scope());
2119 builder()->LoadAccumulatorWithRegister(Register::function_closure());
2120 }
2121 execution_result()->SetResultInAccumulator();
2122}
2123
2124
2125// Visits the expression |expr| and places the result in the accumulator.
2126void BytecodeGenerator::VisitForAccumulatorValue(Expression* expr) {
2127 AccumulatorResultScope accumulator_scope(this);
2128 Visit(expr);
2129}
2130
2131
2132// Visits the expression |expr| and discards the result.
2133void BytecodeGenerator::VisitForEffect(Expression* expr) {
2134 EffectResultScope effect_scope(this);
2135 Visit(expr);
2136}
2137
2138
2139// Visits the expression |expr| and returns the register containing
2140// the expression result.
2141Register BytecodeGenerator::VisitForRegisterValue(Expression* expr) {
2142 RegisterResultScope register_scope(this);
2143 Visit(expr);
2144 return register_scope.ResultRegister();
2145}
2146
2147
2148Register BytecodeGenerator::NextContextRegister() const {
2149 if (execution_context() == nullptr) {
2150 // Return the incoming function context for the outermost execution context.
2151 return Register::function_context();
2152 }
2153 Register previous = execution_context()->reg();
2154 if (previous == Register::function_context()) {
2155 // If the previous context was the incoming function context, then the next
2156 // context register is the first local context register.
2157 return builder_.first_context_register();
2158 } else {
2159 // Otherwise use the next local context register.
2160 DCHECK_LT(previous.index(), builder_.last_context_register().index());
2161 return Register(previous.index() + 1);
2162 }
2163}
2164
2165
2166LanguageMode BytecodeGenerator::language_mode() const {
2167 return info()->language_mode();
2168}
2169
2170
2171Strength BytecodeGenerator::language_mode_strength() const {
2172 return strength(language_mode());
2173}
2174
2175
2176int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const {
2177 return info()->feedback_vector()->GetIndex(slot);
2178}
2179
2180} // namespace interpreter
2181} // namespace internal
2182} // namespace v8