OLD | NEW |
---|---|
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/interpreter/bytecode-generator.h" | 5 #include "src/interpreter/bytecode-generator.h" |
6 | 6 |
7 #include "src/compiler.h" | 7 #include "src/compiler.h" |
8 #include "src/interpreter/control-flow-builders.h" | 8 #include "src/interpreter/control-flow-builders.h" |
9 #include "src/objects.h" | 9 #include "src/objects.h" |
10 #include "src/parser.h" | 10 #include "src/parser.h" |
(...skipping 595 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
606 } else { | 606 } else { |
607 builder()->Jump(&body_label); | 607 builder()->Jump(&body_label); |
608 } | 608 } |
609 builder()->Bind(&done_label); | 609 builder()->Bind(&done_label); |
610 | 610 |
611 loop_builder.SetBreakTarget(done_label); | 611 loop_builder.SetBreakTarget(done_label); |
612 loop_builder.SetContinueTarget(next_label); | 612 loop_builder.SetContinueTarget(next_label); |
613 } | 613 } |
614 | 614 |
615 | 615 |
616 void BytecodeGenerator::VisitForInAssignment(Expression* expr, | |
617 FeedbackVectorSlot slot) { | |
618 DCHECK(expr->IsValidReferenceExpression()); | |
619 | |
620 // Evaluate assignment starting with the value to be stored in the | |
621 // accumulator. | |
622 Property* property = expr->AsProperty(); | |
623 LhsKind assign_type = Property::GetAssignType(property); | |
624 switch (assign_type) { | |
625 case VARIABLE: { | |
626 Variable* variable = expr->AsVariableProxy()->var(); | |
627 VisitVariableAssignment(variable, slot); | |
628 break; | |
629 } | |
630 case NAMED_PROPERTY: { | |
631 TemporaryRegisterScope temporary_register_scope(builder()); | |
632 Register value = temporary_register_scope.NewRegister(); | |
633 builder()->StoreAccumulatorInRegister(value); | |
634 Register object = VisitForRegisterValue(property->obj()); | |
635 size_t name_index = builder()->GetConstantPoolEntry( | |
636 property->key()->AsLiteral()->AsPropertyName()); | |
637 builder()->StoreNamedProperty(object, name_index, feedback_index(slot), | |
638 language_mode()); | |
639 break; | |
640 } | |
641 case KEYED_PROPERTY: { | |
642 TemporaryRegisterScope temporary_register_scope(builder()); | |
643 Register value = temporary_register_scope.NewRegister(); | |
644 builder()->StoreAccumulatorInRegister(value); | |
645 Register object = VisitForRegisterValue(property->obj()); | |
646 Register key = VisitForRegisterValue(property->key()); | |
647 builder()->LoadAccumulatorWithRegister(value); | |
648 builder()->StoreKeyedProperty(object, key, feedback_index(slot), | |
649 language_mode()); | |
650 break; | |
651 } | |
652 case NAMED_SUPER_PROPERTY: | |
653 case KEYED_SUPER_PROPERTY: | |
654 UNIMPLEMENTED(); | |
655 } | |
656 } | |
657 | |
658 | |
616 void BytecodeGenerator::VisitForInStatement(ForInStatement* stmt) { | 659 void BytecodeGenerator::VisitForInStatement(ForInStatement* stmt) { |
617 UNIMPLEMENTED(); | 660 // TODO(oth): For now we need a parent scope for paths that end up |
661 // in VisitLiteral which can allocate in the parent scope. A future | |
662 // CL in preparation will a StatementResultScope that will remove | |
rmcilroy
2015/10/28 13:46:22
/s/will a Statement.../will add a Statement.../
oth
2015/10/28 22:50:40
Done.
| |
663 // the need for this EffectResultScope. | |
664 EffectResultScope result_scope(this); | |
665 | |
666 if (stmt->subject()->IsNullLiteral() || | |
667 stmt->subject()->IsUndefinedLiteral(isolate())) { | |
668 // ForIn generates lots of code, skip if it wouldn't produce any effects. | |
669 return; | |
670 } | |
671 | |
672 LoopBuilder loop_builder(builder()); | |
673 ControlScopeForIteration control_scope(this, stmt, &loop_builder); | |
674 | |
675 // Prepare the state for executing ForIn. | |
676 builder()->EnterBlock(); | |
677 VisitForAccumulatorValue(stmt->subject()); | |
678 loop_builder.BreakIfUndefined(); | |
679 loop_builder.BreakIfNull(); | |
680 | |
681 builder()->CastAccumulatorToJSObject(); | |
682 Register receiver = execution_result()->NewRegister(); | |
683 builder()->StoreAccumulatorInRegister(receiver); | |
684 builder()->CallRuntime(Runtime::kGetPropertyNamesFast, receiver, 1); | |
685 builder()->ForInPrepare(receiver); | |
686 Register for_in_state = execution_result()->NewRegister(); | |
rmcilroy
2015/10/28 13:46:22
nit - I would put Register declarations at the top
oth
2015/10/28 22:50:40
Done.
| |
687 builder() | |
688 ->StoreAccumulatorInRegister(for_in_state) | |
689 .LoadUndefined() | |
690 .CompareOperation(Token::Value::EQ_STRICT, for_in_state, | |
691 language_mode_strength()); | |
rmcilroy
2015/10/28 13:46:22
Can you use BreakIfUndefined here instead?
oth
2015/10/28 22:50:40
Done.
| |
692 loop_builder.BreakIfTrue(); | |
693 | |
694 // The loop. | |
695 BytecodeLabel condition_label, break_label, continue_label; | |
696 Register index = receiver; // re-using register as receiver no longer used. | |
rmcilroy
2015/10/28 13:46:22
nit - /s/re/Re
oth
2015/10/28 22:50:40
Done.
| |
697 builder()->LoadLiteral(Smi::FromInt(0)); | |
698 | |
699 // Check loop termination (accumulator holds index). | |
700 builder() | |
701 ->Bind(&condition_label) | |
702 .StoreAccumulatorInRegister(index) | |
703 .ForInDone(for_in_state); | |
704 loop_builder.BreakIfTrue(); | |
705 | |
706 // Get the next item. | |
707 builder()->LoadAccumulatorWithRegister(index).ForInNext(for_in_state); | |
rmcilroy
2015/10/28 13:46:22
nit - could you require ForInNext to take a regist
oth
2015/10/28 22:50:40
Done.
| |
708 | |
709 // Start again if the item, currently in the accumulator, is undefined. | |
710 loop_builder.ContinueIfUndefined(); | |
711 | |
712 // Store the value in the each variable. | |
713 VisitForInAssignment(stmt->each(), stmt->EachFeedbackSlot()); | |
714 // NB the user's loop variable will be assigned the value of each so | |
715 // even an empty body will have this assignment. | |
716 Visit(stmt->body()); | |
rmcilroy
2015/10/28 13:46:22
VisitForEffect?
oth
2015/10/28 22:50:40
stmt->body() is a statement rather than expression
rmcilroy
2015/10/29 10:53:45
Acknowledged.
| |
717 | |
718 // Increment the index and start loop again. | |
719 builder() | |
720 ->Bind(&continue_label) | |
721 .LoadAccumulatorWithRegister(index) | |
722 .CountOperation(Token::Value::ADD, language_mode_strength()) | |
723 .Jump(&condition_label); | |
724 | |
725 // End of loop | |
726 builder()->Bind(&break_label).LeaveBlock(); | |
727 | |
728 loop_builder.SetBreakTarget(break_label); | |
729 loop_builder.SetContinueTarget(continue_label); | |
618 } | 730 } |
619 | 731 |
620 | 732 |
621 void BytecodeGenerator::VisitForOfStatement(ForOfStatement* stmt) { | 733 void BytecodeGenerator::VisitForOfStatement(ForOfStatement* stmt) { |
622 UNIMPLEMENTED(); | 734 UNIMPLEMENTED(); |
623 } | 735 } |
624 | 736 |
625 | 737 |
626 void BytecodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) { | 738 void BytecodeGenerator::VisitTryCatchStatement(TryCatchStatement* stmt) { |
627 if (FLAG_ignition_fake_try_catch) { | 739 if (FLAG_ignition_fake_try_catch) { |
(...skipping 1319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1947 } | 2059 } |
1948 | 2060 |
1949 | 2061 |
1950 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { | 2062 int BytecodeGenerator::feedback_index(FeedbackVectorSlot slot) const { |
1951 return info()->feedback_vector()->GetIndex(slot); | 2063 return info()->feedback_vector()->GetIndex(slot); |
1952 } | 2064 } |
1953 | 2065 |
1954 } // namespace interpreter | 2066 } // namespace interpreter |
1955 } // namespace internal | 2067 } // namespace internal |
1956 } // namespace v8 | 2068 } // namespace v8 |
OLD | NEW |